From 9b588562da7ca04a0f45cdc033bb892c9d3670d8 Mon Sep 17 00:00:00 2001 From: Netkas Date: Sun, 13 Aug 2023 18:09:44 -0400 Subject: [PATCH] Initial Commit --- .gitignore | 1 + .gitlab-ci.yml | 46 ++ .idea/.gitignore | 8 + .idea/RssLib.iml | 11 + .idea/inspectionProfiles/Project_Default.xml | 29 ++ .idea/modules.xml | 8 + .idea/php.xml | 20 + .idea/runConfigurations/Build.xml | 10 + .idea/runConfigurations/Clean.xml | 8 + .idea/runConfigurations/Install.xml | 10 + .idea/vcs.xml | 6 + LICENSE | 14 + Makefile | 8 + README.md | 82 ++++ project.json | 29 ++ src/RssLib/Classes/Utilities.php | 85 ++++ src/RssLib/Exceptions/RssFeedException.php | 10 + .../SerializableObjectInterface.php | 21 + src/RssLib/Objects/RssChannel.php | 400 ++++++++++++++++++ src/RssLib/Objects/RssChannel/Image.php | 159 +++++++ src/RssLib/Objects/RssChannel/TextInput.php | 113 +++++ src/RssLib/Objects/RssFeed/Enclosure.php | 96 +++++ src/RssLib/Objects/RssFeed/Guid.php | 84 ++++ src/RssLib/Objects/RssFeed/Source.php | 79 ++++ src/RssLib/Objects/RssItem.php | 253 +++++++++++ src/RssLib/RssLib.php | 70 +++ tests/parse_test.php | 8 + 27 files changed, 1668 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab-ci.yml create mode 100644 .idea/.gitignore create mode 100644 .idea/RssLib.iml create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/php.xml create mode 100644 .idea/runConfigurations/Build.xml create mode 100644 .idea/runConfigurations/Clean.xml create mode 100644 .idea/runConfigurations/Install.xml create mode 100644 .idea/vcs.xml create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README.md create mode 100644 project.json create mode 100644 src/RssLib/Classes/Utilities.php create mode 100644 src/RssLib/Exceptions/RssFeedException.php create mode 100644 src/RssLib/Interfaces/SerializableObjectInterface.php create mode 100644 src/RssLib/Objects/RssChannel.php create mode 100644 src/RssLib/Objects/RssChannel/Image.php create mode 100644 src/RssLib/Objects/RssChannel/TextInput.php create mode 100644 src/RssLib/Objects/RssFeed/Enclosure.php create mode 100644 src/RssLib/Objects/RssFeed/Guid.php create mode 100644 src/RssLib/Objects/RssFeed/Source.php create mode 100644 src/RssLib/Objects/RssItem.php create mode 100644 src/RssLib/RssLib.php create mode 100644 tests/parse_test.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..be6085e --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,46 @@ +image: php:8.1 + +before_script: + # Install some stuff that the image doesn't come with + - apt update -yqq + - apt install git libpq-dev libzip-dev zip make wget gnupg -yqq + + # Install phive + - wget -O phive.phar https://phar.io/releases/phive.phar + - wget -O phive.phar.asc https://phar.io/releases/phive.phar.asc + - gpg --keyserver hkps://keys.openpgp.org --recv-keys 0x9D8A98B29B2D5D79 + - gpg --verify phive.phar.asc phive.phar + - chmod +x phive.phar + - mv phive.phar /usr/local/bin/phive + + # Install phab + - phive install phpab --global --trust-gpg-keys 0x2A8299CE842DD38C + + # Install the latest version of ncc (Nosial Code Compiler) + - git clone https://git.n64.cc/nosial/ncc.git + - cd ncc + - make redist + - php build/src/INSTALL --auto --install-composer + - cd .. && rm -rf ncc + +build: + stage: build + script: + - ncc build --config release --log-level debug + artifacts: + paths: + - build/ + rules: + - if: $CI_COMMIT_BRANCH + +release: + stage: deploy + script: + - ncc build --config release --log-level debug + - > + curl --header "JOB-TOKEN: $CI_JOB_TOKEN" --upload-file build/release/net.nosial.rsslib.ncc "$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/net.nosial.rsslib.ncc/$CI_COMMIT_REF_NAME/net.nosial.rsslib.ncc" + artifacts: + paths: + - build/ + rules: + - if: $CI_COMMIT_TAG \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/RssLib.iml b/.idea/RssLib.iml new file mode 100644 index 0000000..4348106 --- /dev/null +++ b/.idea/RssLib.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..87e5ab9 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,29 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b0c8278 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml new file mode 100644 index 0000000..e84699f --- /dev/null +++ b/.idea/php.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Build.xml b/.idea/runConfigurations/Build.xml new file mode 100644 index 0000000..95671e2 --- /dev/null +++ b/.idea/runConfigurations/Build.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Clean.xml b/.idea/runConfigurations/Clean.xml new file mode 100644 index 0000000..e088b48 --- /dev/null +++ b/.idea/runConfigurations/Clean.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/Install.xml b/.idea/runConfigurations/Install.xml new file mode 100644 index 0000000..d7b5373 --- /dev/null +++ b/.idea/runConfigurations/Install.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7c480d8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ +Copyright 2022-2023 Nosial All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6acca3f --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +build: + ncc build --config="release" --log-level debug + +install: + sudo ncc package install --package="build/release/net.nosial.rsslib.ncc" --skip-dependencies --reinstall -y --log-level debug + +clean: + rm -rf build diff --git a/README.md b/README.md new file mode 100644 index 0000000..7e337d8 --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# RssLib + +RssLib is a library used to parse RSS feeds and return the data in a usable format. + +## Table of contents + + +* [RssLib](#rsslib) + * [Table of contents](#table-of-contents) + * [Installation](#installation) + * [Compile from source](#compile-from-source) + * [Requirements](#requirements) + * [Documentation](#documentation) + * [License](#license) + + + +## Installation + +The library can be installed using ncc: + +```bash +ncc install -p "nosial/libs.rss=latest@n64" +``` + +or by adding the following to your project.json file under the `build.dependencies` section: +```json +{ + "name": "net.nosial.rsslib", + "version": "latest", + "source_type": "remote", + "source": "nosial/libs.rsslib=latest@n64" +} +``` + +If you don't have the n64 source configured, you can add it by running the following command: +```bash +ncc source add --name n64 --type gitlab --host git.n64.cc +``` + +## Compile from source + +To compile the library from source, you need to have [ncc](https://git.n64.cc/nosial/ncc) installed, then run the +following command: + +```bash +ncc build +``` + +## Requirements + +The library requires PHP 8.0 or higher. + +## Documentation + +The library is designed to be used as a dependency in other projects, and as such, does not have a command-line +interface. The library is designed to be used as follows: + +```php +try +{ + $feed = \RssLib\RssLib::getFeed('https://rss.nytimes.com/services/xml/rss/nyt/World.xml'); +} +catch(\RssLib\Exceptions\RssFeedException $e) +{ + echo $e->getMessage(); + exit(1); +} + +print("Title: {$feed->getTitle()}\n"); +print("Description: {$feed->getDescription()}\n"); +foreach($feed->getItems() as $item) +{ + print("Item: {$item->getTitle()}\n"); + print("Description: {$item->getDescription()}\n"); + print("Link: {$item->getLink()}\n"); +} +``` + +## License + +Distributed under the MIT License. See `LICENSE` for more information. \ No newline at end of file diff --git a/project.json b/project.json new file mode 100644 index 0000000..b8efd73 --- /dev/null +++ b/project.json @@ -0,0 +1,29 @@ +{ + "project": { + "compiler": { + "extension": "php", + "minimum_version": "8.0", + "maximum_version": "8.2" + }, + "options": [] + }, + "assembly": { + "name": "RssLib", + "package": "net.nosial.rsslib", + "description": "A library used to parse RSS feeds", + "company": "Nosial", + "copyright": "Copyright (c) 2022-2023 Nosial", + "version": "1.0.0", + "uuid": "f24416e8-39f0-11ee-8dcf-f362baa8b68c" + }, + "build": { + "source_path": "src", + "default_configuration": "release", + "configurations": [ + { + "name": "release", + "output_path": "build/release" + } + ] + } +} \ No newline at end of file diff --git a/src/RssLib/Classes/Utilities.php b/src/RssLib/Classes/Utilities.php new file mode 100644 index 0000000..1e57582 --- /dev/null +++ b/src/RssLib/Classes/Utilities.php @@ -0,0 +1,85 @@ +attributes()) + { + foreach ($element->attributes() as $name => $value) + { + $array[$element->getName() . '_' . $name] = (string)$value; + } + if (trim((string)$element) !== '') + { + $array[$element->getName()] = trim((string)$element); + } + } + + // Handle child elements + $items = []; + foreach ($element->children() as $child) + { + $value = ($child->count() > 0 || $child->attributes()) ? self::xmlToArray($child) : (string)$child; + + if ($child->getName() === 'item') + { + $items[] = $value; + } + else if (isset($array[$child->getName()])) + { + if (!is_array($array[$child->getName()])) + { + $array[$child->getName()] = [$array[$child->getName()]]; + } + + /** @noinspection UnsupportedStringOffsetOperationsInspection */ + $array[$child->getName()][] = $value; + } + else + { + $array[$child->getName()] = $value; + } + } + + if (!empty($items)) + { + $array['item'] = $items; + } + + return $array; + } + + + } \ No newline at end of file diff --git a/src/RssLib/Exceptions/RssFeedException.php b/src/RssLib/Exceptions/RssFeedException.php new file mode 100644 index 0000000..58a153c --- /dev/null +++ b/src/RssLib/Exceptions/RssFeedException.php @@ -0,0 +1,10 @@ +title = (string)$data['title']; + $this->link = (string)$data['link']; + $this->description = (string)$data['description']; + + if(array_key_exists('language', $data)) + { + $this->language = (string)$data['language']; + } + + if(array_key_exists('copyright', $data)) + { + $this->copyright = (string)$data['copyright']; + } + + if(array_key_exists('managingEditor', $data)) + { + $this->managing_editor = (string)$data['managingEditor']; + } + + if(array_key_exists('webMaster', $data)) + { + $this->web_master = (string)$data['webMaster']; + } + + if(array_key_exists('pubDate', $data)) + { + $this->publish_date = Utilities::parseTimestamp((string)$data['pubDate']); + } + + if(array_key_exists('lastBuildDate', $data)) + { + $this->last_build_date = Utilities::parseTimestamp((string)$data['lastBuildDate']); + } + + if(array_key_exists('category', $data)) + { + $this->categories = (array)$data['category']; + } + + if(array_key_exists('generator', $data)) + { + $this->generator = (string)$data['generator']; + } + + if(array_key_exists('docs', $data)) + { + $this->docs = (string)$data['docs']; + } + + if(array_key_exists('cloud', $data)) + { + $this->cloud = (string)$data['cloud']; + } + + if(array_key_exists('ttl', $data)) + { + $this->ttl = (int)$data['ttl']; + } + + if(array_key_exists('image', $data)) + { + $this->image = new Image($data['image']); + } + + if(array_key_exists('textInput', $data)) + { + $this->text_input = new TextInput($data['textInput']); + } + + $this->items = []; + if(array_key_exists('item', $data)) + { + foreach($data['item'] as $item) + { + $this->items[] = new RssItem($item); + } + } + } + + /** + * The name of the channel. It's how people refer to your service. If you have an HTML website that contains + * the same information as your RSS file, the title of your channel should be the same as the title of your + * website. + * + * @return string + */ + public function getTitle(): string + { + return $this->title; + } + + /** + * The URL to the HTML website corresponding to the channel. + * + * @return string + */ + public function getLink(): string + { + return $this->link; + } + + /** + * Phrase or sentence describing the channel. + * + * @return string + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * The language the channel is written in + * + * @return string|null + */ + public function getLanguage(): ?string + { + return $this->language; + } + + /** + * Copyright notice for content in the channel. + * + * @return string|null + */ + public function getCopyright(): ?string + { + return $this->copyright; + } + + /** + * Email address for person responsible for editorial content. + * + * @return string|null + */ + public function getManagingEditor(): ?string + { + return $this->managing_editor; + } + + /** + * Email address for person responsible for technical issues relating to channel. + * + * @return string|null + */ + public function getWebMaster(): ?string + { + return $this->web_master; + } + + /** + * The publication date for the content in the channel + * + * @return int|null + */ + public function getPublishDate(): ?int + { + return $this->publish_date; + } + + /** + * The last time the content of the channel changed. + * + * @return int|null + */ + public function getLastBuildDate(): ?int + { + return $this->last_build_date; + } + + /** + * Specify one or more categories that the channel belongs to + * + * @return string[]|null + */ + public function getCategories(): ?array + { + return $this->categories; + } + + /** + * A string indicating the program used to generate the channel. + * + * @return string|null + */ + public function getGenerator(): ?string + { + return $this->generator; + } + + /** + * A URL that points to the documentation for the format used in the RSS file + * + * @return string|null + */ + public function getDocs(): ?string + { + return $this->docs; + } + + /** + * Allows processes to register with a cloud to be notified of updates to the channel, implementing a + * lightweight publish-subscribe protocol for RSS feeds + * + * @return string|null + */ + public function getCloud(): ?string + { + return $this->cloud; + } + + /** + * ttl stands for time to live. It's a number of minutes that indicates how long a channel can be cached before + * refreshing from the source + * + * @return int|null + */ + public function getTtl(): ?int + { + return $this->ttl; + } + + /** + * Specifies a GIF, JPEG or PNG image that can be displayed with the channel + * + * @return Image|null + */ + public function getImage(): ?Image + { + return $this->image; + } + + /** + * Specifies a text input box that can be displayed with the channel. More info + * + * @return TextInput|null + */ + public function getTextInput(): ?TextInput + { + return $this->text_input; + } + + /** + * The items in the channel + * + * @return RssItem[] + */ + public function getItems(): array + { + return $this->items; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'title' => $this->title, + 'link' => $this->link, + 'description' => $this->description, + 'language' => $this->language, + 'managingEditor' => $this->managing_editor, + 'webMaster' => $this->web_master, + 'pubDate' => $this->publish_date, + 'lastBuildDate' => $this->last_build_date, + 'category' => $this->categories, + 'generator' => $this->generator, + 'docs' => $this->docs, + 'cloud' => $this->cloud, + 'ttl' => $this->ttl, + 'image' => ($this->image) ? $this->image->toArray() : null, + 'textInput' => ($this->text_input) ? $this->text_input->toArray() : null, + 'item' => array_map(static function(RssItem $item) { + return $item->toArray(); + }, $this->items) + ]; + } + + /** + * @inheritDoc + */ + public static function fromArray(array $array): SerializableObjectInterface + { + return new self($array); + } + } \ No newline at end of file diff --git a/src/RssLib/Objects/RssChannel/Image.php b/src/RssLib/Objects/RssChannel/Image.php new file mode 100644 index 0000000..3761e5d --- /dev/null +++ b/src/RssLib/Objects/RssChannel/Image.php @@ -0,0 +1,159 @@ +url = (string)$data['url']; + $this->title = (string)$data['title']; + $this->link = (string)$data['link']; + + if(array_key_exists('width', $data)) + { + $this->width = (int)$data['width']; + } + + if(array_key_exists('height', $data)) + { + $this->height = (int)$data['height']; + } + + if(array_key_exists('description', $data)) + { + $this->description = (string)$data['description']; + } + } + + /** + * the URL of a GIF, JPEG or PNG image that represents the channel. + * + * @return string + */ + public function getUrl(): string + { + return $this->url; + } + + /** + * describes the image, it's used in the ALT attribute of the HTML tag when the channel is rendered in HTML. + * + * @return string + */ + public function getTitle(): string + { + return $this->title; + } + + /** + * the URL of the site, when the channel is rendered, the image is a link to the site. + * + * @return string + */ + public function getLink(): string + { + return $this->link; + } + + /** + * Optional. The width of the image in pixels + * + * @return int|null + */ + public function getWidth(): ?int + { + return $this->width; + } + + /** + * Optional. The height of the image in pixels + * + * @return int|null + */ + public function getHeight(): ?int + { + return $this->height; + } + + /** + * Optional. Specifies the text in the HTML TITLE attribute of the link around the image + * + * @return string|null + */ + public function getDescription(): ?string + { + return $this->description; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'url' => $this->url, + 'title' => $this->title, + 'link' => $this->link, + 'width' => $this->width, + 'height' => $this->height, + 'description' => $this->description + ]; + } + + /** + * @inheritDoc + */ + public static function fromArray(array $array): Image + { + return new self($array); + } + } \ No newline at end of file diff --git a/src/RssLib/Objects/RssChannel/TextInput.php b/src/RssLib/Objects/RssChannel/TextInput.php new file mode 100644 index 0000000..5b8714e --- /dev/null +++ b/src/RssLib/Objects/RssChannel/TextInput.php @@ -0,0 +1,113 @@ +title = (string)$data['title']; + $this->description = (string)$data['description']; + $this->name = (string)$data['name']; + $this->link = (string)$data['link']; + } + + /** + * The label of the Submit button in the text input area. + * + * @return string + */ + public function getTitle(): string + { + return $this->title; + } + + /** + * Explains the text input area. + * + * @return string + */ + public function getDescription(): string + { + return $this->description; + } + + /** + * The name of the text object in the text input area. + * + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * The URL of the CGI script that processes text input requests. + * + * @return string + */ + public function getLink(): string + { + return $this->link; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'title' => $this->title, + 'description' => $this->description, + 'name' => $this->name, + 'link' => $this->link + ]; + } + + /** + * @inheritDoc + */ + public static function fromArray(array $array): TextInput + { + return new self($array); + } + } \ No newline at end of file diff --git a/src/RssLib/Objects/RssFeed/Enclosure.php b/src/RssLib/Objects/RssFeed/Enclosure.php new file mode 100644 index 0000000..96e31a1 --- /dev/null +++ b/src/RssLib/Objects/RssFeed/Enclosure.php @@ -0,0 +1,96 @@ +url = (string)$data['enclosure_url']; + $this->length = (int)$data['enclosure_length']; + $this->type = (string)$data['enclosure_type']; + } + + /** + * Required. Defines the URL to the media file + * + * @return string + */ + public function getUrl(): string + { + return $this->url; + } + + /** + * Required. Defines the length of the media file in bytes + * + * @return string + */ + public function getLength(): string + { + return $this->length; + } + + /** + * Required. Defines the MIME type of the media file + * + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'enclosure_url' => $this->url, + 'enclosure_length' => $this->length, + 'enclosure_type' => $this->type + ]; + } + + /** + * @inheritDoc + */ + public static function fromArray(array $array): Enclosure + { + return new self($array); + } + } \ No newline at end of file diff --git a/src/RssLib/Objects/RssFeed/Guid.php b/src/RssLib/Objects/RssFeed/Guid.php new file mode 100644 index 0000000..715a69d --- /dev/null +++ b/src/RssLib/Objects/RssFeed/Guid.php @@ -0,0 +1,84 @@ +guid = (string)$data['guid']; + + if(array_key_exists('guid_isPermalink', $data)) + { + $this->is_permalink = (bool)$data['guid_isPermalink']; + } + else + { + $this->is_permalink = false; + } + } + + /** + * Returns the guid + * + * @return string + */ + public function getGuid(): string + { + return $this->guid; + } + + /** + * Returns True if the guid is a permalink, False otherwise + * + * @return bool + */ + public function isPermalink(): bool + { + return $this->is_permalink; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'guid' => $this->guid, + 'guid_isPermalink' => $this->is_permalink + ]; + } + + /** + * @inheritDoc + */ + public static function fromArray(array $array): Guid + { + return new Guid($array); + } + } \ No newline at end of file diff --git a/src/RssLib/Objects/RssFeed/Source.php b/src/RssLib/Objects/RssFeed/Source.php new file mode 100644 index 0000000..73b4232 --- /dev/null +++ b/src/RssLib/Objects/RssFeed/Source.php @@ -0,0 +1,79 @@ +url = (string)$data['source_url']; + $this->source = (string)$data['source']; + } + + /** + * Returns the url + * + * @return string + */ + public function getUrl(): string + { + return $this->url; + } + + /** + * Returns the source + * + * @return string + */ + public function getSource(): string + { + return $this->source; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'source_url' => $this->url, + 'source' => $this->source + ]; + } + + /** + * @inheritDoc + */ + public static function fromArray(array $array): Source + { + return new static($array); + } + } \ No newline at end of file diff --git a/src/RssLib/Objects/RssItem.php b/src/RssLib/Objects/RssItem.php new file mode 100644 index 0000000..e117d84 --- /dev/null +++ b/src/RssLib/Objects/RssItem.php @@ -0,0 +1,253 @@ +title = (string)$data['title']; + $this->link = (string)$data['link']; + $this->description = (string)$data['description']; + + if(array_key_exists('author', $data)) + { + $this->author = (string)$data['author']; + } + + if(array_key_exists('categories', $data)) + { + if(is_string($data['categories'])) + { + $this->categories = [$data['categories']]; + } + else + { + $this->categories = (array)$data['categories']; + } + } + + if(array_key_exists('comments', $data)) + { + $this->comments = (string)$data['comments']; + } + + if(array_key_exists('enclosure', $data)) + { + $this->enclosure = new Enclosure($data['enclosure']); + } + + if(array_key_exists('guid', $data)) + { + $this->guid = new Guid($data['guid']); + } + + if(array_key_exists('pubDate', $data)) + { + $this->publish_date = Utilities::parseTimestamp($data['pubDate']); + } + + if(array_key_exists('source', $data)) + { + $this->source = new Source($data['source']); + } + } + + /** + * Returns the title of the item. + * + * @return string|null + */ + public function getTitle(): ?string + { + return $this->title; + } + + /** + * Returns the link of the item. + * + * @return string|null + */ + public function getLink(): ?string + { + return $this->link; + } + + /** + * Returns the description of the item. + * + * @return string|null + */ + public function getDescription(): ?string + { + return $this->description; + } + + /** + * Returns the author of the item. + * + * @return string|null + */ + public function getAuthor(): ?string + { + return $this->author; + } + + /** + * Returns the categories of the item. + * + * @return string[]|null + */ + public function getCategories(): array|null + { + return $this->categories; + } + + /** + * Returns the comments of the item. + * + * @return string|null + */ + public function getComments(): ?string + { + return $this->comments; + } + + /** + * Returns the enclosure of the item. + * + * @return Enclosure|null + */ + public function getEnclosure(): ?Enclosure + { + return $this->enclosure; + } + + /** + * Returns the GUID of the item. + * + * @return Guid|null + */ + public function getGuid(): ?Guid + { + return $this->guid; + } + + /** + * Returns the publication date of the item. + * + * @return int|null + */ + public function getPublishDate(): ?int + { + return $this->publish_date; + } + + /** + * Returns the source of the item. + * + * @return Source|null + */ + public function getSource(): ?Source + { + return $this->source; + } + + /** + * @inheritDoc + */ + public function toArray(): array + { + return [ + 'title' => $this->title, + 'link' => $this->link, + 'description' => $this->description, + 'author' => $this->author, + 'categories' => $this->categories, + 'comments' => $this->comments, + 'enclosure' => $this->enclosure?->toArray(), + 'guid' => $this->guid?->toArray(), + 'pubDate' => $this->publish_date, + 'source' => $this->source?->toArray(), + ]; + } + + /** + * @inheritDoc + */ + public static function fromArray(array $array): SerializableObjectInterface + { + return new self($array); + } + } \ No newline at end of file diff --git a/src/RssLib/RssLib.php b/src/RssLib/RssLib.php new file mode 100644 index 0000000..2dfbc16 --- /dev/null +++ b/src/RssLib/RssLib.php @@ -0,0 +1,70 @@ +