Mercurial > hg > cmmr2012-drupal-site
comparison vendor/zendframework/zend-feed/src/Reader/Extension/Atom/Feed.php @ 0:c75dbcec494b
Initial commit from drush-created site
author | Chris Cannam |
---|---|
date | Thu, 05 Jul 2018 14:24:15 +0000 |
parents | |
children | 5311817fb629 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c75dbcec494b |
---|---|
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\Extension\Atom; | |
11 | |
12 use DateTime; | |
13 use DOMElement; | |
14 use Zend\Feed\Reader; | |
15 use Zend\Feed\Reader\Collection; | |
16 use Zend\Feed\Reader\Extension; | |
17 use Zend\Feed\Uri; | |
18 | |
19 class Feed extends Extension\AbstractFeed | |
20 { | |
21 /** | |
22 * Get a single author | |
23 * | |
24 * @param int $index | |
25 * @return string|null | |
26 */ | |
27 public function getAuthor($index = 0) | |
28 { | |
29 $authors = $this->getAuthors(); | |
30 | |
31 if (isset($authors[$index])) { | |
32 return $authors[$index]; | |
33 } | |
34 | |
35 return; | |
36 } | |
37 | |
38 /** | |
39 * Get an array with feed authors | |
40 * | |
41 * @return Collection\Author | |
42 */ | |
43 public function getAuthors() | |
44 { | |
45 if (array_key_exists('authors', $this->data)) { | |
46 return $this->data['authors']; | |
47 } | |
48 | |
49 $list = $this->xpath->query('//atom:author'); | |
50 | |
51 $authors = []; | |
52 | |
53 if ($list->length) { | |
54 foreach ($list as $author) { | |
55 $author = $this->getAuthorFromElement($author); | |
56 if (!empty($author)) { | |
57 $authors[] = $author; | |
58 } | |
59 } | |
60 } | |
61 | |
62 if (count($authors) == 0) { | |
63 $authors = new Collection\Author(); | |
64 } else { | |
65 $authors = new Collection\Author( | |
66 Reader\Reader::arrayUnique($authors) | |
67 ); | |
68 } | |
69 | |
70 $this->data['authors'] = $authors; | |
71 | |
72 return $this->data['authors']; | |
73 } | |
74 | |
75 /** | |
76 * Get the copyright entry | |
77 * | |
78 * @return string|null | |
79 */ | |
80 public function getCopyright() | |
81 { | |
82 if (array_key_exists('copyright', $this->data)) { | |
83 return $this->data['copyright']; | |
84 } | |
85 | |
86 $copyright = null; | |
87 | |
88 if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { | |
89 $copyright = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:copyright)'); | |
90 } else { | |
91 $copyright = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:rights)'); | |
92 } | |
93 | |
94 if (!$copyright) { | |
95 $copyright = null; | |
96 } | |
97 | |
98 $this->data['copyright'] = $copyright; | |
99 | |
100 return $this->data['copyright']; | |
101 } | |
102 | |
103 /** | |
104 * Get the feed creation date | |
105 * | |
106 * @return DateTime|null | |
107 */ | |
108 public function getDateCreated() | |
109 { | |
110 if (array_key_exists('datecreated', $this->data)) { | |
111 return $this->data['datecreated']; | |
112 } | |
113 | |
114 $date = null; | |
115 | |
116 if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { | |
117 $dateCreated = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:created)'); | |
118 } else { | |
119 $dateCreated = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:published)'); | |
120 } | |
121 | |
122 if ($dateCreated) { | |
123 $date = new DateTime($dateCreated); | |
124 } | |
125 | |
126 $this->data['datecreated'] = $date; | |
127 | |
128 return $this->data['datecreated']; | |
129 } | |
130 | |
131 /** | |
132 * Get the feed modification date | |
133 * | |
134 * @return DateTime|null | |
135 */ | |
136 public function getDateModified() | |
137 { | |
138 if (array_key_exists('datemodified', $this->data)) { | |
139 return $this->data['datemodified']; | |
140 } | |
141 | |
142 $date = null; | |
143 | |
144 if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { | |
145 $dateModified = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:modified)'); | |
146 } else { | |
147 $dateModified = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:updated)'); | |
148 } | |
149 | |
150 if ($dateModified) { | |
151 $date = new DateTime($dateModified); | |
152 } | |
153 | |
154 $this->data['datemodified'] = $date; | |
155 | |
156 return $this->data['datemodified']; | |
157 } | |
158 | |
159 /** | |
160 * Get the feed description | |
161 * | |
162 * @return string|null | |
163 */ | |
164 public function getDescription() | |
165 { | |
166 if (array_key_exists('description', $this->data)) { | |
167 return $this->data['description']; | |
168 } | |
169 | |
170 $description = null; | |
171 | |
172 if ($this->getType() === Reader\Reader::TYPE_ATOM_03) { | |
173 $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:tagline)'); | |
174 } else { | |
175 $description = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:subtitle)'); | |
176 } | |
177 | |
178 if (!$description) { | |
179 $description = null; | |
180 } | |
181 | |
182 $this->data['description'] = $description; | |
183 | |
184 return $this->data['description']; | |
185 } | |
186 | |
187 /** | |
188 * Get the feed generator entry | |
189 * | |
190 * @return string|null | |
191 */ | |
192 public function getGenerator() | |
193 { | |
194 if (array_key_exists('generator', $this->data)) { | |
195 return $this->data['generator']; | |
196 } | |
197 // TODO: Add uri support | |
198 $generator = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:generator)'); | |
199 | |
200 if (!$generator) { | |
201 $generator = null; | |
202 } | |
203 | |
204 $this->data['generator'] = $generator; | |
205 | |
206 return $this->data['generator']; | |
207 } | |
208 | |
209 /** | |
210 * Get the feed ID | |
211 * | |
212 * @return string|null | |
213 */ | |
214 public function getId() | |
215 { | |
216 if (array_key_exists('id', $this->data)) { | |
217 return $this->data['id']; | |
218 } | |
219 | |
220 $id = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:id)'); | |
221 | |
222 if (!$id) { | |
223 if ($this->getLink()) { | |
224 $id = $this->getLink(); | |
225 } elseif ($this->getTitle()) { | |
226 $id = $this->getTitle(); | |
227 } else { | |
228 $id = null; | |
229 } | |
230 } | |
231 | |
232 $this->data['id'] = $id; | |
233 | |
234 return $this->data['id']; | |
235 } | |
236 | |
237 /** | |
238 * Get the feed language | |
239 * | |
240 * @return string|null | |
241 */ | |
242 public function getLanguage() | |
243 { | |
244 if (array_key_exists('language', $this->data)) { | |
245 return $this->data['language']; | |
246 } | |
247 | |
248 $language = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:lang)'); | |
249 | |
250 if (!$language) { | |
251 $language = $this->xpath->evaluate('string(//@xml:lang[1])'); | |
252 } | |
253 | |
254 if (!$language) { | |
255 $language = null; | |
256 } | |
257 | |
258 $this->data['language'] = $language; | |
259 | |
260 return $this->data['language']; | |
261 } | |
262 | |
263 /** | |
264 * Get the feed image | |
265 * | |
266 * @return array|null | |
267 */ | |
268 public function getImage() | |
269 { | |
270 if (array_key_exists('image', $this->data)) { | |
271 return $this->data['image']; | |
272 } | |
273 | |
274 $imageUrl = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:logo)'); | |
275 | |
276 if (!$imageUrl) { | |
277 $image = null; | |
278 } else { | |
279 $image = ['uri' => $imageUrl]; | |
280 } | |
281 | |
282 $this->data['image'] = $image; | |
283 | |
284 return $this->data['image']; | |
285 } | |
286 | |
287 /** | |
288 * Get the base URI of the feed (if set). | |
289 * | |
290 * @return string|null | |
291 */ | |
292 public function getBaseUrl() | |
293 { | |
294 if (array_key_exists('baseUrl', $this->data)) { | |
295 return $this->data['baseUrl']; | |
296 } | |
297 | |
298 $baseUrl = $this->xpath->evaluate('string(//@xml:base[1])'); | |
299 | |
300 if (!$baseUrl) { | |
301 $baseUrl = null; | |
302 } | |
303 $this->data['baseUrl'] = $baseUrl; | |
304 | |
305 return $this->data['baseUrl']; | |
306 } | |
307 | |
308 /** | |
309 * Get a link to the source website | |
310 * | |
311 * @return string|null | |
312 */ | |
313 public function getLink() | |
314 { | |
315 if (array_key_exists('link', $this->data)) { | |
316 return $this->data['link']; | |
317 } | |
318 | |
319 $link = null; | |
320 | |
321 $list = $this->xpath->query( | |
322 $this->getXpathPrefix() . '/atom:link[@rel="alternate"]/@href' . '|' . | |
323 $this->getXpathPrefix() . '/atom:link[not(@rel)]/@href' | |
324 ); | |
325 | |
326 if ($list->length) { | |
327 $link = $list->item(0)->nodeValue; | |
328 $link = $this->absolutiseUri($link); | |
329 } | |
330 | |
331 $this->data['link'] = $link; | |
332 | |
333 return $this->data['link']; | |
334 } | |
335 | |
336 /** | |
337 * Get a link to the feed's XML Url | |
338 * | |
339 * @return string|null | |
340 */ | |
341 public function getFeedLink() | |
342 { | |
343 if (array_key_exists('feedlink', $this->data)) { | |
344 return $this->data['feedlink']; | |
345 } | |
346 | |
347 $link = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:link[@rel="self"]/@href)'); | |
348 | |
349 $link = $this->absolutiseUri($link); | |
350 | |
351 $this->data['feedlink'] = $link; | |
352 | |
353 return $this->data['feedlink']; | |
354 } | |
355 | |
356 /** | |
357 * Get an array of any supported Pusubhubbub endpoints | |
358 * | |
359 * @return array|null | |
360 */ | |
361 public function getHubs() | |
362 { | |
363 if (array_key_exists('hubs', $this->data)) { | |
364 return $this->data['hubs']; | |
365 } | |
366 $hubs = []; | |
367 | |
368 $list = $this->xpath->query($this->getXpathPrefix() | |
369 . '//atom:link[@rel="hub"]/@href'); | |
370 | |
371 if ($list->length) { | |
372 foreach ($list as $uri) { | |
373 $hubs[] = $this->absolutiseUri($uri->nodeValue); | |
374 } | |
375 } else { | |
376 $hubs = null; | |
377 } | |
378 | |
379 $this->data['hubs'] = $hubs; | |
380 | |
381 return $this->data['hubs']; | |
382 } | |
383 | |
384 /** | |
385 * Get the feed title | |
386 * | |
387 * @return string|null | |
388 */ | |
389 public function getTitle() | |
390 { | |
391 if (array_key_exists('title', $this->data)) { | |
392 return $this->data['title']; | |
393 } | |
394 | |
395 $title = $this->xpath->evaluate('string(' . $this->getXpathPrefix() . '/atom:title)'); | |
396 | |
397 if (!$title) { | |
398 $title = null; | |
399 } | |
400 | |
401 $this->data['title'] = $title; | |
402 | |
403 return $this->data['title']; | |
404 } | |
405 | |
406 /** | |
407 * Get all categories | |
408 * | |
409 * @return Collection\Category | |
410 */ | |
411 public function getCategories() | |
412 { | |
413 if (array_key_exists('categories', $this->data)) { | |
414 return $this->data['categories']; | |
415 } | |
416 | |
417 if ($this->getType() == Reader\Reader::TYPE_ATOM_10) { | |
418 $list = $this->xpath->query($this->getXpathPrefix() . '/atom:category'); | |
419 } else { | |
420 /** | |
421 * Since Atom 0.3 did not support categories, it would have used the | |
422 * Dublin Core extension. However there is a small possibility Atom 0.3 | |
423 * may have been retrofittied to use Atom 1.0 instead. | |
424 */ | |
425 $this->xpath->registerNamespace('atom10', Reader\Reader::NAMESPACE_ATOM_10); | |
426 $list = $this->xpath->query($this->getXpathPrefix() . '/atom10:category'); | |
427 } | |
428 | |
429 if ($list->length) { | |
430 $categoryCollection = new Collection\Category; | |
431 foreach ($list as $category) { | |
432 $categoryCollection[] = [ | |
433 'term' => $category->getAttribute('term'), | |
434 'scheme' => $category->getAttribute('scheme'), | |
435 'label' => $category->getAttribute('label') | |
436 ]; | |
437 } | |
438 } else { | |
439 return new Collection\Category; | |
440 } | |
441 | |
442 $this->data['categories'] = $categoryCollection; | |
443 | |
444 return $this->data['categories']; | |
445 } | |
446 | |
447 /** | |
448 * Get an author entry in RSS format | |
449 * | |
450 * @param DOMElement $element | |
451 * @return string | |
452 */ | |
453 protected function getAuthorFromElement(DOMElement $element) | |
454 { | |
455 $author = []; | |
456 | |
457 $emailNode = $element->getElementsByTagName('email'); | |
458 $nameNode = $element->getElementsByTagName('name'); | |
459 $uriNode = $element->getElementsByTagName('uri'); | |
460 | |
461 if ($emailNode->length && strlen($emailNode->item(0)->nodeValue) > 0) { | |
462 $author['email'] = $emailNode->item(0)->nodeValue; | |
463 } | |
464 | |
465 if ($nameNode->length && strlen($nameNode->item(0)->nodeValue) > 0) { | |
466 $author['name'] = $nameNode->item(0)->nodeValue; | |
467 } | |
468 | |
469 if ($uriNode->length && strlen($uriNode->item(0)->nodeValue) > 0) { | |
470 $author['uri'] = $uriNode->item(0)->nodeValue; | |
471 } | |
472 | |
473 if (empty($author)) { | |
474 return; | |
475 } | |
476 return $author; | |
477 } | |
478 | |
479 /** | |
480 * Attempt to absolutise the URI, i.e. if a relative URI apply the | |
481 * xml:base value as a prefix to turn into an absolute URI. | |
482 */ | |
483 protected function absolutiseUri($link) | |
484 { | |
485 if (!Uri::factory($link)->isAbsolute()) { | |
486 if ($this->getBaseUrl() !== null) { | |
487 $link = $this->getBaseUrl() . $link; | |
488 if (!Uri::factory($link)->isValid()) { | |
489 $link = null; | |
490 } | |
491 } | |
492 } | |
493 return $link; | |
494 } | |
495 | |
496 /** | |
497 * Register the default namespaces for the current feed format | |
498 */ | |
499 protected function registerNamespaces() | |
500 { | |
501 if ($this->getType() == Reader\Reader::TYPE_ATOM_10 | |
502 || $this->getType() == Reader\Reader::TYPE_ATOM_03 | |
503 ) { | |
504 return; // pre-registered at Feed level | |
505 } | |
506 $atomDetected = $this->getAtomType(); | |
507 switch ($atomDetected) { | |
508 case Reader\Reader::TYPE_ATOM_03: | |
509 $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_03); | |
510 break; | |
511 default: | |
512 $this->xpath->registerNamespace('atom', Reader\Reader::NAMESPACE_ATOM_10); | |
513 break; | |
514 } | |
515 } | |
516 | |
517 /** | |
518 * Detect the presence of any Atom namespaces in use | |
519 */ | |
520 protected function getAtomType() | |
521 { | |
522 $dom = $this->getDomDocument(); | |
523 $prefixAtom03 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_03); | |
524 $prefixAtom10 = $dom->lookupPrefix(Reader\Reader::NAMESPACE_ATOM_10); | |
525 if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_10) | |
526 || !empty($prefixAtom10) | |
527 ) { | |
528 return Reader\Reader::TYPE_ATOM_10; | |
529 } | |
530 if ($dom->isDefaultNamespace(Reader\Reader::NAMESPACE_ATOM_03) | |
531 || !empty($prefixAtom03) | |
532 ) { | |
533 return Reader\Reader::TYPE_ATOM_03; | |
534 } | |
535 } | |
536 } |