diff options
author | 2023-09-25 21:18:48 +0200 | |
---|---|---|
committer | 2023-09-25 21:18:48 +0200 | |
commit | cd30c25b08dc5ecd048e54c8abbbecd72309ab5e (patch) | |
tree | 5defffb410945e3c4dcff8c2b3b410034588aaba /lib | |
parent | e1b911fc1f3416d49c5ad5cc68587f64ab8890eb (diff) | |
download | rss-bridge-cd30c25b08dc5ecd048e54c8abbbecd72309ab5e.tar.gz rss-bridge-cd30c25b08dc5ecd048e54c8abbbecd72309ab5e.tar.zst rss-bridge-cd30c25b08dc5ecd048e54c8abbbecd72309ab5e.zip |
refactor (#3708)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ActionInterface.php | 21 | ||||
-rw-r--r-- | lib/FeedItem.php | 516 | ||||
-rw-r--r-- | lib/FormatAbstract.php | 120 | ||||
-rw-r--r-- | lib/FormatFactory.php | 2 | ||||
-rw-r--r-- | lib/FormatInterface.php | 77 | ||||
-rw-r--r-- | lib/bootstrap.php | 8 | ||||
-rw-r--r-- | lib/logger.php | 3 |
7 files changed, 155 insertions, 592 deletions
diff --git a/lib/ActionInterface.php b/lib/ActionInterface.php index 4eb9cc65..220dfa50 100644 --- a/lib/ActionInterface.php +++ b/lib/ActionInterface.php @@ -1,28 +1,9 @@ <?php -/** - * This file is part of RSS-Bridge, a PHP project capable of generating RSS and - * Atom feeds for websites that don't have one. - * - * For the full license information, please view the UNLICENSE file distributed - * with this source code. - * - * @package Core - * @license http://unlicense.org/ UNLICENSE - * @link https://github.com/rss-bridge/rss-bridge - */ - -/** - * Interface for action objects. - */ interface ActionInterface { /** - * Execute the action. - * - * Note: This function directly outputs data to the user. - * - * @return ?string + * @return string|Response */ public function execute(array $request); } diff --git a/lib/FeedItem.php b/lib/FeedItem.php index 3d1b4509..4915c1b9 100644 --- a/lib/FeedItem.php +++ b/lib/FeedItem.php @@ -1,129 +1,90 @@ <?php -/** - * This file is part of RSS-Bridge, a PHP project capable of generating RSS and - * Atom feeds for websites that don't have one. - * - * For the full license information, please view the UNLICENSE file distributed - * with this source code. - * - * @package Core - * @license http://unlicense.org/ UNLICENSE - * @link https://github.com/rss-bridge/rss-bridge - */ - -/** - * Represents a simple feed item for transformation into various feed formats. - * - * This class represents a feed item. A feed item is an entity that can be - * transformed into various feed formats. It holds a set of pre-defined - * properties: - * - * - **URI**: URI to the full article (i.e. "https://...") - * - **Title**: The title - * - **Timestamp**: A timestamp of when the item was first released - * - **Author**: Name of the author - * - **Content**: Body of the feed, as text or HTML - * - **Enclosures**: A list of links to media objects (images, videos, etc...) - * - **Categories**: A list of category names or tags to categorize the item - * - * _Note_: A feed item can have any number of additional parameters, all of which - * may or may not be transformed to the selected output format. - * - * _Remarks_: This class supports legacy items via {@see FeedItem::__construct()} - * (i.e. `$feedItem = \FeedItem($item);`). Support for legacy items may be removed - * in future versions of RSS-Bridge. - */ class FeedItem { - /** @var string|null URI to the full article */ - protected $uri = null; - - /** @var string|null Title of the item */ - protected $title = null; - - /** @var int|null Timestamp of when the item was first released */ - protected $timestamp = null; - - /** @var string|null Name of the author */ - protected $author = null; - - /** @var string|null Body of the feed */ - protected $content = null; - - /** @var array List of links to media objects */ - protected $enclosures = []; - - /** @var array List of category names or tags */ - protected $categories = []; - - /** @var string Unique ID for the current item */ - protected $uid = null; + protected ?string $uri = null; + protected ?string $title = null; + protected ?int $timestamp = null; + protected ?string $author = null; + protected ?string $content = null; + protected array $enclosures = []; + protected array $categories = []; + protected ?string $uid = null; + protected array $misc = []; + + public function __construct() + { + } - /** @var array Associative list of additional parameters */ - protected $misc = []; // Custom parameters + public static function fromArray(array $itemArray): self + { + $item = new self(); + foreach ($itemArray as $key => $value) { + $item->__set($key, $value); + } + return $item; + } - /** - * Create object from legacy item. - * - * The provided array must be an associative array of key-value-pairs, where - * keys may correspond to any of the properties of this class. - * - * Example use: - * - * ```PHP - * <?php - * $item = array(); - * - * $item['uri'] = 'https://www.github.com/rss-bridge/rss-bridge/'; - * $item['title'] = 'Title'; - * $item['timestamp'] = strtotime('now'); - * $item['author'] = 'Unknown author'; - * $item['content'] = 'Hello World!'; - * $item['enclosures'] = array('https://github.com/favicon.ico'); - * $item['categories'] = array('php', 'rss-bridge', 'awesome'); - * - * $feedItem = new \FeedItem($item); - * - * ``` - * - * The result of the code above is the same as the code below: - * - * ```PHP - * <?php - * $feedItem = \FeedItem(); - * - * $feedItem->uri = 'https://www.github.com/rss-bridge/rss-bridge/'; - * $feedItem->title = 'Title'; - * $feedItem->timestamp = strtotime('now'); - * $feedItem->autor = 'Unknown author'; - * $feedItem->content = 'Hello World!'; - * $feedItem->enclosures = array('https://github.com/favicon.ico'); - * $feedItem->categories = array('php', 'rss-bridge', 'awesome'); - * ``` - * - * @param array $item (optional) A legacy item (empty: no legacy support). - * @return object A new object of this class - */ - public function __construct($item = []) + public function __set($name, $value) { - if (!is_array($item)) { - Debug::log('Item must be an array!'); + switch ($name) { + case 'uri': + $this->setURI($value); + break; + case 'title': + $this->setTitle($value); + break; + case 'timestamp': + $this->setTimestamp($value); + break; + case 'author': + $this->setAuthor($value); + break; + case 'content': + $this->setContent($value); + break; + case 'enclosures': + $this->setEnclosures($value); + break; + case 'categories': + $this->setCategories($value); + break; + case 'uid': + $this->setUid($value); + break; + default: + $this->addMisc($name, $value); } + } - foreach ($item as $key => $value) { - $this->__set($key, $value); + public function __get($name) + { + switch ($name) { + case 'uri': + return $this->getURI(); + case 'title': + return $this->getTitle(); + case 'timestamp': + return $this->getTimestamp(); + case 'author': + return $this->getAuthor(); + case 'content': + return $this->getContent(); + case 'enclosures': + return $this->getEnclosures(); + case 'categories': + return $this->getCategories(); + case 'uid': + return $this->getUid(); + default: + if (array_key_exists($name, $this->misc)) { + return $this->misc[$name]; + } + return null; } } - /** - * Get current URI. - * - * Use {@see FeedItem::setURI()} to set the URI. - * - * @return string|null The URI or null if it hasn't been set. - */ - public function getURI() + public function getURI(): ?string { return $this->uri; } @@ -138,8 +99,7 @@ class FeedItem * _Remarks_: Uses the attribute "href" or "src" if the provided URI is an * object of simple_html_dom_node. * - * @param object|string $uri URI to the full article. - * @return self + * @param simple_html_dom_node|object|string $uri URI to the full article. */ public function setURI($uri) { @@ -156,325 +116,174 @@ class FeedItem } if (!is_string($uri)) { Debug::log(sprintf('Expected $uri to be string but got %s', gettype($uri))); - return $this; + return; } $uri = trim($uri); // Intentionally doing a weak url validation here because FILTER_VALIDATE_URL is too strict if (!preg_match('#^https?://#i', $uri)) { Debug::log(sprintf('Not a valid url: "%s"', $uri)); - return $this; + return; } $this->uri = $uri; - return $this; } - /** - * Get current title. - * - * Use {@see FeedItem::setTitle()} to set the title. - * - * @return string|null The current title or null if it hasn't been set. - */ - public function getTitle() + public function getTitle(): ?string { return $this->title; } - /** - * Set title. - * - * Use {@see FeedItem::getTitle()} to get the title. - * - * _Note_: Removes whitespace from beginning and end of the title. - * - * @param string $title The title - * @return self - */ public function setTitle($title) { - $this->title = null; // Clear previous data - + $this->title = null; if (!is_string($title)) { Debug::log('Title must be a string!'); } else { $this->title = truncate(trim($title)); } - - return $this; } - /** - * Get current timestamp. - * - * Use {@see FeedItem::setTimestamp()} to set the timestamp. - * - * @return int|null The current timestamp or null if it hasn't been set. - */ - public function getTimestamp() + public function getTimestamp(): ?int { return $this->timestamp; } - /** - * Set timestamp of first release. - * - * _Note_: The timestamp should represent the number of seconds since - * January 1 1970 00:00:00 GMT (Unix time). - * - * _Remarks_: If the provided timestamp is a string (not numeric), this - * function automatically attempts to parse the string using - * [strtotime](http://php.net/manual/en/function.strtotime.php) - * - * @link http://php.net/manual/en/function.strtotime.php strtotime (PHP) - * @link https://en.wikipedia.org/wiki/Unix_time Unix time (Wikipedia) - * - * @param string|int $timestamp A timestamp of when the item was first released - * @return self - */ public function setTimestamp($timestamp) { - $this->timestamp = null; // Clear previous data - + $this->timestamp = null; if ( !is_numeric($timestamp) && !$timestamp = strtotime($timestamp) ) { Debug::log('Unable to parse timestamp!'); } - if ($timestamp <= 0) { Debug::log('Timestamp must be greater than zero!'); } else { $this->timestamp = $timestamp; } - - return $this; } - /** - * Get the current author name. - * - * Use {@see FeedItem::setAuthor()} to set the author. - * - * @return string|null The author or null if it hasn't been set. - */ - public function getAuthor() + public function getAuthor(): ?string { return $this->author; } - /** - * Set the author name. - * - * Use {@see FeedItem::getAuthor()} to get the author. - * - * @param string $author The author name. - * @return self - */ public function setAuthor($author) { - $this->author = null; // Clear previous data - + $this->author = null; if (!is_string($author)) { Debug::log('Author must be a string!'); } else { $this->author = $author; } - return $this; } - /** - * Get item content. - * - * Use {@see FeedItem::setContent()} to set the item content. - * - * @return string|null The item content or null if it hasn't been set. - */ - public function getContent() + public function getContent(): ?string { return $this->content; } /** - * Set item content. - * - * Note: This function casts objects of type simple_html_dom and - * simple_html_dom_node to string. - * - * Use {@see FeedItem::getContent()} to get the current item content. - * * @param string|object $content The item content as text or simple_html_dom object. - * @return self */ public function setContent($content) { - $this->content = null; // Clear previous data - + $this->content = null; if ( $content instanceof simple_html_dom || $content instanceof simple_html_dom_node ) { - $content = (string)$content; + $content = (string) $content; } - if (is_string($content)) { $this->content = $content; } else { Debug::log(sprintf('Feed content must be a string but got %s', gettype($content))); } - - return $this; } - /** - * Get item enclosures. - * - * Use {@see FeedItem::setEnclosures()} to set feed enclosures. - * - * @return array Enclosures as array of enclosure URIs. - */ - public function getEnclosures() + public function getEnclosures(): array { return $this->enclosures; } - /** - * Set item enclosures. - * - * Use {@see FeedItem::getEnclosures()} to get the current item enclosures. - * - * @param array $enclosures Array of enclosures, where each element links to - * one enclosure. - * @return self - */ public function setEnclosures($enclosures) { $this->enclosures = []; - if (is_array($enclosures)) { - foreach ($enclosures as $enclosure) { - if ( - !filter_var( - $enclosure, - FILTER_VALIDATE_URL, - FILTER_FLAG_PATH_REQUIRED - ) - ) { - Debug::log('Each enclosure must contain a scheme, host and path!'); - } elseif (!in_array($enclosure, $this->enclosures)) { - $this->enclosures[] = $enclosure; - } - } - } else { + if (!is_array($enclosures)) { Debug::log('Enclosures must be an array!'); + return; + } + foreach ($enclosures as $enclosure) { + if ( + !filter_var( + $enclosure, + FILTER_VALIDATE_URL, + FILTER_FLAG_PATH_REQUIRED + ) + ) { + Debug::log('Each enclosure must contain a scheme, host and path!'); + } elseif (!in_array($enclosure, $this->enclosures)) { + $this->enclosures[] = $enclosure; + } } - - return $this; } - /** - * Get item categories. - * - * Use {@see FeedItem::setCategories()} to set item categories. - * - * @param array The item categories. - */ - public function getCategories() + public function getCategories(): array { return $this->categories; } - /** - * Set item categories. - * - * Use {@see FeedItem::getCategories()} to get the current item categories. - * - * @param array $categories Array of categories, where each element defines - * a single category name. - * @return self - */ public function setCategories($categories) { $this->categories = []; - if (is_array($categories)) { - foreach ($categories as $category) { - if (!is_string($category)) { - Debug::log('Category must be a string!'); - } else { - $this->categories[] = $category; - } - } - } else { + if (!is_array($categories)) { Debug::log('Categories must be an array!'); + return; + } + foreach ($categories as $category) { + if (is_string($category)) { + $this->categories[] = $category; + } else { + Debug::log('Category must be a string!'); + } } - - return $this; } - /** - * Get unique id - * - * Use {@see FeedItem::setUid()} to set the unique id. - * - * @param string The unique id. - */ - public function getUid() + public function getUid(): ?string { return $this->uid; } - /** - * Set unique id. - * - * Use {@see FeedItem::getUid()} to get the unique id. - * - * @param string $uid A string that uniquely identifies the current item - * @return self - */ public function setUid($uid) { - $this->uid = null; // Clear previous data - + $this->uid = null; if (!is_string($uid)) { Debug::log('Unique id must be a string!'); } elseif (preg_match('/^[a-f0-9]{40}$/', $uid)) { - // keep id if it already is a SHA-1 hash + // keep id if it already is SHA-1 hash $this->uid = $uid; } else { $this->uid = sha1($uid); } - - return $this; } - /** - * Add miscellaneous elements to the item. - * - * @param string $key Name of the element. - * @param mixed $value Value of the element. - * @return self - */ - public function addMisc($key, $value) + public function addMisc($name, $value) { - if (!is_string($key)) { + if (!is_string($name)) { Debug::log('Key must be a string!'); - } elseif (in_array($key, get_object_vars($this))) { + } elseif (in_array($name, get_object_vars($this))) { Debug::log('Key must be unique!'); } else { - $this->misc[$key] = $value; + $this->misc[$name] = $value; } - return $this; } - /** - * Transform current object to array - * - * @return array - */ - public function toArray() + public function toArray(): array { return array_merge( [ @@ -490,87 +299,4 @@ class FeedItem $this->misc ); } - - /** - * Set item property - * - * Allows simple assignment to parameters. This method is slower, but easier - * to implement in some cases: - * - * ```PHP - * $item = new \FeedItem(); - * $item->content = 'Hello World!'; - * $item->my_id = 42; - * ``` - * - * @param string $name Property name - * @param mixed $value Property value - */ - public function __set($name, $value) - { - switch ($name) { - case 'uri': - $this->setURI($value); - break; - case 'title': - $this->setTitle($value); - break; - case 'timestamp': - $this->setTimestamp($value); - break; - case 'author': - $this->setAuthor($value); - break; - case 'content': - $this->setContent($value); - break; - case 'enclosures': - $this->setEnclosures($value); - break; - case 'categories': - $this->setCategories($value); - break; - case 'uid': - $this->setUid($value); - break; - default: - $this->addMisc($name, $value); - } - } - - /** - * Get item property - * - * Allows simple assignment to parameters. This method is slower, but easier - * to implement in some cases. - * - * @param string $name Property name - * @return mixed Property value - */ - public function __get($name) - { - switch ($name) { - case 'uri': - return $this->getURI(); - case 'title': - return $this->getTitle(); - case 'timestamp': - return $this->getTimestamp(); - case 'author': - return $this->getAuthor(); - case 'content': - return $this->getContent(); - case 'enclosures': - return $this->getEnclosures(); - case 'categories': - return $this->getCategories(); - case 'uid': - return $this->getUid(); - default: - if (array_key_exists($name, $this->misc)) { - return $this->misc[$name]; - } - return null; - } - } } diff --git a/lib/FormatAbstract.php b/lib/FormatAbstract.php index 3289d651..0304f627 100644 --- a/lib/FormatAbstract.php +++ b/lib/FormatAbstract.php @@ -1,132 +1,70 @@ <?php -/** - * This file is part of RSS-Bridge, a PHP project capable of generating RSS and - * Atom feeds for websites that don't have one. - * - * For the full license information, please view the UNLICENSE file distributed - * with this source code. - * - * @package Core - * @license https://unlicense.org/ UNLICENSE - * @link https://github.com/rss-bridge/rss-bridge - */ - -/** - * An abstract class for format implementations - * - * This class implements {@see FormatInterface} - */ -abstract class FormatAbstract implements FormatInterface +abstract class FormatAbstract { - /** The default charset (UTF-8) */ - const DEFAULT_CHARSET = 'UTF-8'; - - /** MIME type of format output */ const MIME_TYPE = 'text/plain'; - /** @var string $charset The charset */ - protected $charset; + protected string $charset = 'UTF-8'; + protected array $items = []; + protected int $lastModified; + protected array $extraInfos = []; - /** @var array $items The items */ - protected $items; + abstract public function stringify(); - /** - * @var int $lastModified A timestamp to indicate the last modified time of - * the output data. - */ - protected $lastModified; - - /** @var array $extraInfos The extra infos */ - protected $extraInfos; - - /** {@inheritdoc} */ - public function getMimeType() + public function getMimeType(): string { return static::MIME_TYPE; } - /** - * {@inheritdoc} - * - * @param string $charset {@inheritdoc} - */ - public function setCharset($charset) + public function setCharset(string $charset) { $this->charset = $charset; - - return $this; } - /** {@inheritdoc} */ - public function getCharset() + public function getCharset(): string { - $charset = $this->charset; - - if (is_null($charset)) { - return static::DEFAULT_CHARSET; - } - return $charset; + return $this->charset; } - /** - * Set the last modified time - * - * @param int $lastModified The last modified time - * @return void - */ - public function setLastModified($lastModified) + public function setLastModified(int $lastModified) { $this->lastModified = $lastModified; } - /** - * {@inheritdoc} - * - * @param array $items {@inheritdoc} - */ public function setItems(array $items) { $this->items = $items; - - return $this; } - /** {@inheritdoc} */ - public function getItems() + /** + * @return FeedItem[] The items + */ + public function getItems(): array { - if (!is_array($this->items)) { - throw new \LogicException(sprintf('Feed the %s with "setItems" method before !', get_class($this))); - } - return $this->items; } - /** - * {@inheritdoc} - * - * @param array $extraInfos {@inheritdoc} - */ - public function setExtraInfos(array $extraInfos = []) + public function setExtraInfos(array $infos = []) { - foreach (['name', 'uri', 'icon', 'donationUri'] as $infoName) { - if (!isset($extraInfos[$infoName])) { - $extraInfos[$infoName] = ''; + $extras = [ + 'name', + 'uri', + 'icon', + 'donationUri', + ]; + foreach ($extras as $extra) { + if (!isset($infos[$extra])) { + $infos[$extra] = ''; } } - - $this->extraInfos = $extraInfos; - - return $this; + $this->extraInfos = $infos; } - /** {@inheritdoc} */ - public function getExtraInfos() + public function getExtraInfos(): array { - if (is_null($this->extraInfos)) { // No extra info ? - $this->setExtraInfos(); // Define with default value + if (!$this->extraInfos) { + $this->setExtraInfos(); } - return $this->extraInfos; } } diff --git a/lib/FormatFactory.php b/lib/FormatFactory.php index d27d7d6a..9cded40f 100644 --- a/lib/FormatFactory.php +++ b/lib/FormatFactory.php @@ -33,7 +33,7 @@ class FormatFactory * @throws \InvalidArgumentException * @param string $name The name of the format e.g. "Atom", "Mrss" or "Json" */ - public function create(string $name): FormatInterface + public function create(string $name): FormatAbstract { if (! preg_match('/^[a-zA-Z0-9-]*$/', $name)) { throw new \InvalidArgumentException('Format name invalid!'); diff --git a/lib/FormatInterface.php b/lib/FormatInterface.php deleted file mode 100644 index 49e36933..00000000 --- a/lib/FormatInterface.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -/** - * This file is part of RSS-Bridge, a PHP project capable of generating RSS and - * Atom feeds for websites that don't have one. - * - * For the full license information, please view the UNLICENSE file distributed - * with this source code. - * - * @package Core - * @license http://unlicense.org/ UNLICENSE - * @link https://github.com/rss-bridge/rss-bridge - */ - -/** - * The format interface - * - * @todo Add missing function to the interface - * @todo Explain parameters and return values in more detail - * @todo Return self more often (to allow call chaining) - */ -interface FormatInterface -{ - /** - * Generate a string representation of the current data - * - * @return string The string representation - */ - public function stringify(); - - public function setItems(array $items); - - /** - * Return items - * - * @throws \LogicException if the items are not set - * @return FeedItem[] The items - */ - public function getItems(); - - /** - * Set extra information - * - * @param array $infos Extra information - * @return self The format object - */ - public function setExtraInfos(array $infos); - - /** - * Return extra information - * - * @return array Extra information - */ - public function getExtraInfos(); - - /** - * Return MIME type - * - * @return string The MIME type - */ - public function getMimeType(); - - /** - * Set charset - * - * @param string $charset The charset - * @return self The format object - */ - public function setCharset($charset); - - /** - * Return current charset - * - * @return string The charset - */ - public function getCharset(); -} diff --git a/lib/bootstrap.php b/lib/bootstrap.php index dc1c0f04..bc584541 100644 --- a/lib/bootstrap.php +++ b/lib/bootstrap.php @@ -12,20 +12,12 @@ * @link https://github.com/rss-bridge/rss-bridge */ -/** Path to the root folder of RSS-Bridge (where index.php is located) */ -const PATH_ROOT = __DIR__ . '/../'; - -/** Path to the bridges library */ - /** Path to the formats library */ const PATH_LIB_FORMATS = __DIR__ . '/../formats/'; /** Path to the caches library */ const PATH_LIB_CACHES = __DIR__ . '/../caches/'; -/** Path to the actions library */ -const PATH_LIB_ACTIONS = __DIR__ . '/../actions/'; - /** Path to the cache folder */ const PATH_CACHE = __DIR__ . '/../cache/'; diff --git a/lib/logger.php b/lib/logger.php index ed1f1179..5d95e673 100644 --- a/lib/logger.php +++ b/lib/logger.php @@ -148,6 +148,9 @@ final class StreamHandler $context ); error_log($text); + if (Debug::isEnabled()) { + print sprintf("<pre>%s</pre>\n", e($text)); + } //$bytes = file_put_contents('/tmp/rss-bridge.log', $text, FILE_APPEND | LOCK_EX); } } |