From 317d9e37e86c0f4e70a30fef2235fb3f042432b9 Mon Sep 17 00:00:00 2001 From: Clement Desmidt Date: Thu, 13 Apr 2023 11:24:43 +0200 Subject: [PATCH] :sparkles: Finishes Builders --- src/Builder/ChannelBuilder.php | 98 ++++++++++++++++++++++++++++++ src/Builder/ItemBuilder.php | 105 +++++++++++++++++++++++++++++++++ src/Builder/SRSSBuilder.php | 37 ++---------- src/SRSS.php | 6 +- src/SRSSTools.php | 6 ++ src/Validator/Validator.php | 5 ++ tests/CompleteBuilderTest.php | 101 +++++++++++++++++++++++++++++++ 7 files changed, 326 insertions(+), 32 deletions(-) create mode 100644 src/Builder/ChannelBuilder.php create mode 100644 src/Builder/ItemBuilder.php create mode 100644 tests/CompleteBuilderTest.php diff --git a/src/Builder/ChannelBuilder.php b/src/Builder/ChannelBuilder.php new file mode 100644 index 0000000..2f57ea1 --- /dev/null +++ b/src/Builder/ChannelBuilder.php @@ -0,0 +1,98 @@ +document = $document; + } + + /** + * @param \Shikiryu\SRSS\Entity\Channel $channel + * + * @return \DOMElement|false + * @throws \DOMException + */ + public function build(Channel $channel) + { + $node = $this->document->createElement('channel'); + foreach (array_filter($channel->toArray(), static fn($el) => !empty($el)) as $name => $value) { + if ($name === 'category') { + /** @var \Shikiryu\SRSS\Entity\Channel\Category $category */ + foreach ($value as $category) { + $node->appendChild($this->buildCategory($category)); + } + } elseif ($name === 'cloud') { + $node->appendChild($this->buildCloud($value)); + } elseif ($name === 'image') { + $node->appendChild($this->buildImage($value)); + } else { + $new_node = $this->document->createElement($name, $value); + $node->appendChild($new_node); + } + } + + return $node; + } + + /** + * @param \Shikiryu\SRSS\Entity\Channel\Category $category + * + * @return bool|\DOMElement + * @throws \DOMException + */ + private function buildCategory(Channel\Category $category): bool|DOMElement + { + $node = $this->document->createElement('category', $category->value); + $node->setAttribute('domain', $category->domain); + + return $node; + } + + /** + * @param \Shikiryu\SRSS\Entity\Channel\Cloud $cloud + * + * @return \DOMElement|false + * @throws \DOMException + */ + private function buildCloud(Channel\Cloud $cloud) + { + $node = $this->document->createElement('cloud'); + foreach (get_object_vars($cloud) as $name => $value) { + if (!is_array($value)) { + $node->setAttribute($name, $value); + } + } + + return $node; + } + + /** + * @param \Shikiryu\SRSS\Entity\Channel\Image $image + * + * @return \DOMElement|false + * @throws \DOMException + */ + private function buildImage(Channel\Image $image) + { + $node = $this->document->createElement('image'); + foreach (get_object_vars($image) as $name => $value) { + if (!is_array($value)) { + $node->appendChild($this->document->createElement($name, $value)); + } + } + + return $node; + } +} \ No newline at end of file diff --git a/src/Builder/ItemBuilder.php b/src/Builder/ItemBuilder.php new file mode 100644 index 0000000..b65de13 --- /dev/null +++ b/src/Builder/ItemBuilder.php @@ -0,0 +1,105 @@ +document = $document; + } + + /** + * @param \Shikiryu\SRSS\Entity\Item $item + * + * @return \DOMElement|false + * @throws \DOMException + */ + public function build(Item $item): bool|\DOMElement + { + $node = $this->document->createElement('item'); + + foreach (array_filter($item->toArray()) as $name => $value) { + if ($name === 'category') { + /** @var \Shikiryu\SRSS\Entity\Item\Category $category */ + foreach ($value as $category) { + $node->appendChild($this->buildCategory($category)); + } + } elseif ($name === 'medias') { + $group = null; + if (count($value) > 1) { + $group = $node->appendChild($this->document->createElement('media:group')); + } + foreach ($value as $media) { + if (null === $group) { + $node->appendChild($this->buildMedia($media)); + } else { + $group->appendChild($this->buildMedia($media)); + } + } + if ($group !== null) { + $node->appendChild($group); + } + } elseif ($name === 'enclosure') { + $node->appendChild($this->buildEnclosure($value)); + } elseif ($name === 'source') { + $node->appendChild($this->buildSource($value)); + } else { + $new_node = $this->document->createElement($name, $value); + $node->appendChild($new_node); + } + } + + return $node; + } + + private function buildCategory(Item\Category $category) + { + $node = $this->document->createElement('category', $category->value); + $node->setAttribute('domain', $category->domain); + + return $node; + } + + private function buildEnclosure(Item\Enclosure $enclosure) + { + $node = $this->document->createElement('enclosure'); + foreach (get_object_vars($enclosure) as $name => $value) { + if (!is_array($value)) { + $node->setAttribute($name, $value); + } + } + + return $node; + } + + private function buildSource(Item\Source $source) + { + $node = $this->document->createElement('source', $source->value); + $node->setAttribute('url', $source->url); + + return $node; + } + + private function buildMedia(Content $media) + { + $node = $this->document->createElement('media:content'); + foreach (get_object_vars($media) as $name => $value) { + if (!is_array($value)) { + $node->setAttribute($name, $value); + } + } + + return $node; + } + + +} \ No newline at end of file diff --git a/src/Builder/SRSSBuilder.php b/src/Builder/SRSSBuilder.php index 11f1fd3..c62ddc4 100644 --- a/src/Builder/SRSSBuilder.php +++ b/src/Builder/SRSSBuilder.php @@ -3,9 +3,6 @@ namespace Shikiryu\SRSS\Builder; use DOMDocument; -use DOMElement; -use Shikiryu\SRSS\Entity\Channel; -use Shikiryu\SRSS\Entity\Item; use Shikiryu\SRSS\Exception\DOMBuilderException; use Shikiryu\SRSS\SRSS; @@ -20,13 +17,16 @@ class SRSSBuilder extends DomDocument $root = $this->createElement('rss'); $root->setAttribute('version', '2.0'); - $channel = $this->createElement('channel'); $srss->channel->generator = 'Shikiryu RSS'; - $this->appendChannelToDom($srss->channel, $channel); + $channel_builder = new ChannelBuilder($this); + $channel = $channel_builder->build($srss->channel); - $this->appendItemsToDom($srss->items, $channel); + $item_builder = new ItemBuilder($this); + foreach ($srss->items as $item) { + $channel->appendChild($item_builder->build($item)); + } $root->appendChild($channel); $this->appendChild($root); @@ -62,29 +62,4 @@ class SRSSBuilder extends DomDocument ->buildRSS($srss) ->saveXml(); } - - private function appendChannelToDom(Channel $channel, DOMElement $node): void - { - foreach (array_filter($channel->toArray(), static fn($el) => !empty($el)) as $name => $value) { - $new_node = $this->createElement($name, $value); - $node->appendChild($new_node); - } - } - - private function appendItemsToDom(array $items, DOMElement $channel): void - { - foreach ($items as $item) { - $this->appendItemToDom($item, $channel); - } - } - - private function appendItemToDom(Item $item, DOMElement $channel): void - { - $itemNode = $this->createElement('item'); - foreach (array_filter($item->toArray()) as $name => $value) { - $new_node = $this->createElement($name, $value); - $itemNode->appendChild($new_node); - } - $channel->appendChild($itemNode); - } } \ No newline at end of file diff --git a/src/SRSS.php b/src/SRSS.php index 37d6213..082fc54 100644 --- a/src/SRSS.php +++ b/src/SRSS.php @@ -126,7 +126,11 @@ class SRSS implements Iterator throw new PropertyNotFoundException(Channel::class, $name); } if ((new Validator())->isValidValueForObjectProperty($this->channel, $name, $val)) { - $this->channel->{$name} = $val; + if (SRSSTools::getPropertyType(Channel::class, $name) === 'array') { + $this->channel->{$name}[] = $val; + } else { + $this->channel->{$name} = $val; + } } } diff --git a/src/SRSSTools.php b/src/SRSSTools.php index 2f038c3..5ab55f1 100644 --- a/src/SRSSTools.php +++ b/src/SRSSTools.php @@ -4,9 +4,15 @@ namespace Shikiryu\SRSS; use DateTime; use DateTimeInterface; +use ReflectionProperty; class SRSSTools { + public static function getPropertyType($object, $property): ?string + { + $rp = new ReflectionProperty($object, $property); + return $rp->getType()?->getName(); + } public static function check($check, $flag) { return match ($flag) { diff --git a/src/Validator/Validator.php b/src/Validator/Validator.php index da63052..dc981f1 100644 --- a/src/Validator/Validator.php +++ b/src/Validator/Validator.php @@ -272,4 +272,9 @@ class Validator { return in_array($value, ['sample', 'full', 'nonstop']); } + + private function _validateEmail($value): bool + { + return filter_var($value, FILTER_VALIDATE_EMAIL); + } } \ No newline at end of file diff --git a/tests/CompleteBuilderTest.php b/tests/CompleteBuilderTest.php new file mode 100644 index 0000000..06c6b17 --- /dev/null +++ b/tests/CompleteBuilderTest.php @@ -0,0 +1,101 @@ +better'; + $language = 'en-us'; + $copyright = 'Shikiryu'; + $managingEditor = 'editor'; + $webMaster = 'Shikiryu'; + $pubDate = (new DateTime())->format(DATE_RSS); + $lastBuildDate = $pubDate; + $category = new Category(); + $category->domain = $link; + $category->value = 'Test Category'; + $generator = 'SRSS'; + $docs = $link; + $cloud = new Cloud(); + $cloud->domain = $link; + $cloud->port = 80; + $cloud->path = '/test'; + $ttl = 3660; + $image = new Image(); + $image->link = $link; + $image->title = 'title of image'; + $rating = 'yes'; + $textInput = 'ignore'; + $skipDays = 'monday'; + $skipHours = '8'; + + $srss = SRSS::create(); + $srss->title = $title; + $srss->link = $link; + $srss->description = $description; + $srss->language = $language; + $srss->copyright = $copyright; + $srss->managingEditor = $managingEditor; + $srss->webMaster = $webMaster; + $srss->pubDate = $pubDate; + $srss->lastBuildDate = $lastBuildDate; + $srss->category = $category; + $srss->generator = $generator; + $srss->docs = $docs; + $srss->cloud = $cloud; + $srss->ttl = $ttl; + $srss->image = $image; + $srss->rating = $rating; + $srss->textInput = $textInput; + $srss->skipDays = $skipDays; + $srss->skipHours = $skipHours; + + $item_title = 'item title'; + $item_link = 'https://example.com'; + $item_description = 'item description'; + $item_author = 'shikiryu@shikiryu.com'; + $item_category = new \Shikiryu\SRSS\Entity\Item\Category(); + $item_category->domain = 'https://shikiryu.com'; + $item_category->value = 'category shikiryu'; + $item_comments = $link.'/comments'; + $item_enclosure = new Enclosure(); + $item_enclosure->url = $item_link; + $item_enclosure->length = 5023; + $item_enclosure->type = 'audio/mp3'; + $item_guid = '123456'; + $item_pubdate = $pubDate; + $item_source = new Source(); + $item_source->url = $item_link; + $item_source->value = 'source'; + $item_media = new Shikiryu\SRSS\Entity\Media\Content(); + $item_media->url = $item_link; + $item_media->type = 'image/jpg'; + $item = new Shikiryu\SRSS\Entity\Item(); + $item->title = $item_title; + $item->link = $item_link; + $item->description = $item_description; + $item->author = $item_author; + $item->category[] = $item_category; + $item->comments = $item_comments; + $item->enclosure = $item_enclosure; + $item->guid = $item_guid; + $item->pubDate = $item_pubdate; + $item->source = $item_source; + $item->medias[] = $item_media; + + $srss->addItem($item); + + self::assertTrue($srss->isValid(), var_export($srss->channel->validated + array_map(static fn ($item) => $item->validated, $srss->items), true)); + } +} \ No newline at end of file