/libraries/src/Feed/Parser/AtomParser.php

https://github.com/joomla/joomla-cms · PHP · 258 lines · 99 code · 26 blank · 133 comment · 8 complexity · 76e34a5b7f043f738b9fe8fe14627d0a MD5 · raw file

  1. <?php
  2. /**
  3. * Joomla! Content Management System
  4. *
  5. * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org>
  6. * @license GNU General Public License version 2 or later; see LICENSE.txt
  7. */
  8. namespace Joomla\CMS\Feed\Parser;
  9. use Joomla\CMS\Feed\Feed;
  10. use Joomla\CMS\Feed\FeedEntry;
  11. use Joomla\CMS\Feed\FeedLink;
  12. use Joomla\CMS\Feed\FeedParser;
  13. /**
  14. * ATOM Feed Parser class.
  15. *
  16. * @link http://www.atomenabled.org/developers/syndication/
  17. * @since 3.1.4
  18. */
  19. class AtomParser extends FeedParser
  20. {
  21. /**
  22. * @var string The feed format version.
  23. * @since 3.1.4
  24. */
  25. protected $version;
  26. /**
  27. * Method to handle the `<author>` element for the feed.
  28. *
  29. * @param Feed $feed The Feed object being built from the parsed feed.
  30. * @param \SimpleXMLElement $el The current XML element object to handle.
  31. *
  32. * @return void
  33. *
  34. * @since 3.1.4
  35. */
  36. protected function handleAuthor(Feed $feed, \SimpleXMLElement $el)
  37. {
  38. // Set the author information from the XML element.
  39. $feed->setAuthor(
  40. $this->inputFilter->clean((string) $el->name, 'html'),
  41. filter_var((string) $el->email, FILTER_VALIDATE_EMAIL),
  42. filter_var((string) $el->uri, FILTER_VALIDATE_URL)
  43. );
  44. }
  45. /**
  46. * Method to handle the `<contributor>` element for the feed.
  47. *
  48. * @param Feed $feed The Feed object being built from the parsed feed.
  49. * @param \SimpleXMLElement $el The current XML element object to handle.
  50. *
  51. * @return void
  52. *
  53. * @since 3.1.4
  54. */
  55. protected function handleContributor(Feed $feed, \SimpleXMLElement $el)
  56. {
  57. $feed->addContributor(
  58. $this->inputFilter->clean((string) $el->name, 'html'),
  59. filter_var((string) $el->email, FILTER_VALIDATE_EMAIL),
  60. filter_var((string) $el->uri, FILTER_VALIDATE_URL)
  61. );
  62. }
  63. /**
  64. * Method to handle the `<generator>` element for the feed.
  65. *
  66. * @param Feed $feed The Feed object being built from the parsed feed.
  67. * @param \SimpleXMLElement $el The current XML element object to handle.
  68. *
  69. * @return void
  70. *
  71. * @since 3.1.4
  72. */
  73. protected function handleGenerator(Feed $feed, \SimpleXMLElement $el)
  74. {
  75. $feed->generator = $this->inputFilter->clean((string) $el, 'html');
  76. }
  77. /**
  78. * Method to handle the `<id>` element for the feed.
  79. *
  80. * @param Feed $feed The Feed object being built from the parsed feed.
  81. * @param \SimpleXMLElement $el The current XML element object to handle.
  82. *
  83. * @return void
  84. *
  85. * @since 3.1.4
  86. */
  87. protected function handleId(Feed $feed, \SimpleXMLElement $el)
  88. {
  89. $feed->uri = (string) $el;
  90. }
  91. /**
  92. * Method to handle the `<link>` element for the feed.
  93. *
  94. * @param Feed $feed The Feed object being built from the parsed feed.
  95. * @param \SimpleXMLElement $el The current XML element object to handle.
  96. *
  97. * @return void
  98. *
  99. * @since 3.1.4
  100. */
  101. protected function handleLink(Feed $feed, \SimpleXMLElement $el)
  102. {
  103. $link = new FeedLink();
  104. $link->uri = (string) $el['href'];
  105. $link->language = (string) $el['hreflang'];
  106. $link->length = (int) $el['length'];
  107. $link->relation = (string) $el['rel'];
  108. $link->title = $this->inputFilter->clean((string) $el['title'], 'html');
  109. $link->type = (string) $el['type'];
  110. $feed->link = $link;
  111. }
  112. /**
  113. * Method to handle the `<rights>` element for the feed.
  114. *
  115. * @param Feed $feed The Feed object being built from the parsed feed.
  116. * @param \SimpleXMLElement $el The current XML element object to handle.
  117. *
  118. * @return void
  119. *
  120. * @since 3.1.4
  121. */
  122. protected function handleRights(Feed $feed, \SimpleXMLElement $el)
  123. {
  124. $feed->copyright = $this->inputFilter->clean((string) $el, 'html');
  125. }
  126. /**
  127. * Method to handle the `<subtitle>` element for the feed.
  128. *
  129. * @param Feed $feed The Feed object being built from the parsed feed.
  130. * @param \SimpleXMLElement $el The current XML element object to handle.
  131. *
  132. * @return void
  133. *
  134. * @since 3.1.4
  135. */
  136. protected function handleSubtitle(Feed $feed, \SimpleXMLElement $el)
  137. {
  138. $feed->description = $this->inputFilter->clean((string) $el, 'html');
  139. }
  140. /**
  141. * Method to handle the `<title>` element for the feed.
  142. *
  143. * @param Feed $feed The Feed object being built from the parsed feed.
  144. * @param \SimpleXMLElement $el The current XML element object to handle.
  145. *
  146. * @return void
  147. *
  148. * @since 3.1.4
  149. */
  150. protected function handleTitle(Feed $feed, \SimpleXMLElement $el)
  151. {
  152. $feed->title = $this->inputFilter->clean((string) $el, 'html');
  153. }
  154. /**
  155. * Method to handle the `<updated>` element for the feed.
  156. *
  157. * @param Feed $feed The Feed object being built from the parsed feed.
  158. * @param \SimpleXMLElement $el The current XML element object to handle.
  159. *
  160. * @return void
  161. *
  162. * @since 3.1.4
  163. */
  164. protected function handleUpdated(Feed $feed, \SimpleXMLElement $el)
  165. {
  166. $feed->updatedDate = $this->inputFilter->clean((string) $el, 'html');
  167. }
  168. /**
  169. * Method to initialise the feed for parsing. Here we detect the version and advance the stream
  170. * reader so that it is ready to parse feed elements.
  171. *
  172. * @return void
  173. *
  174. * @since 3.1.4
  175. */
  176. protected function initialise()
  177. {
  178. // We want to move forward to the first XML Element after the xml doc type declaration
  179. $this->moveToNextElement();
  180. $this->version = ($this->stream->getAttribute('version') == '0.3') ? '0.3' : '1.0';
  181. }
  182. /**
  183. * Method to handle a `<entry>` element for the feed.
  184. *
  185. * @param FeedEntry $entry The FeedEntry object being built from the parsed feed entry.
  186. * @param \SimpleXMLElement $el The current XML element object to handle.
  187. *
  188. * @return void
  189. *
  190. * @since 3.1.4
  191. */
  192. protected function processFeedEntry(FeedEntry $entry, \SimpleXMLElement $el)
  193. {
  194. $entry->uri = (string) $el->id;
  195. $entry->title = $this->inputFilter->clean((string) $el->title, 'html');
  196. $entry->updatedDate = $this->inputFilter->clean((string) $el->updated, 'html');
  197. $entry->content = $this->inputFilter->clean((string) $el->summary, 'html');
  198. if (!$entry->content) {
  199. $entry->content = $this->inputFilter->clean((string) $el->content, 'html');
  200. }
  201. if (filter_var($entry->uri, FILTER_VALIDATE_URL) === false && !\is_null($el->link) && $el->link) {
  202. $link = $el->link;
  203. if (\is_array($link)) {
  204. $link = $this->bestLinkForUri($link);
  205. }
  206. $uri = (string) $link['href'];
  207. if ($uri) {
  208. $entry->uri = $uri;
  209. }
  210. }
  211. }
  212. /**
  213. * If there is more than one <link> in the feed entry, find the most appropriate one and return it.
  214. *
  215. * @param array $links Array of <link> elements from the feed entry.
  216. *
  217. * @return \SimpleXMLElement
  218. */
  219. private function bestLinkForUri(array $links)
  220. {
  221. $linkPrefs = array('', 'self', 'alternate');
  222. foreach ($linkPrefs as $pref) {
  223. foreach ($links as $link) {
  224. $rel = (string) $link['rel'];
  225. if ($rel === $pref) {
  226. return $link;
  227. }
  228. }
  229. }
  230. return array_shift($links);
  231. }
  232. }