comparison vendor/zendframework/zend-feed/src/Reader/Entry/Rss.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 7a779792577d
comparison
equal deleted inserted replaced
-1:000000000000 0:4c8ae668cc8c
1 <?php
2 /**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10 namespace Zend\Feed\Reader\Entry;
11
12 use DateTime;
13 use DOMElement;
14 use DOMXPath;
15 use Zend\Feed\Reader;
16 use Zend\Feed\Reader\Exception;
17
18 class Rss extends AbstractEntry implements EntryInterface
19 {
20 /**
21 * XPath query for RDF
22 *
23 * @var string
24 */
25 protected $xpathQueryRdf = '';
26
27 /**
28 * XPath query for RSS
29 *
30 * @var string
31 */
32 protected $xpathQueryRss = '';
33
34 /**
35 * Constructor
36 *
37 * @param DOMElement $entry
38 * @param string $entryKey
39 * @param string $type
40 */
41 public function __construct(DOMElement $entry, $entryKey, $type = null)
42 {
43 parent::__construct($entry, $entryKey, $type);
44 $this->xpathQueryRss = '//item[' . ($this->entryKey+1) . ']';
45 $this->xpathQueryRdf = '//rss:item[' . ($this->entryKey+1) . ']';
46
47 $manager = Reader\Reader::getExtensionManager();
48 $extensions = [
49 'DublinCore\Entry',
50 'Content\Entry',
51 'Atom\Entry',
52 'WellFormedWeb\Entry',
53 'Slash\Entry',
54 'Thread\Entry',
55 ];
56 foreach ($extensions as $name) {
57 $extension = $manager->get($name);
58 $extension->setEntryElement($entry);
59 $extension->setEntryKey($entryKey);
60 $extension->setType($type);
61 $this->extensions[$name] = $extension;
62 }
63 }
64
65 /**
66 * Get an author entry
67 *
68 * @param int $index
69 * @return string
70 */
71 public function getAuthor($index = 0)
72 {
73 $authors = $this->getAuthors();
74
75 if (isset($authors[$index])) {
76 return $authors[$index];
77 }
78
79 return;
80 }
81
82 /**
83 * Get an array with feed authors
84 *
85 * @return array
86 */
87 public function getAuthors()
88 {
89 if (array_key_exists('authors', $this->data)) {
90 return $this->data['authors'];
91 }
92
93 $authors = [];
94 $authorsDc = $this->getExtension('DublinCore')->getAuthors();
95 if (!empty($authorsDc)) {
96 foreach ($authorsDc as $author) {
97 $authors[] = [
98 'name' => $author['name']
99 ];
100 }
101 }
102
103 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
104 && $this->getType() !== Reader\Reader::TYPE_RSS_090) {
105 $list = $this->xpath->query($this->xpathQueryRss . '//author');
106 } else {
107 $list = $this->xpath->query($this->xpathQueryRdf . '//rss:author');
108 }
109 if ($list->length) {
110 foreach ($list as $author) {
111 $string = trim($author->nodeValue);
112 $data = [];
113 // Pretty rough parsing - but it's a catchall
114 if (preg_match("/^.*@[^ ]*/", $string, $matches)) {
115 $data['email'] = trim($matches[0]);
116 if (preg_match("/\((.*)\)$/", $string, $matches)) {
117 $data['name'] = $matches[1];
118 }
119 $authors[] = $data;
120 }
121 }
122 }
123
124 if (count($authors) == 0) {
125 $authors = $this->getExtension('Atom')->getAuthors();
126 } else {
127 $authors = new Reader\Collection\Author(
128 Reader\Reader::arrayUnique($authors)
129 );
130 }
131
132 if (count($authors) == 0) {
133 $authors = null;
134 }
135
136 $this->data['authors'] = $authors;
137
138 return $this->data['authors'];
139 }
140
141 /**
142 * Get the entry content
143 *
144 * @return string
145 */
146 public function getContent()
147 {
148 if (array_key_exists('content', $this->data)) {
149 return $this->data['content'];
150 }
151
152 $content = $this->getExtension('Content')->getContent();
153
154 if (!$content) {
155 $content = $this->getDescription();
156 }
157
158 if (empty($content)) {
159 $content = $this->getExtension('Atom')->getContent();
160 }
161
162 $this->data['content'] = $content;
163
164 return $this->data['content'];
165 }
166
167 /**
168 * Get the entry's date of creation
169 *
170 * @return \DateTime
171 */
172 public function getDateCreated()
173 {
174 return $this->getDateModified();
175 }
176
177 /**
178 * Get the entry's date of modification
179 *
180 * @throws Exception\RuntimeException
181 * @return \DateTime
182 */
183 public function getDateModified()
184 {
185 if (array_key_exists('datemodified', $this->data)) {
186 return $this->data['datemodified'];
187 }
188
189 $date = null;
190
191 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
192 && $this->getType() !== Reader\Reader::TYPE_RSS_090
193 ) {
194 $dateModified = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/pubDate)');
195 if ($dateModified) {
196 $dateModifiedParsed = strtotime($dateModified);
197 if ($dateModifiedParsed) {
198 $date = new DateTime('@' . $dateModifiedParsed);
199 } else {
200 $dateStandards = [DateTime::RSS, DateTime::RFC822,
201 DateTime::RFC2822, null];
202 foreach ($dateStandards as $standard) {
203 try {
204 $date = date_create_from_format($standard, $dateModified);
205 break;
206 } catch (\Exception $e) {
207 if ($standard === null) {
208 throw new Exception\RuntimeException(
209 'Could not load date due to unrecognised'
210 .' format (should follow RFC 822 or 2822):'
211 . $e->getMessage(),
212 0, $e
213 );
214 }
215 }
216 }
217 }
218 }
219 }
220
221 if (!$date) {
222 $date = $this->getExtension('DublinCore')->getDate();
223 }
224
225 if (!$date) {
226 $date = $this->getExtension('Atom')->getDateModified();
227 }
228
229 if (!$date) {
230 $date = null;
231 }
232
233 $this->data['datemodified'] = $date;
234
235 return $this->data['datemodified'];
236 }
237
238 /**
239 * Get the entry description
240 *
241 * @return string
242 */
243 public function getDescription()
244 {
245 if (array_key_exists('description', $this->data)) {
246 return $this->data['description'];
247 }
248
249 $description = null;
250
251 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
252 && $this->getType() !== Reader\Reader::TYPE_RSS_090
253 ) {
254 $description = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/description)');
255 } else {
256 $description = $this->xpath->evaluate('string(' . $this->xpathQueryRdf . '/rss:description)');
257 }
258
259 if (!$description) {
260 $description = $this->getExtension('DublinCore')->getDescription();
261 }
262
263 if (empty($description)) {
264 $description = $this->getExtension('Atom')->getDescription();
265 }
266
267 if (!$description) {
268 $description = null;
269 }
270
271 $this->data['description'] = $description;
272
273 return $this->data['description'];
274 }
275
276 /**
277 * Get the entry enclosure
278 * @return string
279 */
280 public function getEnclosure()
281 {
282 if (array_key_exists('enclosure', $this->data)) {
283 return $this->data['enclosure'];
284 }
285
286 $enclosure = null;
287
288 if ($this->getType() == Reader\Reader::TYPE_RSS_20) {
289 $nodeList = $this->xpath->query($this->xpathQueryRss . '/enclosure');
290
291 if ($nodeList->length > 0) {
292 $enclosure = new \stdClass();
293 $enclosure->url = $nodeList->item(0)->getAttribute('url');
294 $enclosure->length = $nodeList->item(0)->getAttribute('length');
295 $enclosure->type = $nodeList->item(0)->getAttribute('type');
296 }
297 }
298
299 if (!$enclosure) {
300 $enclosure = $this->getExtension('Atom')->getEnclosure();
301 }
302
303 $this->data['enclosure'] = $enclosure;
304
305 return $this->data['enclosure'];
306 }
307
308 /**
309 * Get the entry ID
310 *
311 * @return string
312 */
313 public function getId()
314 {
315 if (array_key_exists('id', $this->data)) {
316 return $this->data['id'];
317 }
318
319 $id = null;
320
321 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
322 && $this->getType() !== Reader\Reader::TYPE_RSS_090
323 ) {
324 $id = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/guid)');
325 }
326
327 if (!$id) {
328 $id = $this->getExtension('DublinCore')->getId();
329 }
330
331 if (empty($id)) {
332 $id = $this->getExtension('Atom')->getId();
333 }
334
335 if (!$id) {
336 if ($this->getPermalink()) {
337 $id = $this->getPermalink();
338 } elseif ($this->getTitle()) {
339 $id = $this->getTitle();
340 } else {
341 $id = null;
342 }
343 }
344
345 $this->data['id'] = $id;
346
347 return $this->data['id'];
348 }
349
350 /**
351 * Get a specific link
352 *
353 * @param int $index
354 * @return string
355 */
356 public function getLink($index = 0)
357 {
358 if (!array_key_exists('links', $this->data)) {
359 $this->getLinks();
360 }
361
362 if (isset($this->data['links'][$index])) {
363 return $this->data['links'][$index];
364 }
365
366 return;
367 }
368
369 /**
370 * Get all links
371 *
372 * @return array
373 */
374 public function getLinks()
375 {
376 if (array_key_exists('links', $this->data)) {
377 return $this->data['links'];
378 }
379
380 $links = [];
381
382 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
383 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
384 $list = $this->xpath->query($this->xpathQueryRss . '//link');
385 } else {
386 $list = $this->xpath->query($this->xpathQueryRdf . '//rss:link');
387 }
388
389 if (!$list->length) {
390 $links = $this->getExtension('Atom')->getLinks();
391 } else {
392 foreach ($list as $link) {
393 $links[] = $link->nodeValue;
394 }
395 }
396
397 $this->data['links'] = $links;
398
399 return $this->data['links'];
400 }
401
402 /**
403 * Get all categories
404 *
405 * @return Reader\Collection\Category
406 */
407 public function getCategories()
408 {
409 if (array_key_exists('categories', $this->data)) {
410 return $this->data['categories'];
411 }
412
413 if ($this->getType() !== Reader\Reader::TYPE_RSS_10 &&
414 $this->getType() !== Reader\Reader::TYPE_RSS_090) {
415 $list = $this->xpath->query($this->xpathQueryRss . '//category');
416 } else {
417 $list = $this->xpath->query($this->xpathQueryRdf . '//rss:category');
418 }
419
420 if ($list->length) {
421 $categoryCollection = new Reader\Collection\Category;
422 foreach ($list as $category) {
423 $categoryCollection[] = [
424 'term' => $category->nodeValue,
425 'scheme' => $category->getAttribute('domain'),
426 'label' => $category->nodeValue,
427 ];
428 }
429 } else {
430 $categoryCollection = $this->getExtension('DublinCore')->getCategories();
431 }
432
433 if (count($categoryCollection) == 0) {
434 $categoryCollection = $this->getExtension('Atom')->getCategories();
435 }
436
437 $this->data['categories'] = $categoryCollection;
438
439 return $this->data['categories'];
440 }
441
442 /**
443 * Get a permalink to the entry
444 *
445 * @return string
446 */
447 public function getPermalink()
448 {
449 return $this->getLink(0);
450 }
451
452 /**
453 * Get the entry title
454 *
455 * @return string
456 */
457 public function getTitle()
458 {
459 if (array_key_exists('title', $this->data)) {
460 return $this->data['title'];
461 }
462
463 $title = null;
464
465 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
466 && $this->getType() !== Reader\Reader::TYPE_RSS_090
467 ) {
468 $title = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/title)');
469 } else {
470 $title = $this->xpath->evaluate('string(' . $this->xpathQueryRdf . '/rss:title)');
471 }
472
473 if (!$title) {
474 $title = $this->getExtension('DublinCore')->getTitle();
475 }
476
477 if (!$title) {
478 $title = $this->getExtension('Atom')->getTitle();
479 }
480
481 if (!$title) {
482 $title = null;
483 }
484
485 $this->data['title'] = $title;
486
487 return $this->data['title'];
488 }
489
490 /**
491 * Get the number of comments/replies for current entry
492 *
493 * @return string|null
494 */
495 public function getCommentCount()
496 {
497 if (array_key_exists('commentcount', $this->data)) {
498 return $this->data['commentcount'];
499 }
500
501 $commentcount = $this->getExtension('Slash')->getCommentCount();
502
503 if (!$commentcount) {
504 $commentcount = $this->getExtension('Thread')->getCommentCount();
505 }
506
507 if (!$commentcount) {
508 $commentcount = $this->getExtension('Atom')->getCommentCount();
509 }
510
511 if (!$commentcount) {
512 $commentcount = null;
513 }
514
515 $this->data['commentcount'] = $commentcount;
516
517 return $this->data['commentcount'];
518 }
519
520 /**
521 * Returns a URI pointing to the HTML page where comments can be made on this entry
522 *
523 * @return string
524 */
525 public function getCommentLink()
526 {
527 if (array_key_exists('commentlink', $this->data)) {
528 return $this->data['commentlink'];
529 }
530
531 $commentlink = null;
532
533 if ($this->getType() !== Reader\Reader::TYPE_RSS_10
534 && $this->getType() !== Reader\Reader::TYPE_RSS_090
535 ) {
536 $commentlink = $this->xpath->evaluate('string(' . $this->xpathQueryRss . '/comments)');
537 }
538
539 if (!$commentlink) {
540 $commentlink = $this->getExtension('Atom')->getCommentLink();
541 }
542
543 if (!$commentlink) {
544 $commentlink = null;
545 }
546
547 $this->data['commentlink'] = $commentlink;
548
549 return $this->data['commentlink'];
550 }
551
552 /**
553 * Returns a URI pointing to a feed of all comments for this entry
554 *
555 * @return string
556 */
557 public function getCommentFeedLink()
558 {
559 if (array_key_exists('commentfeedlink', $this->data)) {
560 return $this->data['commentfeedlink'];
561 }
562
563 $commentfeedlink = $this->getExtension('WellFormedWeb')->getCommentFeedLink();
564
565 if (!$commentfeedlink) {
566 $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rss');
567 }
568
569 if (!$commentfeedlink) {
570 $commentfeedlink = $this->getExtension('Atom')->getCommentFeedLink('rdf');
571 }
572
573 if (!$commentfeedlink) {
574 $commentfeedlink = null;
575 }
576
577 $this->data['commentfeedlink'] = $commentfeedlink;
578
579 return $this->data['commentfeedlink'];
580 }
581
582 /**
583 * Set the XPath query (incl. on all Extensions)
584 *
585 * @param DOMXPath $xpath
586 * @return void
587 */
588 public function setXpath(DOMXPath $xpath)
589 {
590 parent::setXpath($xpath);
591 foreach ($this->extensions as $extension) {
592 $extension->setXpath($this->xpath);
593 }
594 }
595 }