Skip to content

Commit be9b287

Browse files
authored
Merge pull request #6 from brick/v0.2
2 parents 3bb8914 + 5186139 commit be9b287

File tree

13 files changed

+259
-103
lines changed

13 files changed

+259
-103
lines changed

.github/workflows/ci.yml

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,33 @@ name: CI
22

33
on:
44
push:
5+
branches: [master]
56
pull_request:
67

78
env:
8-
COVERAGE_PHP_VERSION: "8.3"
9+
PSALM_PHP_VERSION: "8.4"
10+
COVERAGE_PHP_VERSION: "8.4"
911

1012
jobs:
13+
psalm:
14+
name: Psalm
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Setup PHP
22+
uses: shivammathur/setup-php@v2
23+
with:
24+
php-version: ${{ env.PSALM_PHP_VERSION }}
25+
26+
- name: Install composer dependencies
27+
uses: ramsey/composer-install@v3
28+
29+
- name: Run Psalm
30+
run: vendor/bin/psalm --no-progress
31+
1132
phpunit:
1233
name: PHPUnit
1334
runs-on: ubuntu-latest
@@ -16,17 +37,14 @@ jobs:
1637
fail-fast: false
1738
matrix:
1839
php-version:
19-
- "7.2"
20-
- "7.3"
21-
- "7.4"
22-
- "8.0"
2340
- "8.1"
2441
- "8.2"
2542
- "8.3"
43+
- "8.4"
2644
deps:
2745
- "highest"
2846
include:
29-
- php-version: "7.2"
47+
- php-version: "8.1"
3048
deps: "lowest"
3149

3250
steps:

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ composer require brick/structured-data
2222

2323
### Requirements
2424

25-
This library requires PHP 7.2 or later. It makes use of the following extensions:
25+
This library requires PHP 8.1 or later. It makes use of the following extensions:
2626

