Przeglądaj źródła

SimplePie: sync upstream (#7706)

https://github.com/FreshRSS/simplepie/pull/43
Alexandre Alapetite 9 miesięcy temu
rodzic
commit
8b73573a32

+ 1 - 1
lib/composer.json

@@ -14,7 +14,7 @@
         "marienfressinaud/lib_opml": "0.5.1",
         "phpgt/cssxpath": "v1.3.0",
         "phpmailer/phpmailer": "6.10.0",
-        "simplepie/simplepie": "dev-freshrss#2f0417355a702c678c237eac5ffc273863301a80"
+        "simplepie/simplepie": "dev-freshrss#d80757267ea1fcbe13d1d1e3a73c2e81f23440de"
     },
     "config": {
         "sort-packages": true,

+ 8 - 0
lib/simplepie/simplepie/CHANGELOG.md

@@ -24,6 +24,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Deprecated
 
+- The following `SimplePie\Misc` methods are deprecated without replacement:
+  - `SimplePie\Misc::element_implode()`
+  - `SimplePie\Misc::parse_str()`
+  - `SimplePie\Misc::percent_encoding_normalization()`
+  - `SimplePie\Misc::strip_comments()`
+  - `SimplePie\Misc::uncomment_rfc822()`
+
+  If you need any of them, consider copying the function to your codebase. (by @jtojnar in [#899](https://github.com/simplepie/simplepie/pull/899))
 - The method `SimplePie\SimplePie::set_file()` is deprecated, use `SimplePie\SimplePie::set_http_client()` or `SimplePie\SimplePie::set_raw_data()` instead
 - The method `SimplePie\Sanitize::pass_file_data()` is deprecated, use `SimplePie\Sanitize::set_http_client()` instead
 - Passing multiple URLs to `SimplePie\SimplePie::set_feed_url()` is deprecated. You can create separate `SimplePie` instance per feed and then use `SimplePie::merge_items()` to get a single list of items. ([#795](https://github.com/simplepie/simplepie/pull/795))

+ 3 - 0
lib/simplepie/simplepie/phpstan.neon.dist

@@ -65,3 +65,6 @@ parameters:
             message: '(^Access to an undefined property XMLReader::\$\w+\.$)'
             # Only occurs on PHP ≥ 8.2
             reportUnmatched: false
+
+includes:
+    - utils/PHPStan/extension.neon

+ 0 - 68
lib/simplepie/simplepie/src/File.php

@@ -324,98 +324,30 @@ class File implements Response
         return (int) $this->status_code;
     }
 
-    /**
-     * Retrieves all message header values.
-     *
-     * The keys represent the header name as it will be sent over the wire, and
-     * each value is an array of strings associated with the header.
-     *
-     *     // Represent the headers as a string
-     *     foreach ($message->get_headers() as $name => $values) {
-     *         echo $name . ': ' . implode(', ', $values);
-     *     }
-     *
-     *     // Emit headers iteratively:
-     *     foreach ($message->get_headers() as $name => $values) {
-     *         foreach ($values as $value) {
-     *             header(sprintf('%s: %s', $name, $value), false);
-     *         }
-     *     }
-     *
-     * @return string[][] Returns an associative array of the message's headers.
-     *     Each key MUST be a header name, and each value MUST be an array of
-     *     strings for that header.
-     */
     public function get_headers(): array
     {
         $this->maybe_update_headers();
         return $this->parsed_headers;
     }
 
-    /**
-     * Checks if a header exists by the given case-insensitive name.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return bool Returns true if any header names match the given header
-     *     name using a case-insensitive string comparison. Returns false if
-     *     no matching header name is found in the message.
-     */
     public function has_header(string $name): bool
     {
         $this->maybe_update_headers();
         return $this->get_header($name) !== [];
     }
 
-    /**
-     * Retrieves a message header value by the given case-insensitive name.
-     *
-     * This method returns an array of all the header values of the given
-     * case-insensitive header name.
-     *
-     * If the header does not appear in the message, this method MUST return an
-     * empty array.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return string[] An array of string values as provided for the given
-     *    header. If the header does not appear in the message, this method MUST
-     *    return an empty array.
-     */
     public function get_header(string $name): array
     {
         $this->maybe_update_headers();
         return $this->parsed_headers[strtolower($name)] ?? [];
     }
 
-    /**
-     * Retrieves a comma-separated string of the values for a single header.
-     *
-     * This method returns all of the header values of the given
-     * case-insensitive header name as a string concatenated together using
-     * a comma.
-     *
-     * NOTE: Not all header values may be appropriately represented using
-     * comma concatenation. For such headers, use getHeader() instead
-     * and supply your own delimiter when concatenating.
-     *
-     * If the header does not appear in the message, this method MUST return
-     * an empty string.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return string A string of values as provided for the given header
-     *    concatenated together using a comma. If the header does not appear in
-     *    the message, this method MUST return an empty string.
-     */
     public function get_header_line(string $name): string
     {
         $this->maybe_update_headers();
         return implode(', ', $this->get_header($name));
     }
 
-    /**
-     * get the body as string
-     *
-     * @return string
-     */
     public function get_body_content(): string
     {
         return (string) $this->body;

+ 1 - 3
lib/simplepie/simplepie/src/HTTP/Client.php

@@ -7,8 +7,6 @@ declare(strict_types=1);
 
 namespace SimplePie\HTTP;
 
-use SimplePie\Exception\HttpException;
-
 /**
  * HTTP Client interface
  *
@@ -24,7 +22,7 @@ interface Client
      * @param Client::METHOD_* $method
      * @param array<string, string> $headers
      *
-     * @throws HttpException if anything goes wrong requesting the data
+     * @throws ClientException if anything goes wrong requesting the data
      */
     public function request(string $method, string $url, array $headers = []): Response;
 }

+ 5 - 3
lib/simplepie/simplepie/src/Exception/HttpException.php → lib/simplepie/simplepie/src/HTTP/ClientException.php

@@ -5,13 +5,15 @@
 
 declare(strict_types=1);
 
-namespace SimplePie\Exception;
+namespace SimplePie\HTTP;
 
 use SimplePie\Exception as SimplePieException;
 
 /**
- * HTTP exception class
+ * Client exception class
+ *
+ * @internal
  */
-final class HttpException extends SimplePieException
+final class ClientException extends SimplePieException
 {
 }

+ 4 - 5
lib/simplepie/simplepie/src/HTTP/FileClient.php

@@ -8,7 +8,6 @@ declare(strict_types=1);
 namespace SimplePie\HTTP;
 
 use InvalidArgumentException;
-use SimplePie\Exception\HttpException;
 use SimplePie\File;
 use SimplePie\Misc;
 use SimplePie\Registry;
@@ -42,7 +41,7 @@ final class FileClient implements Client
      * @param Client::METHOD_* $method
      * @param array<string, string> $headers
      *
-     * @throws HttpException if anything goes wrong requesting the data
+     * @throws ClientException if anything goes wrong requesting the data
      */
     public function request(string $method, string $url, array $headers = []): Response
     {
@@ -66,11 +65,11 @@ final class FileClient implements Client
                 $this->options['curl_options'] ?? []
             ]);
         } catch (Throwable $th) {
-            throw new HttpException($th->getMessage(), $th->getCode(), $th);
+            throw new ClientException($th->getMessage(), $th->getCode(), $th);
         }
 
-        if (!$file->success) {
-            throw new HttpException($file->error, $file->get_status_code()); // FreshRSS https://github.com/simplepie/simplepie/pull/905
+        if (!$file->success && $file->get_status_code() === 0) {
+            throw new ClientException($file->error);
         }
 
         return $file;

+ 5 - 6
lib/simplepie/simplepie/src/HTTP/Psr18Client.php

@@ -12,7 +12,6 @@ use Psr\Http\Client\ClientExceptionInterface;
 use Psr\Http\Client\ClientInterface;
 use Psr\Http\Message\RequestFactoryInterface;
 use Psr\Http\Message\UriFactoryInterface;
-use SimplePie\Exception\HttpException;
 use Throwable;
 
 /**
@@ -71,7 +70,7 @@ final class Psr18Client implements Client
      * @param string $url
      * @param array<string,string|string[]> $headers
      *
-     * @throws HttpException if anything goes wrong requesting the data
+     * @throws ClientException if anything goes wrong requesting the data
      */
     public function request(string $method, string $url, array $headers = []): Response
     {
@@ -114,7 +113,7 @@ final class Psr18Client implements Client
             try {
                 $response = $this->httpClient->sendRequest($request);
             } catch (ClientExceptionInterface $th) {
-                throw new HttpException($th->getMessage(), $th->getCode(), $th);
+                throw new ClientException($th->getMessage(), $th->getCode(), $th);
             }
 
             $statusCode = $response->getStatusCode();
@@ -145,17 +144,17 @@ final class Psr18Client implements Client
     private function requestLocalFile(string $path): Response
     {
         if (!is_readable($path)) {
-            throw new HttpException(sprintf('file "%s" is not readable', $path));
+            throw new ClientException(sprintf('file "%s" is not readable', $path));
         }
 
         try {
             $raw = file_get_contents($path);
         } catch (Throwable $th) {
-            throw new HttpException($th->getMessage(), $th->getCode(), $th);
+            throw new ClientException($th->getMessage(), $th->getCode(), $th);
         }
 
         if ($raw === false) {
-            throw new HttpException('file_get_contents() could not read the file', 1);
+            throw new ClientException('file_get_contents() could not read the file', 1);
         }
 
         return new RawTextResponse($raw, $path);

+ 0 - 121
lib/simplepie/simplepie/src/HTTP/Psr7Response.php

@@ -41,162 +41,41 @@ final class Psr7Response implements Response
         $this->requested_url = $requested_url;
     }
 
-    /**
-     * Return the string representation of the permanent URI of the requested resource
-     * (the first location after a prefix of (only) permanent redirects).
-     *
-     * Depending on which components of the URI are present, the resulting
-     * string is either a full URI or relative reference according to RFC 3986,
-     * Section 4.1. The method concatenates the various components of the URI,
-     * using the appropriate delimiters:
-     *
-     * - If a scheme is present, it MUST be suffixed by ":".
-     * - If an authority is present, it MUST be prefixed by "//".
-     * - The path can be concatenated without delimiters. But there are two
-     *   cases where the path has to be adjusted to make the URI reference
-     *   valid as PHP does not allow to throw an exception in __toString():
-     *     - If the path is rootless and an authority is present, the path MUST
-     *       be prefixed by "/".
-     *     - If the path is starting with more than one "/" and no authority is
-     *       present, the starting slashes MUST be reduced to one.
-     * - If a query is present, it MUST be prefixed by "?".
-     * - If a fragment is present, it MUST be prefixed by "#".
-     *
-     * @see http://tools.ietf.org/html/rfc3986#section-4.1
-     */
     public function get_permanent_uri(): string
     {
         return $this->permanent_url;
     }
 
-    /**
-     * Return the string representation of the final requested URL after following all redirects.
-     *
-     * Depending on which components of the URI are present, the resulting
-     * string is either a full URI or relative reference according to RFC 3986,
-     * Section 4.1. The method concatenates the various components of the URI,
-     * using the appropriate delimiters:
-     *
-     * - If a scheme is present, it MUST be suffixed by ":".
-     * - If an authority is present, it MUST be prefixed by "//".
-     * - The path can be concatenated without delimiters. But there are two
-     *   cases where the path has to be adjusted to make the URI reference
-     *   valid as PHP does not allow to throw an exception in __toString():
-     *     - If the path is rootless and an authority is present, the path MUST
-     *       be prefixed by "/".
-     *     - If the path is starting with more than one "/" and no authority is
-     *       present, the starting slashes MUST be reduced to one.
-     * - If a query is present, it MUST be prefixed by "?".
-     * - If a fragment is present, it MUST be prefixed by "#".
-     *
-     * @see http://tools.ietf.org/html/rfc3986#section-4.1
-     */
     public function get_final_requested_uri(): string
     {
         return $this->requested_url;
     }
 
-    /**
-     * Gets the response status code.
-     *
-     * The status code is a 3-digit integer result code of the server's attempt
-     * to understand and satisfy the request.
-     *
-     * @return int Status code.
-     */
     public function get_status_code(): int
     {
         return $this->response->getStatusCode();
     }
 
-    /**
-     * Retrieves all message header values.
-     *
-     * The keys represent the header name as it will be sent over the wire, and
-     * each value is an array of strings associated with the header.
-     *
-     *     // Represent the headers as a string
-     *     foreach ($message->get_headers() as $name => $values) {
-     *         echo $name . ': ' . implode(', ', $values);
-     *     }
-     *
-     *     // Emit headers iteratively:
-     *     foreach ($message->get_headers() as $name => $values) {
-     *         foreach ($values as $value) {
-     *             header(sprintf('%s: %s', $name, $value), false);
-     *         }
-     *     }
-     *
-     * @return string[][] Returns an associative array of the message's headers.
-     *     Each key MUST be a header name, and each value MUST be an array of
-     *     strings for that header.
-     */
     public function get_headers(): array
     {
         return $this->response->getHeaders();
     }
 
-    /**
-     * Checks if a header exists by the given case-insensitive name.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return bool Returns true if any header names match the given header
-     *     name using a case-insensitive string comparison. Returns false if
-     *     no matching header name is found in the message.
-     */
     public function has_header(string $name): bool
     {
         return $this->response->hasHeader($name);
     }
 
-    /**
-     * Retrieves a message header value by the given case-insensitive name.
-     *
-     * This method returns an array of all the header values of the given
-     * case-insensitive header name.
-     *
-     * If the header does not appear in the message, this method MUST return an
-     * empty array.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return string[] An array of string values as provided for the given
-     *    header. If the header does not appear in the message, this method MUST
-     *    return an empty array.
-     */
     public function get_header(string $name): array
     {
         return $this->response->getHeader($name);
     }
 
-    /**
-     * Retrieves a comma-separated string of the values for a single header.
-     *
-     * This method returns all of the header values of the given
-     * case-insensitive header name as a string concatenated together using
-     * a comma.
-     *
-     * NOTE: Not all header values may be appropriately represented using
-     * comma concatenation. For such headers, use getHeader() instead
-     * and supply your own delimiter when concatenating.
-     *
-     * If the header does not appear in the message, this method MUST return
-     * an empty string.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return string A string of values as provided for the given header
-     *    concatenated together using a comma. If the header does not appear in
-     *    the message, this method MUST return an empty string.
-     */
     public function get_header_line(string $name): string
     {
         return $this->response->getHeaderLine($name);
     }
 
-    /**
-     * get the body as string
-     *
-     * @return string
-     */
     public function get_body_content(): string
     {
         return $this->response->getBody()->__toString();

+ 0 - 121
lib/simplepie/simplepie/src/HTTP/RawTextResponse.php

@@ -39,162 +39,41 @@ final class RawTextResponse implements Response
         $this->requested_url = $filepath;
     }
 
-    /**
-     * Return the string representation of the permanent URI of the requested resource
-     * (the first location after a prefix of (only) permanent redirects).
-     *
-     * Depending on which components of the URI are present, the resulting
-     * string is either a full URI or relative reference according to RFC 3986,
-     * Section 4.1. The method concatenates the various components of the URI,
-     * using the appropriate delimiters:
-     *
-     * - If a scheme is present, it MUST be suffixed by ":".
-     * - If an authority is present, it MUST be prefixed by "//".
-     * - The path can be concatenated without delimiters. But there are two
-     *   cases where the path has to be adjusted to make the URI reference
-     *   valid as PHP does not allow to throw an exception in __toString():
-     *     - If the path is rootless and an authority is present, the path MUST
-     *       be prefixed by "/".
-     *     - If the path is starting with more than one "/" and no authority is
-     *       present, the starting slashes MUST be reduced to one.
-     * - If a query is present, it MUST be prefixed by "?".
-     * - If a fragment is present, it MUST be prefixed by "#".
-     *
-     * @see http://tools.ietf.org/html/rfc3986#section-4.1
-     */
     public function get_permanent_uri(): string
     {
         return $this->permanent_url;
     }
 
-    /**
-     * Return the string representation of the final requested URL after following all redirects.
-     *
-     * Depending on which components of the URI are present, the resulting
-     * string is either a full URI or relative reference according to RFC 3986,
-     * Section 4.1. The method concatenates the various components of the URI,
-     * using the appropriate delimiters:
-     *
-     * - If a scheme is present, it MUST be suffixed by ":".
-     * - If an authority is present, it MUST be prefixed by "//".
-     * - The path can be concatenated without delimiters. But there are two
-     *   cases where the path has to be adjusted to make the URI reference
-     *   valid as PHP does not allow to throw an exception in __toString():
-     *     - If the path is rootless and an authority is present, the path MUST
-     *       be prefixed by "/".
-     *     - If the path is starting with more than one "/" and no authority is
-     *       present, the starting slashes MUST be reduced to one.
-     * - If a query is present, it MUST be prefixed by "?".
-     * - If a fragment is present, it MUST be prefixed by "#".
-     *
-     * @see http://tools.ietf.org/html/rfc3986#section-4.1
-     */
     public function get_final_requested_uri(): string
     {
         return $this->requested_url;
     }
 
-    /**
-     * Gets the response status code.
-     *
-     * The status code is a 3-digit integer result code of the server's attempt
-     * to understand and satisfy the request.
-     *
-     * @return int Status code.
-     */
     public function get_status_code(): int
     {
         return 200;
     }
 
-    /**
-     * Retrieves all message header values.
-     *
-     * The keys represent the header name as it will be sent over the wire, and
-     * each value is an array of strings associated with the header.
-     *
-     *     // Represent the headers as a string
-     *     foreach ($message->get_headers() as $name => $values) {
-     *         echo $name . ': ' . implode(', ', $values);
-     *     }
-     *
-     *     // Emit headers iteratively:
-     *     foreach ($message->get_headers() as $name => $values) {
-     *         foreach ($values as $value) {
-     *             header(sprintf('%s: %s', $name, $value), false);
-     *         }
-     *     }
-     *
-     * @return string[][] Returns an associative array of the message's headers.
-     *     Each key MUST be a header name, and each value MUST be an array of
-     *     strings for that header.
-     */
     public function get_headers(): array
     {
         return [];
     }
 
-    /**
-     * Checks if a header exists by the given case-insensitive name.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return bool Returns true if any header names match the given header
-     *     name using a case-insensitive string comparison. Returns false if
-     *     no matching header name is found in the message.
-     */
     public function has_header(string $name): bool
     {
         return false;
     }
 
-    /**
-     * Retrieves a message header value by the given case-insensitive name.
-     *
-     * This method returns an array of all the header values of the given
-     * case-insensitive header name.
-     *
-     * If the header does not appear in the message, this method MUST return an
-     * empty array.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return string[] An array of string values as provided for the given
-     *    header. If the header does not appear in the message, this method MUST
-     *    return an empty array.
-     */
     public function get_header(string $name): array
     {
         return [];
     }
 
-    /**
-     * Retrieves a comma-separated string of the values for a single header.
-     *
-     * This method returns all of the header values of the given
-     * case-insensitive header name as a string concatenated together using
-     * a comma.
-     *
-     * NOTE: Not all header values may be appropriately represented using
-     * comma concatenation. For such headers, use getHeader() instead
-     * and supply your own delimiter when concatenating.
-     *
-     * If the header does not appear in the message, this method MUST return
-     * an empty string.
-     *
-     * @param string $name Case-insensitive header field name.
-     * @return string A string of values as provided for the given header
-     *    concatenated together using a comma. If the header does not appear in
-     *    the message, this method MUST return an empty string.
-     */
     public function get_header_line(string $name): string
     {
         return '';
     }
 
-    /**
-     * get the body as string
-     *
-     * @return string
-     */
     public function get_body_content(): string
     {
         return $this->raw_text;

+ 19 - 16
lib/simplepie/simplepie/src/Item.php

@@ -127,7 +127,7 @@ class Item implements RegistryAware
      * @param array<string, mixed> $element
      * @see get_base
      */
-    protected function get_own_base(array $element = []): string
+    private function get_own_base(array $element = []): string
     {
         if (!empty($element['xml_base_explicit']) && isset($element['xml_base'])) {
             return $element['xml_base'];
@@ -1221,11 +1221,11 @@ class Item implements RegistryAware
             // PLAYER
             if ($player_parent = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'player')) {
                 if (isset($player_parent[0]['attribs']['']['url'])) {
-                    $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($player_parent[0]));
+                    $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($player_parent[0]));
                 }
             } elseif ($player_parent = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'player')) {
                 if (isset($player_parent[0]['attribs']['']['url'])) {
-                    $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($player_parent[0]));
+                    $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($player_parent[0]));
                 }
             }
 
@@ -1345,13 +1345,13 @@ class Item implements RegistryAware
             if ($thumbnails = $this->get_item_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) {
                 foreach ($thumbnails as $thumbnail) {
                     if (isset($thumbnail['attribs']['']['url'])) {
-                        $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($thumbnail));
+                        $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
                     }
                 }
             } elseif ($thumbnails = $parent->get_channel_tags(\SimplePie\SimplePie::NAMESPACE_MEDIARSS, 'thumbnail')) {
                 foreach ($thumbnails as $thumbnail) {
                     if (isset($thumbnail['attribs']['']['url'])) {
-                        $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($thumbnail));
+                        $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
                     }
                 }
             }
