1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Feed
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * RSS Feed Parser class.
14 *
15 * @link http://cyber.law.harvard.edu/rss/rss.html
16 * @since 12.3
17 */
18 class JFeedParserRss extends JFeedParser
19 {
20 /**
21 * @var string The feed element name for the entry elements.
22 * @since 12.3
23 */
24 protected $entryElementName = 'item';
25
26 /**
27 * @var string The feed format version.
28 * @since 12.3
29 */
30 protected $version;
31
32 /**
33 * Method to handle the `<category>` element for the feed.
34 *
35 * @param JFeed $feed The JFeed object being built from the parsed feed.
36 * @param SimpleXMLElement $el The current XML element object to handle.
37 *
38 * @return void
39 *
40 * @since 12.3
41 */
42 protected function handleCategory(JFeed $feed, SimpleXMLElement $el)
43 {
44 // Get the data from the element.
45 $domain = (string) $el['domain'];
46 $category = (string) $el;
47
48 $feed->addCategory($category, $domain);
49 }
50
51 /**
52 * Method to handle the `<cloud>` element for the feed.
53 *
54 * @param JFeed $feed The JFeed object being built from the parsed feed.
55 * @param SimpleXMLElement $el The current XML element object to handle.
56 *
57 * @return void
58 *
59 * @since 12.3
60 */
61 protected function handleCloud(JFeed $feed, SimpleXMLElement $el)
62 {
63 $cloud = new stdClass;
64 $cloud->domain = (string) $el['domain'];
65 $cloud->port = (string) $el['port'];
66 $cloud->path = (string) $el['path'];
67 $cloud->protocol = (string) $el['protocol'];
68 $cloud->registerProcedure = (string) $el['registerProcedure'];
69
70 $feed->cloud = $cloud;
71 }
72
73 /**
74 * Method to handle the `<copyright>` element for the feed.
75 *
76 * @param JFeed $feed The JFeed object being built from the parsed feed.
77 * @param SimpleXMLElement $el The current XML element object to handle.
78 *
79 * @return void
80 *
81 * @since 12.3
82 */
83 protected function handleCopyright(JFeed $feed, SimpleXMLElement $el)
84 {
85 $feed->copyright = (string) $el;
86 }
87
88 /**
89 * Method to handle the `<description>` element for the feed.
90 *
91 * @param JFeed $feed The JFeed object being built from the parsed feed.
92 * @param SimpleXMLElement $el The current XML element object to handle.
93 *
94 * @return void
95 *
96 * @since 12.3
97 */
98 protected function handleDescription(JFeed $feed, SimpleXMLElement $el)
99 {
100 $feed->description = (string) $el;
101 }
102
103 /**
104 * Method to handle the `<generator>` element for the feed.
105 *
106 * @param JFeed $feed The JFeed object being built from the parsed feed.
107 * @param SimpleXMLElement $el The current XML element object to handle.
108 *
109 * @return void
110 *
111 * @since 12.3
112 */
113 protected function handleGenerator(JFeed $feed, SimpleXMLElement $el)
114 {
115 $feed->generator = (string) $el;
116 }
117
118 /**
119 * Method to handle the `<image>` element for the feed.
120 *
121 * @param JFeed $feed The JFeed object being built from the parsed feed.
122 * @param SimpleXMLElement $el The current XML element object to handle.
123 *
124 * @return void
125 *
126 * @since 12.3
127 */
128 protected function handleImage(JFeed $feed, SimpleXMLElement $el)
129 {
130 // Create a feed link object for the image.
131 $image = new JFeedLink(
132 (string) $el->url,
133 null,
134 'logo',
135 null,
136 (string) $el->title
137 );
138
139 // Populate extra fields if they exist.
140 $image->link = (string) $el->link;
141 $image->description = (string) $el->description;
142 $image->height = (string) $el->height;
143 $image->width = (string) $el->width;
144
145 $feed->image = $image;
146 }
147
148 /**
149 * Method to handle the `<language>` element for the feed.
150 *
151 * @param JFeed $feed The JFeed object being built from the parsed feed.
152 * @param SimpleXMLElement $el The current XML element object to handle.
153 *
154 * @return void
155 *
156 * @since 12.3
157 */
158 protected function handleLanguage(JFeed $feed, SimpleXMLElement $el)
159 {
160 $feed->language = (string) $el;
161 }
162
163 /**
164 * Method to handle the `<lastBuildDate>` element for the feed.
165 *
166 * @param JFeed $feed The JFeed object being built from the parsed feed.
167 * @param SimpleXMLElement $el The current XML element object to handle.
168 *
169 * @return void
170 *
171 * @since 12.3
172 */
173 protected function handleLastBuildDate(JFeed $feed, SimpleXMLElement $el)
174 {
175 $feed->updatedDate = (string) $el;
176 }
177
178 /**
179 * Method to handle the `<link>` element for the feed.
180 *
181 * @param JFeed $feed The JFeed object being built from the parsed feed.
182 * @param SimpleXMLElement $el The current XML element object to handle.
183 *
184 * @return void
185 *
186 * @since 12.3
187 */
188 protected function handleLink(JFeed $feed, SimpleXMLElement $el)
189 {
190 $link = new JFeedLink;
191 $link->uri = (string) $el['href'];
192 $feed->link = $link;
193 }
194
195 /**
196 * Method to handle the `<managingEditor>` element for the feed.
197 *
198 * @param JFeed $feed The JFeed object being built from the parsed feed.
199 * @param SimpleXMLElement $el The current XML element object to handle.
200 *
201 * @return void
202 *
203 * @since 12.3
204 */
205 protected function handleManagingEditor(JFeed $feed, SimpleXMLElement $el)
206 {
207 $feed->author = $this->processPerson((string) $el);
208 }
209
210 /**
211 * Method to handle the `<skipDays>` element for the feed.
212 *
213 * @param JFeed $feed The JFeed object being built from the parsed feed.
214 * @param SimpleXMLElement $el The current XML element object to handle.
215 *
216 * @return void
217 *
218 * @since 12.3
219 */
220 protected function handleSkipDays(JFeed $feed, SimpleXMLElement $el)
221 {
222 // Initialise the array.
223 $days = array();
224
225 // Add all of the day values from the feed to the array.
226 foreach ($el->day as $day)
227 {
228 $days[] = (string) $day;
229 }
230
231 $feed->skipDays = $days;
232 }
233
234 /**
235 * Method to handle the `<skipHours>` element for the feed.
236 *
237 * @param JFeed $feed The JFeed object being built from the parsed feed.
238 * @param SimpleXMLElement $el The current XML element object to handle.
239 *
240 * @return void
241 *
242 * @since 12.3
243 */
244 protected function handleSkipHours(JFeed $feed, SimpleXMLElement $el)
245 {
246 // Initialise the array.
247 $hours = array();
248
249 // Add all of the day values from the feed to the array.
250 foreach ($el->hour as $hour)
251 {
252 $hours[] = (int) $hour;
253 }
254
255 $feed->skipHours = $hours;
256 }
257
258 /**
259 * Method to handle the `<pubDate>` element for the feed.
260 *
261 * @param JFeed $feed The JFeed object being built from the parsed feed.
262 * @param SimpleXMLElement $el The current XML element object to handle.
263 *
264 * @return void
265 *
266 * @since 12.3
267 */
268 protected function handlePubDate(JFeed $feed, SimpleXMLElement $el)
269 {
270 $feed->publishedDate = (string) $el;
271 }
272
273 /**
274 * Method to handle the `<title>` element for the feed.
275 *
276 * @param JFeed $feed The JFeed object being built from the parsed feed.
277 * @param SimpleXMLElement $el The current XML element object to handle.
278 *
279 * @return void
280 *
281 * @since 12.3
282 */
283 protected function handleTitle(JFeed $feed, SimpleXMLElement $el)
284 {
285 $feed->title = (string) $el;
286 }
287
288 /**
289 * Method to handle the `<ttl>` element for the feed.
290 *
291 * @param JFeed $feed The JFeed object being built from the parsed feed.
292 * @param SimpleXMLElement $el The current XML element object to handle.
293 *
294 * @return void
295 *
296 * @since 12.3
297 */
298 protected function handleTtl(JFeed $feed, SimpleXMLElement $el)
299 {
300 $feed->ttl = (integer) $el;
301 }
302
303 /**
304 * Method to handle the `<webmaster>` element for the feed.
305 *
306 * @param JFeed $feed The JFeed object being built from the parsed feed.
307 * @param SimpleXMLElement $el The current XML element object to handle.
308 *
309 * @return void
310 *
311 * @since 12.3
312 */
313 protected function handleWebmaster(JFeed $feed, SimpleXMLElement $el)
314 {
315 // Get the tag contents and split it over the first space.
316 $tmp = (string) $el;
317 $tmp = explode(' ', $tmp, 2);
318
319 // This is really cheap parsing. Probably need to create a method to do this more robustly.
320 $name = null;
321
322 if (isset($tmp[1]))
323 {
324 $name = trim($tmp[1], ' ()');
325 }
326
327 $email = trim($tmp[0]);
328
329 $feed->addContributor($name, $email, null, 'webmaster');
330 }
331
332 /**
333 * Method to initialise the feed for parsing. Here we detect the version and advance the stream
334 * reader so that it is ready to parse feed elements.
335 *
336 * @return void
337 *
338 * @since 12.3
339 */
340 protected function initialise()
341 {
342 // Read the version attribute.
343 $this->version = $this->stream->getAttribute('version');
344
345 // We want to move forward to the first element after the <channel> element.
346 $this->moveToNextElement('channel');
347 $this->moveToNextElement();
348 }
349
350 /**
351 * Method to handle a `<item>` element for the feed.
352 *
353 * @param JFeedEntry $entry The JFeedEntry object being built from the parsed feed entry.
354 * @param SimpleXMLElement $el The current XML element object to handle.
355 *
356 * @return void
357 *
358 * @since 12.3
359 */
360 protected function processFeedEntry(JFeedEntry $entry, SimpleXMLElement $el)
361 {
362 $entry->uri = (string) $el->link;
363 $entry->title = (string) $el->title;
364 $entry->publishedDate = (string) $el->pubDate;
365 $entry->updatedDate = (string) $el->pubDate;
366 $entry->content = (string) $el->description;
367 $entry->guid = (string) $el->guid;
368 $entry->comments = (string) $el->comments;
369
370 // Add the feed entry author if available.
371 $author = (string) $el->author;
372
373 if (!empty($author))
374 {
375 $entry->author = $this->processPerson($author);
376 }
377
378 // Add any categories to the entry.
379 foreach ($el->category as $category)
380 {
381 $entry->addCategory((string) $category, (string) $category['domain']);
382 }
383
384 // Add any enclosures to the entry.
385 foreach ($el->enclosure as $enclosure)
386 {
387 $link = new JFeedLink(
388 (string) $enclosure['url'],
389 null,
390 (string) $enclosure['type'],
391 null,
392 null,
393 (int) $enclosure['length']
394 );
395
396 $entry->addLink($link);
397 }
398 }
399
400 /**
401 * Method to parse a string with person data and return a JFeedPerson object.
402 *
403 * @param string $data The string to parse for a person.
404 *
405 * @return JFeedPerson
406 *
407 * @since 12.3
408 */
409 protected function processPerson($data)
410 {
411 // Create a new person object.
412 $person = new JFeedPerson;
413
414 // This is really cheap parsing, but so far good enough. :)
415 $data = explode(' ', $data, 2);
416
417 if (isset($data[1]))
418 {
419 $person->name = trim($data[1], ' ()');
420 }
421
422 // Set the email for the person.
423 $person->email = trim($data[0]);
424
425 return $person;
426 }
427 }
428