Completed
Push — master ( ff4556...f8a7b2 )
by Alex
07:23 queued 04:33
created

RssParser::parseCategories()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 9
Ratio 100 %

Code Coverage

Tests 4
CRAP Score 2.3149

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 9
loc 9
ccs 4
cts 7
cp 0.5714
rs 9.6667
cc 2
eloc 5
nc 2
nop 2
crap 2.3149
1
<?php
2
3
/**
4
 * Rss/Atom Bundle for Symfony 2.
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
            $media = $this->createMedia($element->enclosure);
140
            $item->addMedia($media);
141 1
        }
142
143 1
        return $this;
144
    }
145
146
    /**
147
     * According to RSS specs, either we can have a summary in description ;
148
     * full content in description ; or a summary in description AND full content in content:encoded
149
     *
150
     * @param SimpleXMLElement $xmlElement
151
     * @param ItemInInterface $item
152
     */
153 1
    protected function handleDescription(SimpleXMLElement $xmlElement, ItemInInterface $item)
154
    {
155 1
        $contentChild = $xmlElement->children('http://purl.org/rss/1.0/modules/content/');
156
157 1
        if (isset($contentChild->encoded)) {
158 1
            $item->setDescription($contentChild->encoded);
159
            $item->setSummary($xmlElement->description);
160
        } else {
161 1
            $item->setDescription($xmlElement->description);
162
        }
163 1
    }
164
165
    /**
166
     * Parse elements from Yahoo RSS Media extension
167
     *
168
     * @param SimpleXMLElement $xmlElement
169
     * @param ItemInInterface $item with Media added
170
     */
171 1
    protected function handleMediaExtension(SimpleXMLElement $xmlElement, ItemInInterface $item)
172
    {
173 1
        foreach ($xmlElement->children('http://search.yahoo.com/mrss/') as $xmlMedia) {
174 1
            $media = new Media();
175 1
            $media->setUrl($this->getAttributeValue($xmlMedia, 'url'))
176 1
                ->setType($this->searchAttributeValue($xmlMedia, array('type', 'medium')))
177 1
                ->setLength($this->getAttributeValue($xmlMedia, 'fileSize'))
178
            ;
179
180 1
            $item->addMedia($media);
181 1
        }
182 1
    }
183
184
    /**
185
     * Parse category elements.
186
     * We may have more than one.
187
     *
188
     * @param SimpleXMLElement $element
189
     * @param ItemInInterface $item
190
     */
191 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...
192
    {
193 1
        foreach ($element->category as $xmlCategory) {
194
            $category = new Category();
195
            $category->setName((string) $xmlCategory);
196
197
            $item->addCategory($category);
198 1
        }
199 1
    }
200
201
    /**
202
     * Parse author:
203
     * first we look at optional dc:creator, which is the author name
204
     * if no, we fallback to the RSS author element which is the author email
205
     *
206
     * @param SimpleXMLElement $element
207
     * @param ItemInInterface $item
208
     */
209 1
    protected function handleAuthor(SimpleXMLElement $element, ItemInInterface $item)
210
    {
211 1
        $dcChild = $element->children('http://purl.org/dc/elements/1.1/');
212
213 1
        if (isset($dcChild->creator)) {
214 1
            $item->setAuthor((string) $dcChild->creator);
215 1
        } else {
216
            $item->setAuthor((string) $element->author);
217
        }
218 1
    }
219
}
220