From ccc356d22a2d9eb4dedd6fa6a5031b4c7ae665ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vasilj=20Milo=C5=A1evi=C4=87?= Date: Fri, 25 Feb 2022 01:40:31 +0100 Subject: [PATCH 1/6] PHP8.1 compatibility --- composer.json | 5 +++-- src/MicrodataDOMDocument.php | 14 ++++++++------ src/MicrodataDOMElement.php | 31 +++++++++++++++++-------------- src/MicrodataParser.php | 31 +++++++++++++++++-------------- tests/MicrodataParserTest.php | 17 ++++++++++++++--- tests/MicrodataTest.php | 8 +++++--- 6 files changed, 64 insertions(+), 42 deletions(-) diff --git a/composer.json b/composer.json index 6b46a9f..c79d646 100644 --- a/composer.json +++ b/composer.json @@ -20,8 +20,9 @@ } ], "require": { - "php" : "~7.0", - "ext-dom": "*" + "php" : "~8.1", + "ext-dom": "*", + "ext-libxml": "*" }, "require-dev": { "phpunit/phpunit" : ">=5.4.3", diff --git a/src/MicrodataDOMDocument.php b/src/MicrodataDOMDocument.php index bf3c47d..0675f5a 100644 --- a/src/MicrodataDOMDocument.php +++ b/src/MicrodataDOMDocument.php @@ -2,10 +2,12 @@ namespace YusufKandemir\MicrodataParser; +use DOMXPath; + class MicrodataDOMDocument extends \DOMDocument { - /** @var \DOMXPath */ - public $xpath; + /** @var DOMXPath */ + public DOMXPath $xpath; /** * Get top-level items of the document @@ -23,11 +25,11 @@ public function getItems() : \DOMNodeList * {@inheritdoc} * Also assigns $xpath with DOMXPath of freshly loaded DOMDocument */ - public function loadHTML($source, $options = 0) + public function loadHTML($source, $options = 0): \DOMDocument|bool { $return = parent::loadHTML($source, $options); - $this->xpath = new \DOMXPath($this); + $this->xpath = new DOMXPath($this); return $return; } @@ -36,11 +38,11 @@ public function loadHTML($source, $options = 0) * {@inheritdoc} * Also assigns $xpath with DOMXPath of freshly loaded DOMDocument */ - public function loadHTMLFile($filename, $options = 0) + public function loadHTMLFile($filename, $options = 0): \DOMDocument|bool { $return = parent::loadHTMLFile($filename, $options); - $this->xpath = new \DOMXPath($this); + $this->xpath = new DOMXPath($this); return $return; } diff --git a/src/MicrodataDOMElement.php b/src/MicrodataDOMElement.php index d5acdb0..849e7d3 100644 --- a/src/MicrodataDOMElement.php +++ b/src/MicrodataDOMElement.php @@ -2,10 +2,13 @@ namespace YusufKandemir\MicrodataParser; +use function array_key_exists; +use function in_array; + class MicrodataDOMElement extends \DOMElement { /** @var array "tag name" to "attribute name" mapping */ - private static $tagNameLookup = [ + private static array $tagNameLookup = [ 'audio' => 'src', 'embed' => 'src', 'iframe' => 'src', @@ -23,7 +26,7 @@ class MicrodataDOMElement extends \DOMElement ]; /** @var array Attributes that have absolute values */ - private static $absoluteAttributes = ['src', 'href', 'data',]; + private static array $absoluteAttributes = ['src', 'href', 'data',]; /** * @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-item-properties for details of algorithm @@ -94,11 +97,11 @@ public function getPropertyNames() : array /** * @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-property-value for details of algorithm * - * @param callable $absoluteUriHandler + * @param callable|null $absoluteUriHandler * * @return $this|string */ - public function getPropertyValue(callable $absoluteUriHandler = null) + public function getPropertyValue(callable $absoluteUriHandler = null): string|static { if ($this->hasAttribute('itemscope')) { return $this; @@ -110,11 +113,11 @@ public function getPropertyValue(callable $absoluteUriHandler = null) $value = ''; - if (\array_key_exists($this->tagName, self::$tagNameLookup)) { + if (array_key_exists($this->tagName, self::$tagNameLookup)) { $attribute = self::$tagNameLookup[$this->tagName]; $value = $this->getAttribute($attribute); - if (!empty($value) && \in_array($attribute, self::$absoluteAttributes) && !$this->isAbsoluteUri($value)) { + if (!empty($value) && in_array($attribute, self::$absoluteAttributes) && !$this->isAbsoluteUri($value)) { $value = $absoluteUriHandler($value, $this->ownerDocument->documentURI); } } @@ -132,7 +135,7 @@ public function getPropertyValue(callable $absoluteUriHandler = null) * * @return false|int */ - protected function isAbsoluteUri(string $uri) + protected function isAbsoluteUri(string $uri): bool|int { return preg_match("/^\w+:/", trim($uri)); } @@ -142,7 +145,7 @@ protected function isAbsoluteUri(string $uri) * * @return array Result array which contains child ElementNodes */ - protected function getChildElementNodes() + protected function getChildElementNodes(): array { $childNodes = []; @@ -160,9 +163,9 @@ protected function getChildElementNodes() * * @param string $attributeName Name of the attribute * - * @return array|array[]|false|string[] + * @return array|bool */ - public function tokenizeAttribute(string $attributeName) + public function tokenizeAttribute(string $attributeName): array|bool { $attribute = []; @@ -176,15 +179,15 @@ public function tokenizeAttribute(string $attributeName) /** * Splits given attribute value in space characters to array * + * @param string $attribute + * + * @return array|bool * @see \preg_split() for possible return values and behaviour * * @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-split-a-string-on-spaces for definition of tokens * - * @param string $attribute - * - * @return array[]|false|string[] */ - protected function tokenize(string $attribute) + protected function tokenize(string $attribute): array|bool { return preg_split('/\s+/', trim($attribute)); } diff --git a/src/MicrodataParser.php b/src/MicrodataParser.php index 262ec98..0b23bac 100644 --- a/src/MicrodataParser.php +++ b/src/MicrodataParser.php @@ -2,10 +2,13 @@ namespace YusufKandemir\MicrodataParser; +use DOMElement; +use stdClass; + class MicrodataParser { /** @var MicrodataDOMDocument */ - protected $dom; + protected MicrodataDOMDocument $dom; /** * Handler will be called with $value(non-absolute uri string) and $base(base uri) parameters @@ -26,7 +29,7 @@ class MicrodataParser */ public function __construct(MicrodataDOMDocument $dom, callable $absoluteUriHandler = null) { - $dom->registerNodeClass(\DOMElement::class, MicrodataDOMElement::class); + $dom->registerNodeClass(DOMElement::class, MicrodataDOMElement::class); $this->dom = $dom; $this->absoluteUriHandler = $absoluteUriHandler ?: function ($value, $base) { @@ -48,9 +51,9 @@ public function toArray() : array /** * Extracts and converts microdata to object * - * @return \stdClass + * @return stdClass */ - public function toObject() : \stdClass + public function toObject() : stdClass { return $this->extractMicrodata(); } @@ -58,24 +61,24 @@ public function toObject() : \stdClass /** * Extracts and converts microdata to json using \json_encode() * - * @see \json_encode() to description of parameters and return values - * * @param int $options * @param int $depth * * @return false|string + *@see \json_encode() to description of parameters and return values + * */ - public function toJSON($options = 0, $depth = 512) + public function toJSON(int $options = 0, int $depth = 512): bool|string { return json_encode($this->extractMicrodata(), $options, $depth); } /** - * @return \stdClass + * @return stdClass */ - protected function extractMicrodata() : \stdClass + protected function extractMicrodata() : stdClass { - $result = new \stdClass; + $result = new stdClass; $result->items = []; @@ -92,11 +95,11 @@ protected function extractMicrodata() : \stdClass * @param MicrodataDOMElement $item * @param array $memory * - * @return \stdClass + * @return stdClass */ - protected function getObject(MicrodataDOMElement $item, $memory = []) : \stdClass + protected function getObject(MicrodataDOMElement $item, array $memory = []) : stdClass { - $result = new \stdClass; + $result = new stdClass; $memory[] = $item; @@ -108,7 +111,7 @@ protected function getObject(MicrodataDOMElement $item, $memory = []) : \stdClas } // @todo Check if item ids are valid absolute urls or like isbn:xxx - $properties = new \stdClass; + $properties = new stdClass; foreach ($item->getProperties() as $element) { $value = $element->getPropertyValue($this->absoluteUriHandler); diff --git a/tests/MicrodataParserTest.php b/tests/MicrodataParserTest.php index d9c4480..621e17e 100644 --- a/tests/MicrodataParserTest.php +++ b/tests/MicrodataParserTest.php @@ -2,6 +2,7 @@ namespace YusufKandemir\MicrodataParser\Tests; +use JetBrains\PhpStorm\ArrayShape; use YusufKandemir\MicrodataParser\MicrodataDOMDocument; use YusufKandemir\MicrodataParser\MicrodataParser; @@ -12,7 +13,7 @@ protected function setUp() libxml_use_internal_errors(true); // Ignore warnings of DOMDocument::loadHTML check } - protected function getParser($data) + protected function getParser($data): MicrodataParser { $dom = new MicrodataDOMDocument; $dom->loadHTML($data['source']); @@ -83,7 +84,12 @@ function (string $value, string $base) use ($baseUri) : string { /** * @todo Provide more test data */ - public function data() + #[ArrayShape([ + 'W3C Example' => "array[]", + 'Itemref & src based tags' => "array[]", + 'Object & Data tags' => "array[]", + 'Itemid & Content attributes' => "array[]"])] + public function data(): array { return [ // https://www.w3.org/TR/microdata/#ex-jsonconv @@ -102,7 +108,12 @@ public function data() ]; } - private function getTestData($folderName, $sourceName, $resultName) + #[ArrayShape([ + 'uri' => "mixed|string", + 'source' => "false|string", + 'result' => "false|string" + ])] + private function getTestData($folderName, $sourceName, $resultName): array { $folderPath = __DIR__.'/data/'.$folderName.'/'; diff --git a/tests/MicrodataTest.php b/tests/MicrodataTest.php index d3a9aec..b33cc77 100644 --- a/tests/MicrodataTest.php +++ b/tests/MicrodataTest.php @@ -2,12 +2,14 @@ namespace YusufKandemir\MicrodataParser\Tests; +use DOMDocument; +use PHPUnit\Framework\TestCase; use YusufKandemir\MicrodataParser\Microdata; use YusufKandemir\MicrodataParser\MicrodataParser; -class MicrodataTest extends \PHPUnit\Framework\TestCase +class MicrodataTest extends TestCase { - protected $htmlFileName = __DIR__ . '/data/W3C/source.html'; + protected string $htmlFileName = __DIR__ . '/data/W3C/source.html'; public function testItCreatesMicrodataParserFromHtml() { @@ -26,7 +28,7 @@ public function testItCreatesMicrodataParserFromHtmlFile() public function testItCreatesMicrodataParserFromDomDocument() { - $dom = new \DOMDocument; + $dom = new DOMDocument; $dom->loadHTMLFile($this->htmlFileName); $microdata = Microdata::fromDOMDocument($dom); From 8aa72b29a18f03a547adaba33b15635aeac03f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vasilj=20Milo=C5=A1evi=C4=87?= Date: Fri, 25 Feb 2022 01:41:57 +0100 Subject: [PATCH 2/6] PHP8.1 compatibility --- tests/MicrodataParserTest.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/MicrodataParserTest.php b/tests/MicrodataParserTest.php index 621e17e..b96cd80 100644 --- a/tests/MicrodataParserTest.php +++ b/tests/MicrodataParserTest.php @@ -3,12 +3,16 @@ namespace YusufKandemir\MicrodataParser\Tests; use JetBrains\PhpStorm\ArrayShape; +use PHPUnit\Framework\TestCase; use YusufKandemir\MicrodataParser\MicrodataDOMDocument; use YusufKandemir\MicrodataParser\MicrodataParser; -class MicrodataParserTest extends \PHPUnit\Framework\TestCase +class MicrodataParserTest extends TestCase { - protected function setUp() + /** + * @return void + */ + protected function setUp() :void { libxml_use_internal_errors(true); // Ignore warnings of DOMDocument::loadHTML check } From 92811dd44db83600101c9545667fa3b581c42597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vasilj=20Milo=C5=A1evi=C4=87?= Date: Fri, 25 Feb 2022 01:42:23 +0100 Subject: [PATCH 3/6] add idea to ignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a064c15..1c81cdc 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ build composer.lock vendor phpcs.xml -phpunit.xml \ No newline at end of file +phpunit.xml +.idea From 1a97014a3ee96ce8d8c74f9a483abcb48bfa5165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vasilj=20Milo=C5=A1evi=C4=87?= Date: Sun, 27 Feb 2022 03:01:03 +0100 Subject: [PATCH 4/6] apply suggested changes for PHP8 --- src/MicrodataDOMDocument.php | 8 ++++---- src/MicrodataDOMElement.php | 4 ++-- src/MicrodataParser.php | 3 +-- tests/MicrodataParserTest.php | 16 +++++++--------- tests/MicrodataTest.php | 3 +-- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/MicrodataDOMDocument.php b/src/MicrodataDOMDocument.php index 0675f5a..c590cc3 100644 --- a/src/MicrodataDOMDocument.php +++ b/src/MicrodataDOMDocument.php @@ -2,11 +2,11 @@ namespace YusufKandemir\MicrodataParser; +use DOMDocument; use DOMXPath; -class MicrodataDOMDocument extends \DOMDocument +class MicrodataDOMDocument extends DOMDocument { - /** @var DOMXPath */ public DOMXPath $xpath; /** @@ -25,7 +25,7 @@ public function getItems() : \DOMNodeList * {@inheritdoc} * Also assigns $xpath with DOMXPath of freshly loaded DOMDocument */ - public function loadHTML($source, $options = 0): \DOMDocument|bool + public function loadHTML($source, $options = 0): DOMDocument|bool { $return = parent::loadHTML($source, $options); @@ -38,7 +38,7 @@ public function loadHTML($source, $options = 0): \DOMDocument|bool * {@inheritdoc} * Also assigns $xpath with DOMXPath of freshly loaded DOMDocument */ - public function loadHTMLFile($filename, $options = 0): \DOMDocument|bool + public function loadHTMLFile($filename, $options = 0): DOMDocument|bool { $return = parent::loadHTMLFile($filename, $options); diff --git a/src/MicrodataDOMElement.php b/src/MicrodataDOMElement.php index 849e7d3..2dcc63b 100644 --- a/src/MicrodataDOMElement.php +++ b/src/MicrodataDOMElement.php @@ -163,7 +163,7 @@ protected function getChildElementNodes(): array * * @param string $attributeName Name of the attribute * - * @return array|bool + * @return array|false */ public function tokenizeAttribute(string $attributeName): array|bool { @@ -181,7 +181,7 @@ public function tokenizeAttribute(string $attributeName): array|bool * * @param string $attribute * - * @return array|bool + * @return array|false * @see \preg_split() for possible return values and behaviour * * @see https://www.w3.org/TR/2018/WD-microdata-20180426/#dfn-split-a-string-on-spaces for definition of tokens diff --git a/src/MicrodataParser.php b/src/MicrodataParser.php index 0b23bac..92c59f1 100644 --- a/src/MicrodataParser.php +++ b/src/MicrodataParser.php @@ -7,7 +7,6 @@ class MicrodataParser { - /** @var MicrodataDOMDocument */ protected MicrodataDOMDocument $dom; /** @@ -65,7 +64,7 @@ public function toObject() : stdClass * @param int $depth * * @return false|string - *@see \json_encode() to description of parameters and return values + * @see \json_encode() to description of parameters and return values * */ public function toJSON(int $options = 0, int $depth = 512): bool|string diff --git a/tests/MicrodataParserTest.php b/tests/MicrodataParserTest.php index b96cd80..a5d8008 100644 --- a/tests/MicrodataParserTest.php +++ b/tests/MicrodataParserTest.php @@ -9,9 +9,6 @@ class MicrodataParserTest extends TestCase { - /** - * @return void - */ protected function setUp() :void { libxml_use_internal_errors(true); // Ignore warnings of DOMDocument::loadHTML check @@ -69,7 +66,7 @@ public function testItUsesAbsoluteUriHandlerWhenHandlingAbsoluteUris() $parser = $this->getParser($data); $resultBefore = $parser->toObject(); - $resultBeforeUri = $resultBefore->items[0]->properties->work[0]; + $resultBeforeUri = $resultBefore->items[0]->properties->work; $this->assertNotContains($baseUri, $resultBeforeUri); @@ -87,12 +84,13 @@ function (string $value, string $base) use ($baseUri) : string { /** * @todo Provide more test data + * @return array[ + * 'W3C Example' => "array[]", + * 'Itemref & src based tags' => "array[]", + * 'Object & Data tags' => "array[]", + * 'Itemid & Content attributes' => "array[]" + * ] */ - #[ArrayShape([ - 'W3C Example' => "array[]", - 'Itemref & src based tags' => "array[]", - 'Object & Data tags' => "array[]", - 'Itemid & Content attributes' => "array[]"])] public function data(): array { return [ diff --git a/tests/MicrodataTest.php b/tests/MicrodataTest.php index b33cc77..2a87983 100644 --- a/tests/MicrodataTest.php +++ b/tests/MicrodataTest.php @@ -3,11 +3,10 @@ namespace YusufKandemir\MicrodataParser\Tests; use DOMDocument; -use PHPUnit\Framework\TestCase; use YusufKandemir\MicrodataParser\Microdata; use YusufKandemir\MicrodataParser\MicrodataParser; -class MicrodataTest extends TestCase +class MicrodataTest extends \PHPUnit\Framework\TestCase { protected string $htmlFileName = __DIR__ . '/data/W3C/source.html'; From 16541df3a1e8cdeb2f6fff3fa8e50e02d9516abe Mon Sep 17 00:00:00 2001 From: Yusuf Kandemir Date: Sat, 2 Apr 2022 01:57:46 +0300 Subject: [PATCH 5/6] fix(tests): Fix absolute uri test case --- tests/MicrodataParserTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/MicrodataParserTest.php b/tests/MicrodataParserTest.php index a5d8008..ceb9a5b 100644 --- a/tests/MicrodataParserTest.php +++ b/tests/MicrodataParserTest.php @@ -66,9 +66,9 @@ public function testItUsesAbsoluteUriHandlerWhenHandlingAbsoluteUris() $parser = $this->getParser($data); $resultBefore = $parser->toObject(); - $resultBeforeUri = $resultBefore->items[0]->properties->work; + $resultBeforeUri = $resultBefore->items[0]->properties->work[0]; - $this->assertNotContains($baseUri, $resultBeforeUri); + $this->assertStringNotContainsString($baseUri, $resultBeforeUri); $parser->setAbsoluteUriHandler( function (string $value, string $base) use ($baseUri) : string { @@ -79,7 +79,7 @@ function (string $value, string $base) use ($baseUri) : string { $resultAfter = $parser->toObject(); $resultAfterUri = $resultAfter->items[0]->properties->work[0]; - $this->assertContains($baseUri, $resultAfterUri); + $this->assertStringContainsString($baseUri, $resultAfterUri); } /** From e897e8ba9af7326454fca2d4729889064adc3ec9 Mon Sep 17 00:00:00 2001 From: Yusuf Kandemir Date: Sat, 2 Apr 2022 02:20:38 +0300 Subject: [PATCH 6/6] chore(tests): Fix array shape types --- tests/MicrodataParserTest.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/tests/MicrodataParserTest.php b/tests/MicrodataParserTest.php index ceb9a5b..ffd2ac9 100644 --- a/tests/MicrodataParserTest.php +++ b/tests/MicrodataParserTest.php @@ -2,7 +2,6 @@ namespace YusufKandemir\MicrodataParser\Tests; -use JetBrains\PhpStorm\ArrayShape; use PHPUnit\Framework\TestCase; use YusufKandemir\MicrodataParser\MicrodataDOMDocument; use YusufKandemir\MicrodataParser\MicrodataParser; @@ -84,12 +83,12 @@ function (string $value, string $base) use ($baseUri) : string { /** * @todo Provide more test data - * @return array[ - * 'W3C Example' => "array[]", - * 'Itemref & src based tags' => "array[]", - * 'Object & Data tags' => "array[]", - * 'Itemid & Content attributes' => "array[]" - * ] + * @return array{ + * 'W3C Example': array{uri: string, source: string, result: string}[], + * 'Itemref & src based tags': array{uri: string, source: string, result: string}[], + * 'Object & Data tags': array{uri: string, source: string, result: string}[], + * 'Itemid & Content attributes': array{uri: string, source: string, result: string}[] + * } */ public function data(): array { @@ -110,11 +109,9 @@ public function data(): array ]; } - #[ArrayShape([ - 'uri' => "mixed|string", - 'source' => "false|string", - 'result' => "false|string" - ])] + /** + * @return array{uri: string, source: string, result: string} + */ private function getTestData($folderName, $sourceName, $resultName): array { $folderPath = __DIR__.'/data/'.$folderName.'/'; @@ -122,6 +119,10 @@ private function getTestData($folderName, $sourceName, $resultName): array $source = file_get_contents($folderPath . $sourceName); $result = file_get_contents($folderPath . $resultName); + if ($source === false || $result === false) { + throw new \Exception('Could not load test data'); + } + $uri = ''; // Set $uri if URI specified in test data if (preg_match('//', $source, $matches)) {