diff --git a/.gitignore b/.gitignore index 53d78e7f2..47e209bc0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ bin **/*/.github # ignore changelogs **/CHANGELOG.md +**/CHANGELOG*.md # ignore coc **/CODE_OF_CONDUCT.md # ignore composer.json @@ -31,6 +32,7 @@ bin */*/psalm.baseline.xml */*/phpcs.xml */*/phpcs.xml.dist +*/*/.php-cs-fixer.php */*/.php-cs-fixer.dist.php */*/.phpcs.xml */*/phpstan.neon.dist diff --git a/composer.json b/composer.json index 9caba967a..a3e4a3ae8 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "deepdiver1975/tarstreamer": "^2.1.0", "doctrine/dbal": "^3.9.1", "egulias/email-validator": "^4.0.4", - "fusonic/opengraph": "^2.3.0", + "fusonic/opengraph": "^3.0.0", "giggsey/libphonenumber-for-php-lite": "^9.0.9", "guzzlehttp/guzzle": "^7.9.3", "icewind/searchdav": "^3.2.0", diff --git a/composer.lock b/composer.lock index 347a47740..ab10320e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eb06f8384bc134dc1ffdb6a0f4ebbc2e", + "content-hash": "86bb1b60f929e3fa40bb828c73b81440", "packages": [ { "name": "aws/aws-crt-php", @@ -925,34 +925,39 @@ }, { "name": "fusonic/opengraph", - "version": "v2.3.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/fusonic/opengraph.git", - "reference": "09dca70b04b4221c9dc664e1689e876a3faa50c2" + "reference": "2daa6dce84f23b1bb6d66bf03b3e9371c39cd378" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fusonic/opengraph/zipball/09dca70b04b4221c9dc664e1689e876a3faa50c2", - "reference": "09dca70b04b4221c9dc664e1689e876a3faa50c2", + "url": "https://api.github.com/repos/fusonic/opengraph/zipball/2daa6dce84f23b1bb6d66bf03b3e9371c39cd378", + "reference": "2daa6dce84f23b1bb6d66bf03b3e9371c39cd378", "shasum": "" }, "require": { "ext-dom": "*", - "php": "^7.4|^8.0", + "php": "^8.1", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "symfony/css-selector": "^3.0|^4.0|^5.0|^6.0", - "symfony/dom-crawler": "^3.0|^4.0|^5.0|^6.0" + "symfony/css-selector": "^5.4 || ^6.4 || ^7.1", + "symfony/dom-crawler": "^5.4 || ^6.4 || ^7.1" }, "require-dev": { - "nyholm/psr7": "^1.2", - "phpunit/phpunit": "^9.0", - "symfony/http-client": "^6.0" + "friendsofphp/php-cs-fixer": "^3.65", + "nyholm/psr7": "^1.8", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^10.5 || ^11.4", + "symfony/http-client": "^5.4 || ^6.4 || ^7.1" }, "suggest": { - "nyholm/psr7": "^1.2", - "symfony/http-client": "^5.0" + "nyholm/psr7": "^1.8", + "symfony/http-client": "^5.4 || ^6.4 || ^7.1" }, "type": "library", "autoload": { @@ -971,15 +976,15 @@ } ], "description": "PHP library for consuming and publishing Open Graph resources.", - "homepage": "https://github.com/fusonic/fusonic-opengraph", + "homepage": "https://github.com/fusonic/opengraph", "keywords": [ "opengraph" ], "support": { "issues": "https://github.com/fusonic/opengraph/issues", - "source": "https://github.com/fusonic/opengraph/tree/v2.3.0" + "source": "https://github.com/fusonic/opengraph/tree/v3.0.0" }, - "time": "2023-12-05T14:26:51+00:00" + "time": "2025-01-13T07:23:24+00:00" }, { "name": "giggsey/libphonenumber-for-php-lite", @@ -4327,16 +4332,16 @@ }, { "name": "symfony/css-selector", - "version": "v6.4.3", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229" + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ee0f7ed5cf298cc019431bb3b3977ebc52b86229", - "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/cb23e97813c5837a041b73a6d63a9ddff0778f5e", + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e", "shasum": "" }, "require": { @@ -4372,7 +4377,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.3" + "source": "https://github.com/symfony/css-selector/tree/v6.4.13" }, "funding": [ { @@ -4388,7 +4393,7 @@ "type": "tidelift" } ], - "time": "2024-01-23T14:51:35+00:00" + "time": "2024-09-25T14:18:03+00:00" }, { "name": "symfony/deprecation-contracts", @@ -4459,16 +4464,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v6.4.4", + "version": "v6.4.23", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531" + "reference": "22210aacb35dbadd772325d759d17bce2374a84d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", - "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/22210aacb35dbadd772325d759d17bce2374a84d", + "reference": "22210aacb35dbadd772325d759d17bce2374a84d", "shasum": "" }, "require": { @@ -4506,7 +4511,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.4" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.23" }, "funding": [ { @@ -4522,7 +4527,7 @@ "type": "tidelift" } ], - "time": "2024-02-07T09:17:57+00:00" + "time": "2025-06-13T12:10:00+00:00" }, { "name": "symfony/event-dispatcher", @@ -4924,7 +4929,7 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -4983,7 +4988,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { diff --git a/composer/installed.json b/composer/installed.json index 53ec75480..947f88823 100644 --- a/composer/installed.json +++ b/composer/installed.json @@ -958,37 +958,42 @@ }, { "name": "fusonic/opengraph", - "version": "v2.3.0", - "version_normalized": "2.3.0.0", + "version": "v3.0.0", + "version_normalized": "3.0.0.0", "source": { "type": "git", "url": "https://github.com/fusonic/opengraph.git", - "reference": "09dca70b04b4221c9dc664e1689e876a3faa50c2" + "reference": "2daa6dce84f23b1bb6d66bf03b3e9371c39cd378" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fusonic/opengraph/zipball/09dca70b04b4221c9dc664e1689e876a3faa50c2", - "reference": "09dca70b04b4221c9dc664e1689e876a3faa50c2", + "url": "https://api.github.com/repos/fusonic/opengraph/zipball/2daa6dce84f23b1bb6d66bf03b3e9371c39cd378", + "reference": "2daa6dce84f23b1bb6d66bf03b3e9371c39cd378", "shasum": "" }, "require": { "ext-dom": "*", - "php": "^7.4|^8.0", + "php": "^8.1", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "symfony/css-selector": "^3.0|^4.0|^5.0|^6.0", - "symfony/dom-crawler": "^3.0|^4.0|^5.0|^6.0" + "symfony/css-selector": "^5.4 || ^6.4 || ^7.1", + "symfony/dom-crawler": "^5.4 || ^6.4 || ^7.1" }, "require-dev": { - "nyholm/psr7": "^1.2", - "phpunit/phpunit": "^9.0", - "symfony/http-client": "^6.0" + "friendsofphp/php-cs-fixer": "^3.65", + "nyholm/psr7": "^1.8", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^10.5 || ^11.4", + "symfony/http-client": "^5.4 || ^6.4 || ^7.1" }, "suggest": { - "nyholm/psr7": "^1.2", - "symfony/http-client": "^5.0" + "nyholm/psr7": "^1.8", + "symfony/http-client": "^5.4 || ^6.4 || ^7.1" }, - "time": "2023-12-05T14:26:51+00:00", + "time": "2025-01-13T07:23:24+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -1007,13 +1012,13 @@ } ], "description": "PHP library for consuming and publishing Open Graph resources.", - "homepage": "https://github.com/fusonic/fusonic-opengraph", + "homepage": "https://github.com/fusonic/opengraph", "keywords": [ "opengraph" ], "support": { "issues": "https://github.com/fusonic/opengraph/issues", - "source": "https://github.com/fusonic/opengraph/tree/v2.3.0" + "source": "https://github.com/fusonic/opengraph/tree/v3.0.0" }, "install-path": "../fusonic/opengraph" }, @@ -4513,23 +4518,23 @@ }, { "name": "symfony/css-selector", - "version": "v6.4.3", - "version_normalized": "6.4.3.0", + "version": "v6.4.13", + "version_normalized": "6.4.13.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229" + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/ee0f7ed5cf298cc019431bb3b3977ebc52b86229", - "reference": "ee0f7ed5cf298cc019431bb3b3977ebc52b86229", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/cb23e97813c5837a041b73a6d63a9ddff0778f5e", + "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e", "shasum": "" }, "require": { "php": ">=8.1" }, - "time": "2024-01-23T14:51:35+00:00", + "time": "2024-09-25T14:18:03+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4561,7 +4566,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.3" + "source": "https://github.com/symfony/css-selector/tree/v6.4.13" }, "funding": [ { @@ -4651,17 +4656,17 @@ }, { "name": "symfony/dom-crawler", - "version": "v6.4.4", - "version_normalized": "6.4.4.0", + "version": "v6.4.23", + "version_normalized": "6.4.23.0", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531" + "reference": "22210aacb35dbadd772325d759d17bce2374a84d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", - "reference": "f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/22210aacb35dbadd772325d759d17bce2374a84d", + "reference": "22210aacb35dbadd772325d759d17bce2374a84d", "shasum": "" }, "require": { @@ -4673,7 +4678,7 @@ "require-dev": { "symfony/css-selector": "^5.4|^6.0|^7.0" }, - "time": "2024-02-07T09:17:57+00:00", + "time": "2025-06-13T12:10:00+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -4701,7 +4706,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.4" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.23" }, "funding": [ { @@ -5134,8 +5139,8 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.31.0", - "version_normalized": "1.31.0.0", + "version": "v1.32.0", + "version_normalized": "1.32.0.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", @@ -5196,7 +5201,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.32.0" }, "funding": [ { diff --git a/composer/installed.php b/composer/installed.php index ffc779714..b46ece9f9 100644 --- a/composer/installed.php +++ b/composer/installed.php @@ -128,9 +128,9 @@ 'dev_requirement' => false, ), 'fusonic/opengraph' => array( - 'pretty_version' => 'v2.3.0', - 'version' => '2.3.0.0', - 'reference' => '09dca70b04b4221c9dc664e1689e876a3faa50c2', + 'pretty_version' => 'v3.0.0', + 'version' => '3.0.0.0', + 'reference' => '2daa6dce84f23b1bb6d66bf03b3e9371c39cd378', 'type' => 'library', 'install_path' => __DIR__ . '/../fusonic/opengraph', 'aliases' => array(), @@ -662,9 +662,9 @@ 'dev_requirement' => false, ), 'symfony/css-selector' => array( - 'pretty_version' => 'v6.4.3', - 'version' => '6.4.3.0', - 'reference' => 'ee0f7ed5cf298cc019431bb3b3977ebc52b86229', + 'pretty_version' => 'v6.4.13', + 'version' => '6.4.13.0', + 'reference' => 'cb23e97813c5837a041b73a6d63a9ddff0778f5e', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), @@ -680,9 +680,9 @@ 'dev_requirement' => false, ), 'symfony/dom-crawler' => array( - 'pretty_version' => 'v6.4.4', - 'version' => '6.4.4.0', - 'reference' => 'f0e7ec3fa17000e2d0cb4557b4b47c88a6a63531', + 'pretty_version' => 'v6.4.23', + 'version' => '6.4.23.0', + 'reference' => '22210aacb35dbadd772325d759d17bce2374a84d', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/dom-crawler', 'aliases' => array(), @@ -740,8 +740,8 @@ 'dev_requirement' => false, ), 'symfony/polyfill-ctype' => array( - 'pretty_version' => 'v1.31.0', - 'version' => '1.31.0.0', + 'pretty_version' => 'v1.32.0', + 'version' => '1.32.0.0', 'reference' => 'a3cc8b044a6ea513310cbd48ef7333b384945638', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', diff --git a/fusonic/opengraph/LICENSE b/fusonic/opengraph/LICENSE index 46c173a30..bb8f68c21 100644 --- a/fusonic/opengraph/LICENSE +++ b/fusonic/opengraph/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014 Fusonic GmbH (http://www.fusonic.net) +Copyright (c) 2014-2024 Fusonic GmbH (https://www.fusonic.net) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/fusonic/opengraph/src/Consumer.php b/fusonic/opengraph/src/Consumer.php index 74aec6a64..7dc884abc 100644 --- a/fusonic/opengraph/src/Consumer.php +++ b/fusonic/opengraph/src/Consumer.php @@ -1,23 +1,26 @@ client = $client; - $this->requestFactory = $requestFactory; + public function __construct( + private ?ClientInterface $client = null, + private ?RequestFactoryInterface $requestFactory = null, + ) { } /** * Fetches HTML content from the given URL and then crawls it for Open Graph data. * - * @param string $url URL to be crawled. - * - * @return ObjectBase + * @param string $url URL to be crawled * * @throws ClientExceptionInterface */ public function loadUrl(string $url): ObjectBase { - if ($this->client === null) { - throw new LogicException( - "To use loadUrl() you must provide \$client and \$requestFactory when instantiating the consumer." + if (null === $this->client || null === $this->requestFactory) { + throw new \LogicException( + 'To use loadUrl() you must provide $client and $requestFactory when instantiating the consumer.' ); } - $request = $this->requestFactory->createRequest("GET", $url); + $request = $this->requestFactory->createRequest('GET', $url); $response = $this->client->sendRequest($request); return $this->loadHtml($response->getBody()->getContents(), $url); @@ -66,18 +67,16 @@ public function loadUrl(string $url): ObjectBase /** * Crawls the given HTML string for OpenGraph data. * - * @param string $html HTML string, usually whole content of crawled web resource. - * @param string $fallbackUrl URL to use when fallback mode is enabled. - * - * @return ObjectBase + * @param string $html HTML string, usually whole content of crawled web resource + * @param string|null $fallbackUrl URL to use when fallback mode is enabled */ - public function loadHtml(string $html, string $fallbackUrl = null): ObjectBase + public function loadHtml(string $html, ?string $fallbackUrl = null): ObjectBase { // Extract all data that can be found $page = $this->extractOpenGraphData($html); // Use the user's URL as fallback - if ($this->useFallbackMode && $page->url === null) { + if ($this->useFallbackMode && null === $page->url) { $page->url = $fallbackUrl; } @@ -87,26 +86,27 @@ public function loadHtml(string $html, string $fallbackUrl = null): ObjectBase private function extractOpenGraphData(string $content): ObjectBase { - $crawler = new Crawler; - $crawler->addHTMLContent($content, 'UTF-8'); + $crawler = new Crawler(); + $crawler->addHtmlContent(content: $content); $properties = []; - foreach(['name', 'property'] as $t) - { + foreach (['name', 'property'] as $t) { // Get all meta-tags starting with "og:" $ogMetaTags = $crawler->filter("meta[{$t}^='og:']"); // Create clean property array $props = []; + + /** @var \DOMElement $tag */ foreach ($ogMetaTags as $tag) { $name = strtolower(trim($tag->getAttribute($t))); - $value = trim($tag->getAttribute("content")); + $value = trim($tag->getAttribute('content')); $props[] = new Property($name, $value); } $properties = array_merge($properties, $props); } - + // Create new object $object = new Website(); @@ -114,26 +114,26 @@ private function extractOpenGraphData(string $content): ObjectBase $object->assignProperties($properties, $this->debug); // Fallback for url - if ($this->useFallbackMode && !$object->url) { + if ($this->useFallbackMode && null === $object->url) { $urlElement = $crawler->filter("link[rel='canonical']")->first(); if ($urlElement->count() > 0) { - $object->url = trim($urlElement->attr("href")); + $object->url = trim($urlElement->attr('href') ?? ''); } } // Fallback for title - if ($this->useFallbackMode && !$object->title) { - $titleElement = $crawler->filter("title")->first(); + if ($this->useFallbackMode && null === $object->title) { + $titleElement = $crawler->filter('title')->first(); if ($titleElement->count() > 0) { $object->title = trim($titleElement->text()); } } // Fallback for description - if ($this->useFallbackMode && !$object->description) { + if ($this->useFallbackMode && null === $object->description) { $descriptionElement = $crawler->filter("meta[property='description']")->first(); if ($descriptionElement->count() > 0) { - $object->description = trim($descriptionElement->attr("content")); + $object->description = trim($descriptionElement->attr('content') ?? ''); } } diff --git a/fusonic/opengraph/src/Elements/Audio.php b/fusonic/opengraph/src/Elements/Audio.php index 20df532d2..394348cc1 100644 --- a/fusonic/opengraph/src/Elements/Audio.php +++ b/fusonic/opengraph/src/Elements/Audio.php @@ -1,5 +1,12 @@ url = $url; } /** * Gets all properties set on this element. * - * @return array|Property[] + * @return Property[] */ - public function getProperties() + public function getProperties(): array { $properties = []; // URL must precede all other properties - if ($this->url !== null) { + if (null !== $this->url) { $properties[] = new Property(Property::AUDIO_URL, $this->url); } - if ($this->secureUrl !== null) { + if (null !== $this->secureUrl) { $properties[] = new Property(Property::AUDIO_SECURE_URL, $this->secureUrl); } - if ($this->type !== null) { + if (null !== $this->type) { $properties[] = new Property(Property::AUDIO_TYPE, $this->type); } diff --git a/fusonic/opengraph/src/Elements/ElementBase.php b/fusonic/opengraph/src/Elements/ElementBase.php index dd4139dc3..566006493 100644 --- a/fusonic/opengraph/src/Elements/ElementBase.php +++ b/fusonic/opengraph/src/Elements/ElementBase.php @@ -1,20 +1,25 @@ url = $url; } /** * Gets all properties set on this element. * - * @return array|Property[] + * @return Property[] */ - public function getProperties() + public function getProperties(): array { $properties = []; // URL must precede all other properties - if ($this->url !== null) { + if (null !== $this->url) { $properties[] = new Property(Property::IMAGE_URL, $this->url); } - if ($this->height !== null) { + if (null !== $this->height) { $properties[] = new Property(Property::IMAGE_HEIGHT, $this->height); } - if ($this->secureUrl !== null) { + if (null !== $this->secureUrl) { $properties[] = new Property(Property::IMAGE_SECURE_URL, $this->secureUrl); } - if ($this->type !== null) { + if (null !== $this->type) { $properties[] = new Property(Property::IMAGE_TYPE, $this->type); } - if ($this->width !== null) { + if (null !== $this->width) { $properties[] = new Property(Property::IMAGE_WIDTH, $this->width); } - if ($this->userGenerated !== null) { + if (null !== $this->userGenerated) { $properties[] = new Property(Property::IMAGE_USER_GENERATED, $this->userGenerated); } diff --git a/fusonic/opengraph/src/Elements/Video.php b/fusonic/opengraph/src/Elements/Video.php index ff5a3305b..c5062fe2f 100644 --- a/fusonic/opengraph/src/Elements/Video.php +++ b/fusonic/opengraph/src/Elements/Video.php @@ -1,5 +1,12 @@ url = $url; } /** * Gets all properties set on this element. * - * @return array|Property[] + * @return Property[] */ - public function getProperties() + public function getProperties(): array { $properties = []; // URL must precede all other properties - if ($this->url !== null) { + if (null !== $this->url) { $properties[] = new Property(Property::VIDEO_URL, $this->url); } - if ($this->height !== null) { + if (null !== $this->height) { $properties[] = new Property(Property::VIDEO_HEIGHT, $this->height); } - if ($this->secureUrl !== null) { + if (null !== $this->secureUrl) { $properties[] = new Property(Property::VIDEO_SECURE_URL, $this->secureUrl); } - if ($this->type !== null) { + if (null !== $this->type) { $properties[] = new Property(Property::VIDEO_TYPE, $this->type); } - if ($this->width !== null) { + if (null !== $this->width) { $properties[] = new Property(Property::VIDEO_WIDTH, $this->width); } diff --git a/fusonic/opengraph/src/Objects/ObjectBase.php b/fusonic/opengraph/src/Objects/ObjectBase.php index 33b9976d1..40e3bf97d 100644 --- a/fusonic/opengraph/src/Objects/ObjectBase.php +++ b/fusonic/opengraph/src/Objects/ObjectBase.php @@ -1,16 +1,21 @@ key; $value = $property->value; - switch($name) { + switch ($name) { case Property::AUDIO: case Property::AUDIO_URL: $this->audios[] = new Audio($value); break; case Property::AUDIO_SECURE_URL: case Property::AUDIO_TYPE: - if (count($this->audios) > 0) { - $this->handleAudioAttribute($this->audios[count($this->audios) - 1], $name, $value); + if (\count($this->audios) > 0) { + $this->handleAudioAttribute($this->audios[\count($this->audios) - 1], $name, $value); } elseif ($debug) { - throw new UnexpectedValueException( - sprintf( + throw new \UnexpectedValueException( + \sprintf( "Found '%s' property but no audio was found before.", $name ) @@ -130,12 +131,12 @@ public function assignProperties(array $properties, $debug = false): void } break; case Property::DESCRIPTION: - if ($this->description === null) { + if (null === $this->description) { $this->description = $value; } break; case Property::DETERMINER: - if ($this->determiner === null) { + if (null === $this->determiner) { $this->determiner = $value; } break; @@ -148,11 +149,11 @@ public function assignProperties(array $properties, $debug = false): void case Property::IMAGE_TYPE: case Property::IMAGE_WIDTH: case Property::IMAGE_USER_GENERATED: - if (count($this->images) > 0) { - $this->handleImageAttribute($this->images[count($this->images) - 1], $name, $value); + if (\count($this->images) > 0) { + $this->handleImageAttribute($this->images[\count($this->images) - 1], $name, $value); } elseif ($debug) { - throw new UnexpectedValueException( - sprintf( + throw new \UnexpectedValueException( + \sprintf( "Found '%s' property but no image was found before.", $name ) @@ -160,7 +161,7 @@ public function assignProperties(array $properties, $debug = false): void } break; case Property::LOCALE: - if ($this->locale === null) { + if (null === $this->locale) { $this->locale = $value; } break; @@ -174,22 +175,22 @@ public function assignProperties(array $properties, $debug = false): void $this->seeAlso[] = $value; break; case Property::SITE_NAME: - if ($this->siteName === null) { + if (null === $this->siteName) { $this->siteName = $value; } break; case Property::TITLE: - if ($this->title === null) { + if (null === $this->title) { $this->title = $value; } break; case Property::UPDATED_TIME: - if ($this->updatedTime === null) { + if (null === $this->updatedTime) { $this->updatedTime = $this->convertToDateTime($value); } break; case Property::URL: - if ($this->url === null) { + if (null === $this->url) { $this->url = $value; } break; @@ -201,10 +202,10 @@ public function assignProperties(array $properties, $debug = false): void case Property::VIDEO_SECURE_URL: case Property::VIDEO_TYPE: case Property::VIDEO_WIDTH: - if (count($this->videos) > 0) { - $this->handleVideoAttribute($this->videos[count($this->videos) - 1], $name, $value); + if (\count($this->videos) > 0) { + $this->handleVideoAttribute($this->videos[\count($this->videos) - 1], $name, $value); } elseif ($debug) { - throw new UnexpectedValueException(sprintf( + throw new \UnexpectedValueException(\sprintf( "Found '%s' property but no video was found before.", $name )); @@ -215,13 +216,12 @@ public function assignProperties(array $properties, $debug = false): void private function handleImageAttribute(Image $element, string $name, string $value): void { - switch($name) - { + switch ($name) { case Property::IMAGE_HEIGHT: - $element->height = (int)$value; + $element->height = (int) $value; break; case Property::IMAGE_WIDTH: - $element->width = (int)$value; + $element->width = (int) $value; break; case Property::IMAGE_TYPE: $element->type = $value; @@ -237,13 +237,12 @@ private function handleImageAttribute(Image $element, string $name, string $valu private function handleVideoAttribute(Video $element, string $name, string $value): void { - switch($name) - { + switch ($name) { case Property::VIDEO_HEIGHT: - $element->height = (int)$value; + $element->height = (int) $value; break; case Property::VIDEO_WIDTH: - $element->width = (int)$value; + $element->width = (int) $value; break; case Property::VIDEO_TYPE: $element->type = $value; @@ -256,8 +255,7 @@ private function handleVideoAttribute(Video $element, string $name, string $valu private function handleAudioAttribute(Audio $element, string $name, string $value): void { - switch($name) - { + switch ($name) { case Property::AUDIO_TYPE: $element->type = $value; break; @@ -267,10 +265,10 @@ private function handleAudioAttribute(Audio $element, string $name, string $valu } } - protected function convertToDateTime(string $value): ?DateTimeImmutable + protected function convertToDateTime(string $value): ?\DateTimeImmutable { try { - return new DateTimeImmutable($value); + return new \DateTimeImmutable($value); } catch (\Exception $e) { return null; } @@ -278,10 +276,9 @@ protected function convertToDateTime(string $value): ?DateTimeImmutable protected function convertToBoolean(string $value): bool { - switch(strtolower($value)) - { - case "1": - case "true": + switch (strtolower($value)) { + case '1': + case 'true': return true; default: return false; @@ -291,7 +288,7 @@ protected function convertToBoolean(string $value): bool /** * Gets all properties set on this object. * - * @return Property[] + * @return Property[] */ public function getProperties(): array { @@ -300,16 +297,16 @@ public function getProperties(): array foreach ($this->audios as $audio) { $properties = array_merge($properties, $audio->getProperties()); } - - if ($this->title !== null) { + + if (null !== $this->title) { $properties[] = new Property(Property::TITLE, $this->title); } - if ($this->description !== null) { + if (null !== $this->description) { $properties[] = new Property(Property::DESCRIPTION, $this->description); } - if ($this->determiner !== null) { + if (null !== $this->determiner) { $properties[] = new Property(Property::DETERMINER, $this->determiner); } @@ -317,7 +314,7 @@ public function getProperties(): array $properties = array_merge($properties, $image->getProperties()); } - if ($this->locale !== null) { + if (null !== $this->locale) { $properties[] = new Property(Property::LOCALE, $this->locale); } @@ -325,27 +322,27 @@ public function getProperties(): array $properties[] = new Property(Property::LOCALE_ALTERNATE, $locale); } - if ($this->richAttachment !== null) { - $properties[] = new Property(Property::RICH_ATTACHMENT, (int)$this->richAttachment); + if (null !== $this->richAttachment) { + $properties[] = new Property(Property::RICH_ATTACHMENT, (int) $this->richAttachment); } foreach ($this->seeAlso as $seeAlso) { $properties[] = new Property(Property::SEE_ALSO, $seeAlso); } - if ($this->siteName !== null) { + if (null !== $this->siteName) { $properties[] = new Property(Property::SITE_NAME, $this->siteName); } - if ($this->type !== null) { + if (null !== $this->type) { $properties[] = new Property(Property::TYPE, $this->type); } - if ($this->updatedTime !== null) { - $properties[] = new Property(Property::UPDATED_TIME, $this->updatedTime->format("c")); + if (null !== $this->updatedTime) { + $properties[] = new Property(Property::UPDATED_TIME, $this->updatedTime->format('c')); } - if ($this->url !== null) { + if (null !== $this->url) { $properties[] = new Property(Property::URL, $this->url); } diff --git a/fusonic/opengraph/src/Objects/Website.php b/fusonic/opengraph/src/Objects/Website.php index f66428cc2..a973c77f2 100644 --- a/fusonic/opengraph/src/Objects/Website.php +++ b/fusonic/opengraph/src/Objects/Website.php @@ -1,5 +1,12 @@ type = self::TYPE; } } diff --git a/fusonic/opengraph/src/Property.php b/fusonic/opengraph/src/Property.php index e94593bd2..00fe7beaf 100644 --- a/fusonic/opengraph/src/Property.php +++ b/fusonic/opengraph/src/Property.php @@ -1,5 +1,12 @@ key = $key; - $this->value = $value; + /** + * Value of the property. + */ + public mixed $value, + ) { } } diff --git a/fusonic/opengraph/src/Publisher.php b/fusonic/opengraph/src/Publisher.php index 059363aba..7a6eb6678 100644 --- a/fusonic/opengraph/src/Publisher.php +++ b/fusonic/opengraph/src/Publisher.php @@ -1,18 +1,23 @@ doctype == self::DOCTYPE_XHTML ? " />" : ">"); + $html = ''; + $format = 'doctype ? ' />' : '>'); foreach ($object->getProperties() as $property) { - if ($html !== "") { + if ('' !== $html) { $html .= "\n"; } - if ($property->value === null) { + if (null === $property->value) { continue; - } elseif ($property->value instanceof DateTimeInterface) { - $value = $property->value->format("c"); - } elseif (is_object($property->value)) { - throw new UnexpectedValueException( - sprintf( + } elseif ($property->value instanceof \DateTimeInterface) { + $value = $property->value->format('c'); + } elseif (\is_object($property->value)) { + throw new \UnexpectedValueException( + \sprintf( "Cannot handle value of type '%s' for property '%s'.", - get_class($property->value), + \get_class($property->value), $property->key ) ); - } elseif ($property->value === true) { - $value = "1"; - } elseif ($property->value === false) { - $value = "0"; + } elseif (true === $property->value) { + $value = '1'; + } elseif (false === $property->value) { + $value = '0'; } else { - $value = (string)$property->value; + $value = (string) $property->value; } - $html .= sprintf($format, $property->key, htmlspecialchars($value)); + $html .= \sprintf($format, $property->key, htmlspecialchars($value)); } return $html; diff --git a/symfony/dom-crawler/AbstractUriElement.php b/symfony/dom-crawler/AbstractUriElement.php index e67716f64..6d5846a87 100644 --- a/symfony/dom-crawler/AbstractUriElement.php +++ b/symfony/dom-crawler/AbstractUriElement.php @@ -46,7 +46,7 @@ public function __construct(\DOMElement $node, ?string $currentUri = null, ?stri $this->method = $method ? strtoupper($method) : null; $this->currentUri = $currentUri; - $elementUriIsRelative = null === parse_url(trim($this->getRawUri()), \PHP_URL_SCHEME); + $elementUriIsRelative = !parse_url(trim($this->getRawUri()), \PHP_URL_SCHEME); $baseUriIsAbsolute = null !== $this->currentUri && \in_array(strtolower(substr($this->currentUri, 0, 4)), ['http', 'file']); if ($elementUriIsRelative && !$baseUriIsAbsolute) { throw new \InvalidArgumentException(sprintf('The URL of the element is relative, so you must define its base URI passing an absolute URL to the constructor of the "%s" class ("%s" was passed).', __CLASS__, $this->currentUri)); diff --git a/symfony/dom-crawler/Crawler.php b/symfony/dom-crawler/Crawler.php index 8c5e26930..71e8528f1 100644 --- a/symfony/dom-crawler/Crawler.php +++ b/symfony/dom-crawler/Crawler.php @@ -431,7 +431,7 @@ public function closest(string $selector): ?self $domNode = $this->getNode(0); - while (\XML_ELEMENT_NODE === $domNode->nodeType) { + while (null !== $domNode && \XML_ELEMENT_NODE === $domNode->nodeType) { $node = $this->createSubCrawler($domNode); if ($node->matches($selector)) { return $node; @@ -770,12 +770,12 @@ public function selectImage(string $value): static } /** - * Selects a button by name or alt value for images. + * Selects a button by its text content, id, value, name or alt attribute. */ public function selectButton(string $value): static { return $this->filterRelativeXPath( - sprintf('descendant-or-self::input[((contains(%1$s, "submit") or contains(%1$s, "button")) and contains(concat(\' \', normalize-space(string(@value)), \' \'), %2$s)) or (contains(%1$s, "image") and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %2$s)) or @id=%3$s or @name=%3$s] | descendant-or-self::button[contains(concat(\' \', normalize-space(string(.)), \' \'), %2$s) or @id=%3$s or @name=%3$s]', 'translate(@type, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")', static::xpathLiteral(' '.$value.' '), static::xpathLiteral($value)) + sprintf('descendant-or-self::input[((contains(%1$s, "submit") or contains(%1$s, "button")) and contains(concat(\' \', normalize-space(string(@value)), \' \'), %2$s)) or (contains(%1$s, "image") and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %2$s)) or @id=%3$s or @name=%3$s] | descendant-or-self::button[contains(concat(\' \', normalize-space(string(.)), \' \'), %2$s) or contains(concat(\' \', normalize-space(string(@value)), \' \'), %2$s) or @id=%3$s or @name=%3$s]', 'translate(@type, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")', static::xpathLiteral(' '.$value.' '), static::xpathLiteral($value)) ); } @@ -1090,12 +1090,30 @@ protected function sibling(\DOMNode $node, string $siblingDir = 'nextSibling'): private function parseHtml5(string $htmlContent, string $charset = 'UTF-8'): \DOMDocument { - return $this->html5Parser->parse($this->convertToHtmlEntities($htmlContent, $charset)); + if (!$this->supportsEncoding($charset)) { + $htmlContent = $this->convertToHtmlEntities($htmlContent, $charset); + $charset = 'UTF-8'; + } + + return $this->html5Parser->parse($htmlContent, ['encoding' => $charset]); + } + + private function supportsEncoding(string $encoding): bool + { + try { + return '' === @mb_convert_encoding('', $encoding, 'UTF-8'); + } catch (\Throwable $e) { + return false; + } } private function parseXhtml(string $htmlContent, string $charset = 'UTF-8'): \DOMDocument { - $htmlContent = $this->convertToHtmlEntities($htmlContent, $charset); + if ('UTF-8' === $charset && preg_match('//u', $htmlContent)) { + $htmlContent = ''.$htmlContent; + } else { + $htmlContent = $this->convertToHtmlEntities($htmlContent, $charset); + } $internalErrors = libxml_use_internal_errors(true); diff --git a/symfony/dom-crawler/Field/ChoiceFormField.php b/symfony/dom-crawler/Field/ChoiceFormField.php index dcae5490a..7688b6d7e 100644 --- a/symfony/dom-crawler/Field/ChoiceFormField.php +++ b/symfony/dom-crawler/Field/ChoiceFormField.php @@ -45,6 +45,10 @@ public function hasValue(): bool */ public function isDisabled(): bool { + if ('checkbox' === $this->type) { + return parent::isDisabled(); + } + if (parent::isDisabled() && 'select' === $this->type) { return true; } diff --git a/symfony/dom-crawler/Form.php b/symfony/dom-crawler/Form.php index fd55546fe..9a7c19c1c 100644 --- a/symfony/dom-crawler/Form.php +++ b/symfony/dom-crawler/Form.php @@ -180,9 +180,8 @@ public function getUri(): string $uri = parent::getUri(); if (!\in_array($this->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) { - $query = parse_url($uri, \PHP_URL_QUERY); $currentParameters = []; - if ($query) { + if ($query = parse_url($uri, \PHP_URL_QUERY)) { parse_str($query, $currentParameters); } diff --git a/symfony/dom-crawler/UriResolver.php b/symfony/dom-crawler/UriResolver.php index d3b0c8396..398cb7bc3 100644 --- a/symfony/dom-crawler/UriResolver.php +++ b/symfony/dom-crawler/UriResolver.php @@ -33,7 +33,7 @@ public static function resolve(string $uri, ?string $baseUri): string $uri = trim($uri); // absolute URL? - if (null !== parse_url($uri, \PHP_URL_SCHEME)) { + if (null !== parse_url(\strlen($uri) !== strcspn($uri, '?#') ? $uri : $uri.'#', \PHP_URL_SCHEME)) { return $uri; }