Completed
Push — master ( bd5947...6becd7 )
by Alex
12s
created

RssParser::detectAndSetLastModified()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.4746

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 5
cts 8
cp 0.625
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 3
crap 3.4746
1
<?php
2
3
/**
4
 * Rss/Atom Bundle for Symfony.
5
 *
6
 *
7
 * @license http://opensource.org/licenses/lgpl-3.0.html LGPL
8
 * @copyright (c) 2013, Alexandre Debril
9
 */
10
namespace Debril\RssAtomBundle\Protocol\Parser;
11
12
use Debril\RssAtomBundle\Protocol\FeedInterface;
13
use Debril\RssAtomBundle\Protocol\ItemInInterface;
14
use Debril\RssAtomBundle\Protocol\Parser;
15
use SimpleXMLElement;
16
17
/**
18
 * Class RssParser.
19
 */
20
class RssParser extends Parser
21
{
22
    protected $mandatoryFields = array(
23
        'channel',
24
    );
25
26
    /**
27
     *
28
     */
29 3
    public function __construct()
30
    {
31 3
        $this->setdateFormats(array(\DateTime::RSS));
32 3
    }
33
34
    /**
35
     * @param SimpleXMLElement $xmlBody
36
     *
37
     * @return bool
38
     */
39 3
    public function canHandle(SimpleXMLElement $xmlBody)
40
    {
41 3
        return 'rss' === strtolower($xmlBody->getName());
42
    }
43
44
    /**
45
     * @param SimpleXMLElement $xmlBody
46
     * @param FeedInterface    $feed
47
     * @param array            $filters
48
     *
49
     * @return FeedInterface
50
     */
51 6
    protected function parseBody(SimpleXMLElement $xmlBody, FeedInterface $feed, array $filters)
52
    {
53 6
        $namespaces = $xmlBody->getNamespaces(true);
54
55 6
        $feed->setPublicId($xmlBody->channel->link);
56 6
        $feed->setLink($xmlBody->channel->link);
57 6
        $feed->setTitle($xmlBody->channel->title);
58 6
        $feed->setDescription($xmlBody->channel->description);
59
60 6
        $latest = new \DateTime('@0');
61 6
        $date = new \DateTime('now');
62 6
        foreach ($xmlBody->channel->item as $xmlElement) {
63 6
            $item = $this->newItem();
64
65 6
            if (isset($xmlElement->pubDate)) {
66 6
                $readDate = trim($xmlElement->pubDate);
67
68 6
                $format = isset($format) ? $format : $this->guessDateFormat($readDate);
69 6
                $date = static::convertToDateTime($readDate, $format);
70 6
            }
71
72 6
            $item->setTitle($xmlElement->title)
73 6
                 ->setDescription($xmlElement->description)
74 6
                 ->setPublicId($xmlElement->guid)
75 6
                 ->setUpdated($date)
76 6
                 ->setLink($xmlElement->link)
77 6
                 ->setComment($xmlElement->comments);
78
79 6
            if ($date > $latest) {
80 6
                $latest = $date;
81 6
            }
82
83 6
            $this->parseCategories($xmlElement, $item);
84
85 6
            $this->handleAuthor($xmlElement, $item);
86 6
            $this->handleDescription($xmlElement, $item);
87
88 6
            $item->setAdditional($this->getAdditionalNamespacesElements($xmlElement, $namespaces));
89
90 6
            $this->handleEnclosure($xmlElement, $item);
91 6
            $this->handleMediaExtension($xmlElement, $item);
92
93 6
            $this->addValidItem($feed, $item, $filters);
94 6
        }
95
96 6
        $this->detectAndSetLastModified($xmlBody, $feed, $latest);
97
98 6
        return $feed;
99
    }
100
101
    /**
102
     * @param SimpleXMLElement $xmlBody
103
     * @param FeedInterface    $feed
104
     * @param $latestItemDate
105
     */
106 1
    protected function detectAndSetLastModified(SimpleXMLElement $xmlBody, FeedInterface $feed, $latestItemDate)
107
    {
108 1
        if (isset($xmlBody->channel->lastBuildDate)) {
109 1
            $this->setLastModified($feed, $xmlBody->channel->lastBuildDate);
110 1
        } elseif (isset($xmlBody->channel->pubDate)) {
111
            $this->setLastModified($feed, $xmlBody->channel->pubDate);
112
        } else {
113
            $feed->setLastModified($latestItemDate);
114
        }
115 1
    }
116
117
    /**
118
     * @param FeedInterface $feed
119
     * @param string        $rssDate
120
     */
121 2
    protected function setLastModified(FeedInterface $feed, $rssDate)
122
    {
123 2
        $format = $this->guessDateFormat($rssDate);
124 2
        $updated = static::convertToDateTime($rssDate, $format);
125 2
        $feed->setLastModified($updated);
126 2
    }
127
128
    /**
129
     * Handles enclosures if any.
130
     *
131
     * @param SimpleXMLElement $element
132
     * @param ItemInInterface  $item
133
     *
134
     * @return $this
135
     */
136 1
    protected function handleEnclosure(SimpleXMLElement $element, ItemInInterface $item)
137
    {
138 1
        if (isset($element->enclosure)) {
139
            foreach ($element->enclosure as $enclosure) {
140
                $media = $this->createMedia($enclosure);
141 1
                $item->addMedia($media);
142
            }
143
        }
144
145 1
        return $this;
146
    }
147
148
    /**
149
     * According to RSS specs, either we can have a summary in description ;
150
     * full content in description ; or a summary in description AND full content in content:encoded
151
     *
152
     * @param SimpleXMLElement $xmlElement
153
     * @param ItemInInterface $item
154
     */
155 1
    protected function handleDescription(SimpleXMLElement $xmlElement, ItemInInterface $item)
156
    {
157 1
        $contentChild = $xmlElement->children('http://purl.org/rss/1.0/modules/content/');
158
159 1
        if (isset($contentChild->encoded)) {
160
            $item->setDescription($contentChild->encoded);
161
            $item->setSummary($xmlElement->description);
162
        } else {
163 1
            $item->setDescription($xmlElement->description);
164
        }
165 1
    }
166
167
    /**
168
     * Parse elements from Yahoo RSS Media extension
169
     *
170
     * @param SimpleXMLElement $xmlElement
171
     * @param ItemInInterface $item with Media added
172
     */
173 1
    protected function handleMediaExtension(SimpleXMLElement $xmlElement, ItemInInterface $item)
174
    {
175 1
        foreach ($xmlElement->children('http://search.yahoo.com/mrss/') as $xmlMedia) {
176 1
            $media = new Media();
177 1
            $media->setUrl($this->getAttributeValue($xmlMedia, 'url'))
178 1
                ->setType($this->searchAttributeValue($xmlMedia, array('type', 'medium')))
179 1
                ->setLength($this->getAttributeValue($xmlMedia, 'fileSize'))
180
            ;
181
182 1
            $item->addMedia($media);
183 1
        }
184 1
    }
185
186
    /**
187
     * Parse category elements.
188
     * We may have more than one.
189
     *
190
     * @param SimpleXMLElement $element
191
     * @param ItemInInterface $item
192
     */
193 1 View Code Duplication
    protected function parseCategories(SimpleXMLElement $element, ItemInInterface $item)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
    {
195 1
        foreach ($element->category as $xmlCategory) {
196
            $category = new Category();
197
            $category->setName((string) $xmlCategory);
198
199
            $item->addCategory($category);
200 1
        }
201 1
    }
202
203
    /**
204
     * Parse author:
205
     * first we look at optional dc:creator, which is the author name
206
     * if no, we fallback to the RSS author element which is the author email
207
     *
208
     * @param SimpleXMLElement $element
209
     * @param ItemInInterface $item
210
     */
211 1
    protected function handleAuthor(SimpleXMLElement $element, ItemInInterface $item)
212
    {
213 1
        $dcChild = $element->children('http://purl.org/dc/elements/1.1/');
214
215 1
        if (isset($dcChild->creator)) {
216 1
            $item->setAuthor((string) $dcChild->creator);
217 1
        } else {
218
            $item->setAuthor((string) $element->author);
219 1
        }
220 1
    }
221
}
222