@@ -1475,7 +1475,7 @@ class Item implements RegistryAware
                             if (isset($content['attribs']['']['width'])) {
                                 $width = $this->sanitize($content['attribs']['']['width'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
                             }
-                            $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($content));
+                            $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($content));
 
                             // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
 
@@ -1734,9 +1734,11 @@ class Item implements RegistryAware
 
                             // PLAYER
                             if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) {
-                                $player = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player']));
+                                $playerElem = $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0];
+                                $player = $this->sanitize($playerElem['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($playerElem));
                             } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) {
-                                $player = $this->sanitize($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player']));
+                                $playerElem = $group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0];
+                                $player = $this->sanitize($playerElem['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($playerElem));
                             } else {
                                 $player = $player_parent;
                             }
@@ -1826,14 +1828,14 @@ class Item implements RegistryAware
                             // THUMBNAILS
                             if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) {
                                 foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) {
-                                    $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($thumbnail));
+                                    $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
                                 }
                                 if (is_array($thumbnails)) {
                                     $thumbnails = array_values(array_unique($thumbnails));
                                 }
                             } elseif (isset($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) {
                                 foreach ($group['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) {
-                                    $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($thumbnail));
+                                    $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
                                 }
                                 if (is_array($thumbnails)) {
                                     $thumbnails = array_values(array_unique($thumbnails));
@@ -1931,7 +1933,7 @@ class Item implements RegistryAware
                             $width = $this->sanitize($content['attribs']['']['width'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
                         }
                         if (isset($content['attribs']['']['url'])) {
-                            $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($content));
+                            $url = $this->sanitize($content['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($content));
                         }
                         // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
 
@@ -2086,7 +2088,8 @@ class Item implements RegistryAware
                         // PLAYER
                         if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'])) {
                             if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'])) {
-                                $player = $this->sanitize($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0]));
+                                $playerElem = $content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['player'][0];
+                                $player = $this->sanitize($playerElem['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($playerElem));
                             }
                         } else {
                             $player = $player_parent;
@@ -2142,7 +2145,7 @@ class Item implements RegistryAware
                         if (isset($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'])) {
                             foreach ($content['child'][\SimplePie\SimplePie::NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail) {
                                 if (isset($thumbnail['attribs']['']['url'])) {
-                                    $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($thumbnail));
+                                    $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($thumbnail));
                                 }
                             }
                             if (is_array($thumbnails)) {
@@ -2182,7 +2185,7 @@ class Item implements RegistryAware
                     $url = null;
                     $width = null;
 
-                    $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link));
+                    $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($link));
                     if (isset($link['attribs']['']['type'])) {
                         $type = $this->sanitize($link['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
                     }
@@ -2218,7 +2221,7 @@ class Item implements RegistryAware
                     $url = null;
                     $width = null;
 
-                    $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($link));
+                    $url = $this->sanitize($link['attribs']['']['href'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($link));
                     if (isset($link['attribs']['']['type'])) {
                         $type = $this->sanitize($link['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);
                     }
@@ -2249,7 +2252,7 @@ class Item implements RegistryAware
                     $url = null;
                     $width = null;
 
-                    $url = $this->sanitize($enclosure['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_base($enclosure));
+                    $url = $this->sanitize($enclosure['attribs']['']['url'], \SimplePie\SimplePie::CONSTRUCT_IRI, $this->get_own_base($enclosure));
                     $url = $this->get_sanitize()->https_url($url);
                     if (isset($enclosure['attribs']['']['type'])) {
                         $type = $this->sanitize($enclosure['attribs']['']['type'], \SimplePie\SimplePie::CONSTRUCT_TEXT);

+ 4 - 4
lib/simplepie/simplepie/src/Locator.php

@@ -11,8 +11,8 @@ use DomDocument;
 use Psr\Http\Client\ClientInterface;
 use Psr\Http\Message\RequestFactoryInterface;
 use Psr\Http\Message\UriFactoryInterface;
-use SimplePie\Exception\HttpException;
 use SimplePie\HTTP\Client;
+use SimplePie\HTTP\ClientException;
 use SimplePie\HTTP\FileClient;
 use SimplePie\HTTP\Psr18Client;
 use SimplePie\HTTP\Response;
@@ -263,7 +263,7 @@ class Locator implements RegistryAware
                         if ((!Misc::is_remote_uri($feed->get_final_requested_uri()) || ($feed->get_status_code() === 200 || $feed->get_status_code() > 206 && $feed->get_status_code() < 300)) && $this->is_feed($feed, true)) {
                             $feeds[$href] = $feed;
                         }
-                    } catch (HttpException $th) {
+                    } catch (ClientException $th) {
                         // Just mark it as done and continue.
                     }
                 }
@@ -388,7 +388,7 @@ class Locator implements RegistryAware
                     if ((!Misc::is_remote_uri($feed->get_final_requested_uri()) || ($feed->get_status_code() === 200 || $feed->get_status_code() > 206 && $feed->get_status_code() < 300)) && $this->is_feed($feed)) {
                         return [$feed];
                     }
-                } catch (HttpException $th) {
+                } catch (ClientException $th) {
                     // Just unset and continue.
                 }
 
@@ -420,7 +420,7 @@ class Locator implements RegistryAware
                     if ((!Misc::is_remote_uri($feed->get_final_requested_uri()) || ($feed->get_status_code() === 200 || $feed->get_status_code() > 206 && $feed->get_status_code() < 300)) && $this->is_feed($feed)) {
                         return [$feed];
                     }
-                } catch (HttpException $th) {
+                } catch (ClientException $th) {
                     // Just unset and continue.
                 }
 

+ 15 - 2
lib/simplepie/simplepie/src/Misc.php

@@ -105,11 +105,14 @@ class Misc
     }
 
     /**
+     * @deprecated since SimplePie 1.9.0. If you need it, you can copy the function to your codebase. But you should consider using `DOMDocument` for any DOM wrangling.
      * @param array{tag: string, self_closing: bool, attribs: array<string, array{data: string}>, content: string} $element
      * @return string
      */
     public static function element_implode(array $element)
     {
+        // trigger_error(sprintf('Using method "' . __METHOD__ . '" is deprecated since SimplePie 1.9.'), \E_USER_DEPRECATED);
+
         $full = "<{$element['tag']}";
         foreach ($element['attribs'] as $key => $value) {
             $key = strtolower($key);
@@ -250,6 +253,7 @@ class Misc
     }
 
     /**
+     * @deprecated since SimplePie 1.9.0. This functionality is part of `IRI` – if you need it standalone, consider copying the function to your codebase.
      * @param array<int, string> $match
      * @return string
      */
@@ -1712,11 +1716,14 @@ class Misc
     /**
      * Strip HTML comments
      *
+     * @deprecated since SimplePie 1.9.0. If you need it, you can copy the function to your codebase. But you should consider using `DOMDocument` for any DOM wrangling.
      * @param string $data Data to strip comments from
      * @return string Comment stripped string
      */
     public static function strip_comments(string $data)
     {
+        // trigger_error(sprintf('Using method "' . __METHOD__ . '" is deprecated since SimplePie 1.9.'), \E_USER_DEPRECATED);
+
         $output = '';
         while (($start = strpos($data, '<!--')) !== false) {
             $output .= substr($data, 0, $start);
@@ -1756,11 +1763,14 @@ class Misc
     /**
      * Remove RFC822 comments
      *
+     * @deprecated since SimplePie 1.9.0. If you need it, consider copying the function to your codebase.
      * @param string $string Data to strip comments from
      * @return string Comment stripped string
      */
     public static function uncomment_rfc822(string $string)
     {
+        // trigger_error(sprintf('Using method "' . __METHOD__ . '" is deprecated since SimplePie 1.9.'), \E_USER_DEPRECATED);
+
         $position = 0;
         $length = strlen($string);
         $depth = 0;
@@ -1848,7 +1858,7 @@ class Misc
 
     /**
      * @param array<string, array<string, string>> $attribs
-     * @return int
+     * @return int-mask-of<SimplePie::CONSTRUCT_*>
      */
     public static function atom_10_construct_type(array $attribs)
     {
@@ -1872,7 +1882,7 @@ class Misc
 
     /**
      * @param array<string, array<string, string>> $attribs
-     * @return int
+     * @return int-mask-of<SimplePie::CONSTRUCT_*>
      */
     public static function atom_10_content_construct_type(array $attribs)
     {
@@ -1964,12 +1974,15 @@ class Misc
      * Returns an associative array of name/value pairs, where the value is an
      * array of values that have used the same name
      *
+     * @deprecated since SimplePie 1.9.0. If you need it, consider copying the function to your codebase.
      * @static
      * @param string $str The input string.
      * @return array<string, array<string|null>>
      */
     public static function parse_str(string $str)
     {
+        // trigger_error(sprintf('Using method "' . __METHOD__ . '" is deprecated since SimplePie 1.9.'), \E_USER_DEPRECATED);
+
         $return = [];
         $str = explode('&', $str);
 

Plik diff jest za duży
+ 12 - 7
lib/simplepie/simplepie/src/Parser.php


+ 2 - 2
lib/simplepie/simplepie/src/Sanitize.php

@@ -18,8 +18,8 @@ use SimplePie\Cache\BaseDataCache;
 use SimplePie\Cache\CallableNameFilter;
 use SimplePie\Cache\DataCache;
 use SimplePie\Cache\NameFilter;
-use SimplePie\Exception\HttpException;
 use SimplePie\HTTP\Client;
+use SimplePie\HTTP\ClientException;
 use SimplePie\HTTP\FileClient;
 use SimplePie\HTTP\Psr18Client;
 
@@ -504,7 +504,7 @@ class Sanitize implements RegistryAware
                                         $img->getAttribute('src'),
                                         ['X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']]
                                     );
-                                } catch (HttpException $th) {
+                                } catch (ClientException $th) {
                                     continue;
                                 }
 

+ 5 - 5
lib/simplepie/simplepie/src/SimplePie.php

@@ -20,8 +20,8 @@ use SimplePie\Cache\NameFilter;
 use SimplePie\Cache\Psr16;
 use SimplePie\Content\Type\Sniffer;
 use SimplePie\Exception as SimplePieException;
-use SimplePie\Exception\HttpException;
 use SimplePie\HTTP\Client;
+use SimplePie\HTTP\ClientException;
 use SimplePie\HTTP\FileClient;
 use SimplePie\HTTP\Psr18Client;
 use SimplePie\HTTP\Response;
@@ -1997,7 +1997,7 @@ class SimplePie
                         try {
                             $file = $this->get_http_client()->request(Client::METHOD_GET, $this->feed_url, $headers);
                             $this->status_code = $file->get_status_code();
-                        } catch (HttpException $th) {
+                        } catch (ClientException $th) {
                             $this->check_modified = false;
                             $this->status_code = $th->getCode(); // FreshRSS https://github.com/simplepie/simplepie/pull/905
 
@@ -2090,7 +2090,7 @@ class SimplePie
                 ];
                 try {
                     $file = $this->get_http_client()->request(Client::METHOD_GET, $this->feed_url, $headers);
-                } catch (HttpException $th) {
+                } catch (ClientException $th) {
                     // If the file connection has an error, set SimplePie::error to that and quit
                     $this->error = $th->getMessage();
                     $this->status_code = $th->getCode(); // FreshRSS https://github.com/simplepie/simplepie/pull/905
@@ -2605,10 +2605,10 @@ class SimplePie
         if (!empty($element['xml_base_explicit']) && isset($element['xml_base'])) {
             return $element['xml_base'];
         }
-        if (($link = $this->get_link(0, 'self')) !== null) {
+        if (($link = $this->get_link(0, 'alternate')) !== null) {
             return $link;
         }
-        if (($link = $this->get_link(0, 'alternate')) !== null) {
+        if (($link = $this->get_link(0, 'self')) !== null) {
             return $link;
         }
 

+ 7 - 0
lib/simplepie/simplepie/utils/PHPStan/README.md

@@ -0,0 +1,7 @@
+# SimplePie PHPStan extension
+
+**This extension is considered unstable, use at your own risk.**
+
+It provides:
+
+- Correct return type for `Registry::call()`

+ 101 - 0
lib/simplepie/simplepie/utils/PHPStan/RegistryCallMethodReturnTypeExtension.php

@@ -0,0 +1,101 @@
+<?php
+
+// SPDX-FileCopyrightText: 2024 Jan Tojnar
+// SPDX-License-Identifier: BSD-3-Clause
+
+declare(strict_types=1);
+
+namespace SimplePieUtils\PHPStan;
+
+use PHPStan\Analyser\Scope;
+use PHPStan\Reflection\MethodReflection;
+use PHPStan\Reflection\ParametersAcceptorSelector;
+use PHPStan\Type\DynamicMethodReturnTypeExtension;
+use PHPStan\Type\Type;
+use PHPStan\Reflection\ReflectionProvider;
+use PhpParser\Node\Expr\MethodCall;
+use PHPStan\Type\Constant\ConstantStringType;
+use PHPStan\Type\Constant\ConstantArrayType;
+use PHPStan\Type\ArrayType;
+use PHPStan\Type\MixedType;
+
+/**
+ * Fixes return type for `Registry::call()` to match the called method.
+ */
+class RegistryCallMethodReturnTypeExtension implements DynamicMethodReturnTypeExtension
+{
+    /** @var ReflectionProvider */
+    private $reflectionProvider;
+
+    public function __construct(ReflectionProvider $reflectionProvider)
+    {
+        $this->reflectionProvider = $reflectionProvider;
+    }
+
+    public function getClass(): string
+    {
+        return 'SimplePie\Registry';
+    }
+
+    public function isMethodSupported(MethodReflection $methodReflection): bool
+    {
+        return $methodReflection->getName() === 'call';
+    }
+
+    public function getTypeFromMethodCall(MethodReflection $methodReflection, MethodCall $methodCall, Scope $scope): Type
+    {
+        // The method will be called as `$registry->call($className, $methodName, $arguments)`.
+        $args = $methodCall->getArgs();
+
+        if (count($args) < 2) {
+            // Not enough arguments to determine the return type.
+            return new MixedType();
+        }
+
+        $classNameArg = $args[0]->value;
+        $methodNameArg = $args[1]->value;
+        $argumentsArg = $args[2]->value ?? null;
+
+        $classType = $scope->getType($classNameArg);
+        $methodType = $scope->getType($methodNameArg);
+
+        if (!$classType  instanceof ConstantStringType || !$methodType instanceof ConstantStringType) {
+            return new MixedType();
+        }
+
+        $className = $classType->getValue();
+        if (!$this->reflectionProvider->hasClass($className)) {
+            return new MixedType();
+        }
+
+        $classReflection = $this->reflectionProvider->getClass($className);
+
+        $methodName = $methodType->getValue();
+        if (!$classReflection->hasMethod($methodName)) {
+            return new MixedType();
+        }
+
+        $methodReflection = $classReflection->getMethod($methodName, $scope);
+
+        $argumentTypes = [];
+        if ($argumentsArg !== null) {
+            $argumentsType = $scope->getType($argumentsArg);
+
+            if ($argumentsType instanceof ConstantArrayType) {
+                $argumentTypes = $argumentsType->getValueTypes();
+            } elseif ($argumentsType instanceof ArrayType) {
+                $argumentTypes = [$argumentsType->getItemType()];
+            } else {
+                return new MixedType();
+            }
+        }
+
+        $parametersAcceptor = ParametersAcceptorSelector::selectFromTypes(
+            $argumentTypes,
+            $methodReflection->getVariants(),
+            false
+        );
+
+        return $parametersAcceptor->getReturnType();
+    }
+}

+ 6 - 0
lib/simplepie/simplepie/utils/PHPStan/extension.neon

@@ -0,0 +1,6 @@
+
+services:
+    -
+        class: SimplePieUtils\PHPStan\RegistryCallMethodReturnTypeExtension
+        tags:
+            - phpstan.broker.dynamicMethodReturnTypeExtension

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików