/system/classes/kohana/feed.php

https://bitbucket.org/mslepko/default-kohana · PHP · 176 lines · 98 code · 29 blank · 49 comment · 10 complexity · 7e5895bbe51617627242596601488ac6 MD5 · raw file

  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * RSS and Atom feed helper.
  4. *
  5. * @package Kohana
  6. * @category Helpers
  7. * @author Kohana Team
  8. * @copyright (c) 2007-2012 Kohana Team
  9. * @license http://kohanaframework.org/license
  10. */
  11. class Kohana_Feed {
  12. /**
  13. * Parses a remote feed into an array.
  14. *
  15. * @param string $feed remote feed URL
  16. * @param integer $limit item limit to fetch
  17. * @return array
  18. */
  19. public static function parse($feed, $limit = 0)
  20. {
  21. // Check if SimpleXML is installed
  22. if ( ! function_exists('simplexml_load_file'))
  23. throw new Kohana_Exception('SimpleXML must be installed!');
  24. // Make limit an integer
  25. $limit = (int) $limit;
  26. // Disable error reporting while opening the feed
  27. $error_level = error_reporting(0);
  28. // Allow loading by filename or raw XML string
  29. $load = (is_file($feed) OR Valid::url($feed)) ? 'simplexml_load_file' : 'simplexml_load_string';
  30. // Load the feed
  31. $feed = $load($feed, 'SimpleXMLElement', LIBXML_NOCDATA);
  32. // Restore error reporting
  33. error_reporting($error_level);
  34. // Feed could not be loaded
  35. if ($feed === FALSE)
  36. return array();
  37. $namespaces = $feed->getNamespaces(true);
  38. // Detect the feed type. RSS 1.0/2.0 and Atom 1.0 are supported.
  39. $feed = isset($feed->channel) ? $feed->xpath('//item') : $feed->entry;
  40. $i = 0;
  41. $items = array();
  42. foreach ($feed as $item)
  43. {
  44. if ($limit > 0 AND $i++ === $limit)
  45. break;
  46. $item_fields = (array) $item;
  47. // get namespaced tags
  48. foreach ($namespaces as $ns)
  49. {
  50. $item_fields += (array) $item->children($ns);
  51. }
  52. $items[] = $item_fields;
  53. }
  54. return $items;
  55. }
  56. /**
  57. * Creates a feed from the given parameters.
  58. *
  59. * @param array $info feed information
  60. * @param array $items items to add to the feed
  61. * @param string $format define which format to use (only rss2 is supported)
  62. * @param string $encoding define which encoding to use
  63. * @return string
  64. */
  65. public static function create($info, $items, $format = 'rss2', $encoding = 'UTF-8')
  66. {
  67. $info += array('title' => 'Generated Feed', 'link' => '', 'generator' => 'KohanaPHP');
  68. $feed = '<?xml version="1.0" encoding="'.$encoding.'"?><rss version="2.0"><channel></channel></rss>';
  69. $feed = simplexml_load_string($feed);
  70. foreach ($info as $name => $value)
  71. {
  72. if ($name === 'image')
  73. {
  74. // Create an image element
  75. $image = $feed->channel->addChild('image');
  76. if ( ! isset($value['link'], $value['url'], $value['title']))
  77. {
  78. throw new Kohana_Exception('Feed images require a link, url, and title');
  79. }
  80. if (strpos($value['link'], '://') === FALSE)
  81. {
  82. // Convert URIs to URLs
  83. $value['link'] = URL::site($value['link'], 'http');
  84. }
  85. if (strpos($value['url'], '://') === FALSE)
  86. {
  87. // Convert URIs to URLs
  88. $value['url'] = URL::site($value['url'], 'http');
  89. }
  90. // Create the image elements
  91. $image->addChild('link', $value['link']);
  92. $image->addChild('url', $value['url']);
  93. $image->addChild('title', $value['title']);
  94. }
  95. else
  96. {
  97. if (($name === 'pubDate' OR $name === 'lastBuildDate') AND (is_int($value) OR ctype_digit($value)))
  98. {
  99. // Convert timestamps to RFC 822 formatted dates
  100. $value = date('r', $value);
  101. }
  102. elseif (($name === 'link' OR $name === 'docs') AND strpos($value, '://') === FALSE)
  103. {
  104. // Convert URIs to URLs
  105. $value = URL::site($value, 'http');
  106. }
  107. // Add the info to the channel
  108. $feed->channel->addChild($name, $value);
  109. }
  110. }
  111. foreach ($items as $item)
  112. {
  113. // Add the item to the channel
  114. $row = $feed->channel->addChild('item');
  115. foreach ($item as $name => $value)
  116. {
  117. if ($name === 'pubDate' AND (is_int($value) OR ctype_digit($value)))
  118. {
  119. // Convert timestamps to RFC 822 formatted dates
  120. $value = date('r', $value);
  121. }
  122. elseif (($name === 'link' OR $name === 'guid') AND strpos($value, '://') === FALSE)
  123. {
  124. // Convert URIs to URLs
  125. $value = URL::site($value, 'http');
  126. }
  127. // Add the info to the row
  128. $row->addChild($name, $value);
  129. }
  130. }
  131. if (function_exists('dom_import_simplexml'))
  132. {
  133. // Convert the feed object to a DOM object
  134. $feed = dom_import_simplexml($feed)->ownerDocument;
  135. // DOM generates more readable XML
  136. $feed->formatOutput = TRUE;
  137. // Export the document as XML
  138. $feed = $feed->saveXML();
  139. }
  140. else
  141. {
  142. // Export the document as XML
  143. $feed = $feed->asXML();
  144. }
  145. return $feed;
  146. }
  147. } // End Feed