PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/zendframework/zend-feed/src/Reader/Extension/Atom/Feed.php

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