2727
- [dom](https://www.php.net/manual/en/book.dom.php)
2828
- [json](https://www.php.net/manual/en/book.json.php)
@@ -39,7 +39,7 @@ optimizing existing code, etc.), `y` is incremented.
3939

4040
**When a breaking change is introduced, a new `0.x` version cycle is always started.**
4141

42-
It is therefore safe to lock your project to a given release cycle, such as `0.1.*`.
42+
It is therefore safe to lock your project to a given release cycle, such as `0.2.*`.
4343

4444
If you need to upgrade to a newer release cycle, check the [release history](https://github.com/brick/structured-data/releases)
4545
for a list of changes introduced by each further `0.x.0` version.

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@
1111
],
1212
"license": "MIT",
1313
"require": {
14-
"php": "^7.2 || ^8.0",
14+
"php": "^8.1",
1515
"ext-dom": "*",
1616
"ext-json": "*",
1717
"ext-libxml": "*",
18-
"sabre/uri": "^2.1"
18+
"sabre/uri": "^2.1 || ^3.0"
1919
},
2020
"require-dev": {
2121
"phpunit/phpunit": "^8.0 || ^9.0",
22-
"php-coveralls/php-coveralls": "^2.0"
22+
"php-coveralls/php-coveralls": "^2.0",
23+
"vimeo/psalm": "6.12.0"
2324
},
2425
"autoload": {
2526
"psr-4": {

psalm-baseline.xml

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<files psalm-version="6.12.0@cf420941d061a57050b6c468ef2c778faf40aee2">
3+
<file src="src/Reader/JsonLdReader.php">
4+
<ArgumentTypeCoercion>
5+
<code><![CDATA[$data]]></code>
6+
<code><![CDATA[$item]]></code>
7+
<code><![CDATA[$value]]></code>
8+
</ArgumentTypeCoercion>
9+
<DocblockTypeContradiction>
10+
<code><![CDATA[is_string($type)]]></code>
11+
</DocblockTypeContradiction>
12+
<MissingClosureParamType>
13+
<code><![CDATA[$a]]></code>
14+
</MissingClosureParamType>
15+
<MixedArgument>
16+
<code><![CDATA[$name]]></code>
17+
</MixedArgument>
18+
<MixedArrayAccess>
19+
<code><![CDATA[$name[0]]]></code>
20+
</MixedArrayAccess>
21+
<PossiblyInvalidArgument>
22+
<code><![CDATA[fn(DOMNode $node) => $this->readJson($node->textContent, $url)]]></code>
23+
</PossiblyInvalidArgument>
24+
<RawObjectIteration>
25+
<code><![CDATA[$item]]></code>
26+
</RawObjectIteration>
27+
<RedundantConditionGivenDocblockType>
28+
<code><![CDATA[null]]></code>
29+
</RedundantConditionGivenDocblockType>
30+
</file>
31+
<file src="src/Reader/MicrodataReader.php">
32+
<InvalidArgument>
33+
<code><![CDATA[function(DOMNode $itemprop) use ($node, $xpath) {
34+
for (;;) {
35+
$itemprop = $itemprop->parentNode;
36+
37+
if ($itemprop->isSameNode($node)) {
38+
return true;
39+
}
40+
41+
if ($itemprop->attributes->getNamedItem('itemscope')) {
42+
return false;
43+
}
44+
}
45+
}]]></code>
46+
</InvalidArgument>
47+
<PossiblyInvalidArgument>
48+
<code><![CDATA[fn(DOMNode $node) => $this->nodeToItem($node, $xpath, $url)]]></code>
49+
<code><![CDATA[function(DOMNode $itemprop) use ($node, $xpath) {
50+
for (;;) {
51+
$itemprop = $itemprop->parentNode;
52+
53+
if ($itemprop->isSameNode($node)) {
54+
return true;
55+
}
56+
57+
if ($itemprop->attributes->getNamedItem('itemscope')) {
58+
return false;
59+
}
60+
}
61+
}]]></code>
62+
</PossiblyInvalidArgument>
63+
<PossiblyNullArgument>
64+
<code><![CDATA[$names]]></code>
65+
<code><![CDATA[preg_replace('/\s+/', ' ', $node->textContent)]]></code>
66+
</PossiblyNullArgument>
67+
<PossiblyNullPropertyFetch>
68+
<code><![CDATA[$itemprop->attributes->getNamedItem('itemprop')->textContent]]></code>
69+
</PossiblyNullPropertyFetch>
70+
<PossiblyNullReference>
71+
<code><![CDATA[getNamedItem]]></code>
72+
<code><![CDATA[getNamedItem]]></code>
73+
<code><![CDATA[getNamedItem]]></code>
74+
<code><![CDATA[getNamedItem]]></code>
75+
<code><![CDATA[isSameNode]]></code>
76+
</PossiblyNullReference>
77+
</file>
78+
<file src="src/Reader/RdfaLiteReader.php">
79+
<InvalidArgument>
80+
<code><![CDATA[function(DOMNode $itemprop) use ($node, $xpath) {
81+
for (;;) {
82+
$itemprop = $itemprop->parentNode;
83+
84+
if ($itemprop->isSameNode($node)) {
85+
return true;
86+
}
87+
88+
if ($itemprop->attributes->getNamedItem('typeof')) {
89+
return false;
90+
}
91+
}
92+
93+
// Unreachable, but makes static analysis happy
94+
return false;
95+
}]]></code>
96+
</InvalidArgument>
97+
<PossiblyInvalidArgument>
98+
<code><![CDATA[fn(DOMNode $node) => $this->nodeToItem($node, $xpath, $url, self::PREDEFINED_PREFIXES, null)]]></code>
99+
<code><![CDATA[function(DOMNode $itemprop) use ($node, $xpath) {
100+
for (;;) {
101+
$itemprop = $itemprop->parentNode;
102+
103+
if ($itemprop->isSameNode($node)) {
104+
return true;
105+
}
106+
107+
if ($itemprop->attributes->getNamedItem('typeof')) {
108+
return false;
109+
}
110+
}
111+
112+
// Unreachable, but makes static analysis happy
113+
return false;
114+
}]]></code>
115+
</PossiblyInvalidArgument>
116+
<PossiblyNullArgument>
117+
<code><![CDATA[$names]]></code>
118+
<code><![CDATA[$typeof->textContent]]></code>
119+
<code><![CDATA[preg_replace('/\s+/', ' ', $node->textContent)]]></code>
120+
</PossiblyNullArgument>
121+
<PossiblyNullPropertyFetch>
122+
<code><![CDATA[$property->attributes->getNamedItem('property')->textContent]]></code>
123+
<code><![CDATA[$typeof->textContent]]></code>
124+
</PossiblyNullPropertyFetch>
125+
<PossiblyNullReference>
126+
<code><![CDATA[getNamedItem]]></code>
127+
<code><![CDATA[getNamedItem]]></code>
128+
<code><![CDATA[getNamedItem]]></code>
129+
<code><![CDATA[getNamedItem]]></code>
130+
<code><![CDATA[getNamedItem]]></code>
131+
<code><![CDATA[isSameNode]]></code>
132+
</PossiblyNullReference>
133+
</file>
134+
</files>

psalm.xml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0"?>
2+
<psalm
3+
errorLevel="1"
4+
resolveFromConfigFile="true"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xmlns="https://getpsalm.org/schema/config"
7+
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
8+
findUnusedBaselineEntry="true"
9+
findUnusedPsalmSuppress="true"
10+
findUnusedCode="false"
11+
errorBaseline="psalm-baseline.xml"
12+
>
13+
<projectFiles>
14+
<directory name="src" />
15+
<ignoreFiles>
16+
<directory name="vendor" />
17+
</ignoreFiles>
18+
</projectFiles>
19+
20+
<issueHandlers>
21+
<MixedAssignment errorLevel="suppress" />
22+
</issueHandlers>
23+
</psalm>

src/DOMBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
use DOMDocument;
88

9-
class DOMBuilder
9+
final class DOMBuilder
1010
{
1111
/**
1212
* Builds a DOMDocument from an HTML string.

src/HTMLReader.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@
44

55
namespace Brick\StructuredData;
66

7-
class HTMLReader
7+
final class HTMLReader
88
{
9-
/**
10-
* @var Reader
11-
*/
12-
private $reader;
9+
private readonly Reader $reader;
1310

1411
/**
1512
* HTMLReader constructor.

src/Item.php

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,29 @@
44

55
namespace Brick\StructuredData;
66

7-
use TypeError;
8-
97
/**
108
* An item, such as a Thing in schema.org's vocabulary.
119
*/
12-
class Item
10+
final class Item
1311
{
1412
/**
1513
* The global identifier of the item, if any.
16-
*
17-
* @var string|null
1814
*/
19-
private $id;
15+
private readonly ?string $id;
2016

2117
/**
2218
* The types this Item implements, as URLs.
2319
*
24-
* @var array<string>
20+
* @var string[]
2521
*/
26-
private $types;
22+
private readonly array $types;
2723

2824
/**
2925
* The properties, as a map of property name to list of values.
3026
*
3127
* @var array<string, array<Item|string>>
3228
*/
33-
private $properties = [];
29+
private array $properties = [];
3430

3531
/**
3632
* Item constructor.
@@ -57,9 +53,9 @@ public function getId() : ?string
5753
/**
5854
* Returns the list of types this Item implements.
5955
*
60-
* Each type is a represented as a URL, e.g. http://schema.org/Product .
56+
* Each type is represented as a URL, e.g. http://schema.org/Product .
6157
*
62-
* @return array<string>
58+
* @return string[]
6359
*/
6460
public function getTypes() : array
6561
{
@@ -100,12 +96,8 @@ public function getProperty(string $name) : array
10096
*
10197
* @return void
10298
*/
103-
public function addProperty(string $name, $value) : void
99+
public function addProperty(string $name, Item|string $value) : void
104100
{
105-
if (! $value instanceof Item && ! is_string($value)) {
106-
throw new TypeError(sprintf('Property value must be an instance of %s or a string.', Item::class));
107-
}
108-
109101
$this->properties[$name][] = $value;
110102
}
111103
}

src/JsonLdWriter.php

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/**
88
* Exports Items to JSON-LD.
99
*/
10-
class JsonLdWriter
10+
final class JsonLdWriter
1111
{
1212
/**
1313
* Exports a list of Items as JSON-LD.
@@ -18,11 +18,12 @@ class JsonLdWriter
1818
*/
1919
public function write(Item ...$items) : string
2020
{
21-
$items = array_map(function(Item $item) {
22-
return $this->convertItem($item);
23-
}, $items);
21+
$items = array_map(
22+
fn(Item $item) => $this->convertItem($item),
23+
$items,
24+
);
2425

25-
return json_encode($this->extractIfSingle($items), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
26+
return json_encode($this->extractIfSingle($items), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
2627
}
2728

2829
/**
@@ -62,7 +63,7 @@ private function convertItem(Item $item) : array
6263
*
6364
* @return mixed
6465
*/
65-
private function extractIfSingle(array $values)
66+
private function extractIfSingle(array $values) : mixed
6667
{
6768
if (count($values) === 1) {
6869
return $values[0];

0 commit comments

Comments
 (0)