Completed
Push — develop ( d7c7d4...e90b1b )
by Baptiste
02:32
created

RSS::parse()   B

Complexity

Conditions 6
Paths 2

Size

Total Lines 86
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 66
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 86
ccs 66
cts 66
cp 1
rs 8.3234
c 0
b 0
f 0
cc 6
eloc 63
nc 2
nop 3
crap 6

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types = 1);
3
4
namespace PersonalGalaxy\RSS\Parser;
5
6
use PersonalGalaxy\RSS\Entity\{
7
    Article,
8
    Article\Author,
9
    Article\Description,
10
    Article\Title,
11
};
12
use Innmind\Url\Url;
13
use Innmind\Crawler\{
14
    Parser,
15
    HttpResource\Attribute\Attribute,
16
};
17
use Innmind\Http\Message\{
18
    Request,
19
    Response,
20
};
21
use Innmind\Xml\{
22
    ReaderInterface,
23
    NodeInterface,
24
    ElementInterface,
25
};
26
use Innmind\TimeContinuum\TimeContinuumInterface;
27
use Innmind\Immutable\{
28
    MapInterface,
29
    SetInterface,
30
    Set,
31
    StreamInterface,
32
    Stream,
33
};
34
35
final class RSS implements Parser
36
{
37
    private $reader;
38
    private $clock;
39
40 4
    public function __construct(
41
        ReaderInterface $reader,
42
        TimeContinuumInterface $clock
43
    ) {
44 4
        $this->reader = $reader;
45 4
        $this->clock = $clock;
46 4
    }
47
48 3
    public function parse(
49
        Request $request,
50
        Response $response,
51
        MapInterface $attributes
52
    ): MapInterface {
53
        if (
54 3
            !$response->headers()->has('content-type') ||
55 3
            (string) $response->headers()->get('content-type')->values()->current() !== 'application/rss'
56
        ) {
57 2
            return $attributes;
58
        }
59
60 1
        $xml = $this->reader->read($response->body());
61
        $articles = $xml
62 1
            ->children()
63 1
            ->values()
64 1
            ->first() // rss node
65 1
            ->children()
66 1
            ->values()
67 1
            ->filter(static function(NodeInterface $node): bool {
68 1
                return $node instanceof ElementInterface && $node->name() === 'channel';
69 1
            })
70 1
            ->reduce(
71 1
                Stream::of(NodeInterface::class),
72 1
                static function(StreamInterface $channels, ElementInterface $channel): StreamInterface {
73 1
                    return $channels->append($channel->children()->values());
74 1
                }
75
            )
76 1
            ->filter(static function(NodeInterface $node): bool {
77 1
                return $node instanceof ElementInterface && $node->name() === 'item';
78 1
            })
79 1
            ->reduce(
80 1
                Set::of(Article::class),
81 1
                function(SetInterface $articles, ElementInterface $item): SetInterface {
82
                    $elements = $item
83 1
                        ->children()
84 1
                        ->values()
85 1
                        ->filter(static function(NodeInterface $node): bool {
86 1
                            return $node instanceof ElementInterface;
87 1
                        });
88
                    $link = $elements
89 1
                        ->filter(static function(ElementInterface $element): bool {
90 1
                            return $element->name() === 'link';
91 1
                        })
92 1
                        ->first()
93 1
                        ->content();
94
                    $author = $elements
95 1
                        ->filter(static function(ElementInterface $element): bool {
96 1
                            return $element->name() === 'author' || $element->name() === 'dc:creator';
97 1
                        })
98 1
                        ->first()
99 1
                        ->content();
100
                    $description = $elements
101 1
                        ->filter(static function(ElementInterface $element): bool {
102 1
                            return $element->name() === 'description';
103 1
                        })
104 1
                        ->first()
105 1
                        ->content();
106
                    $title = $elements
107 1
                        ->filter(static function(ElementInterface $element): bool {
108 1
                            return $element->name() === 'title';
109 1
                        })
110 1
                        ->first()
111 1
                        ->content();
112
                    $publicationDate = $elements
113 1
                        ->filter(static function(ElementInterface $element): bool {
114 1
                            return $element->name() === 'pubDate';
115 1
                        })
116 1
                        ->first()
117 1
                        ->content();
118
119 1
                    return $articles->add(Article::fetch(
120 1
                        Url::fromString(trim($link)),
121 1
                        new Author(trim($author)),
122 1
                        new Description(trim($description)),
123 1
                        new Title(trim($title)),
124 1
                        $this->clock->at(trim($publicationDate))
125
                    ));
126 1
                }
127
            );
128
129 1
        return $attributes->put(
130 1
            self::key(),
1 ignored issue
show
Bug introduced by
self::key() of type string is incompatible with the type Innmind\Immutable\T expected by parameter $key of Innmind\Immutable\MapInterface::put(). ( Ignorable by Annotation )

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

130
            /** @scrutinizer ignore-type */ self::key(),
Loading history...
131 1
            new Attribute(
132 1
                self::key(),
133 1
                $articles
134
            )
135
        );
136
    }
137
138 2
    public static function key(): string
139
    {
140 2
        return 'articles';
141
    }
142
}
143