Passed
Push — master ( b6a4c4...137285 )
by Caen
03:01 queued 13s
created

RssFeedGenerator   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Importance

Changes 8
Bugs 0 Features 0
Metric Value
wmc 16
eloc 40
c 8
b 0
f 0
dl 0
loc 96
rs 10

10 Methods

Rating   Name   Duplication   Size   Complexity  
A addItem() 0 7 1
A generate() 0 6 1
A getDescription() 0 3 1
A getImageType() 0 4 2
A getImageLength() 0 4 1
A addBaseChannelItems() 0 10 1
A constructBaseElement() 0 8 1
A addDynamicItemData() 0 24 6
A addAtomLinkItem() 0 6 1
A getFilename() 0 3 1
1
<?php
2
3
/** @noinspection PhpComposerExtensionStubsInspection */
4
/** @noinspection XmlUnusedNamespaceDeclaration */
5
6
declare(strict_types=1);
7
8
namespace Hyde\Framework\Features\XmlGenerators;
9
10
use function config;
11
use function date;
12
use Hyde\Facades\Site;
13
use Hyde\Hyde;
14
use Hyde\Pages\MarkdownPost;
15
use SimpleXMLElement;
16
use function str_ends_with;
17
18
/**
19
 * @see \Hyde\Framework\Testing\Feature\Services\RssFeedServiceTest
20
 * @see https://validator.w3.org/feed/docs/rss2.html
21
 */
22
class RssFeedGenerator extends BaseXmlGenerator
23
{
24
    public function generate(): static
25
    {
26
        MarkdownPost::getLatestPosts()
27
            ->each(fn (MarkdownPost $post) => $this->addItem($post));
28
29
        return $this;
30
    }
31
32
    protected function constructBaseElement(): void
33
    {
34
        $this->xmlElement = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>
35
            <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" />');
36
        $this->xmlElement->addChild('channel');
37
38
        $this->addBaseChannelItems();
39
        $this->addAtomLinkItem();
40
    }
41
42
    protected function addItem(MarkdownPost $post): void
43
    {
44
        $item = $this->xmlElement->channel->addChild('item');
45
        $item->addChild('title', $post->title);
46
        $item->addChild('description', $post->description);
47
48
        $this->addDynamicItemData($item, $post);
49
    }
50
51
    protected function addDynamicItemData(SimpleXMLElement $item, MarkdownPost $post): void
52
    {
53
        if (isset($post->canonicalUrl)) {
54
            $item->addChild('link', $post->canonicalUrl);
55
            $item->addChild('guid', $post->canonicalUrl);
56
        }
57
58
        if (isset($post->date)) {
59
            $item->addChild('pubDate', $post->date->dateTimeObject->format(DATE_RSS));
60
        }
61
62
        if (isset($post->author)) {
63
            $item->addChild('dc:creator', $post->author->getName(), 'http://purl.org/dc/elements/1.1/');
0 ignored issues
show
Bug introduced by
The method getName() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

63
            $item->addChild('dc:creator', $post->author->/** @scrutinizer ignore-call */ getName(), 'http://purl.org/dc/elements/1.1/');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
64
        }
65
66
        if (isset($post->category)) {
67
            $item->addChild('category', $post->category);
68
        }
69
70
        if (isset($post->image)) {
71
            $image = $item->addChild('enclosure');
72
            $image->addAttribute('url', Hyde::image($post->image->getSource(), true));
0 ignored issues
show
Bug introduced by
The method getSource() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

72
            $image->addAttribute('url', Hyde::image($post->image->/** @scrutinizer ignore-call */ getSource(), true));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
73
            $image->addAttribute('type', $this->getImageType($post));
74
            $image->addAttribute('length', $this->getImageLength($post));
75
        }
76
    }
77
78
    protected function addBaseChannelItems(): void
79
    {
80
        $channel = $this->xmlElement->channel;
81
82
        $channel->addChild('title', $this->escape(Site::name()));
0 ignored issues
show
Bug introduced by
It seems like Hyde\Facades\Site::name() can also be of type null; however, parameter $string of Hyde\Framework\Features\...eXmlGenerator::escape() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

82
        $channel->addChild('title', $this->escape(/** @scrutinizer ignore-type */ Site::name()));
Loading history...
83
        $channel->addChild('link', $this->escape(Site::url()));
84
        $channel->addChild('description', $this->escape($this->getDescription()));
85
        $channel->addChild('language', config('site.language', 'en'));
86
        $channel->addChild('generator', 'HydePHP '.Hyde::version());
87
        $channel->addChild('lastBuildDate', date(DATE_RSS));
88
    }
89
90
    protected function addAtomLinkItem(): void
91
    {
92
        $atomLink = $this->xmlElement->channel->addChild('atom:link', namespace: 'http://www.w3.org/2005/Atom');
93
        $atomLink->addAttribute('href', $this->escape(Hyde::url($this->getFilename())));
94
        $atomLink->addAttribute('rel', 'self');
95
        $atomLink->addAttribute('type', 'application/rss+xml');
96
    }
97
98
    protected function getImageType(MarkdownPost $post): string
99
    {
100
        /** @todo Add support for more types */
101
        return str_ends_with($post->image->getSource(), '.png') ? 'image/png' : 'image/jpeg';
102
    }
103
104
    protected function getImageLength(MarkdownPost $post): string
105
    {
106
        /** @todo We might want to add a build warning if the length is zero */
107
        return (string) $post->image->getContentLength();
108
    }
109
110
    public static function getFilename(): string
111
    {
112
        return config('hyde.rss_filename', 'feed.xml');
113
    }
114
115
    public static function getDescription(): string
116
    {
117
        return config('hyde.rss_description', Site::name().' RSS Feed');
118
    }
119
}
120