home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-includes / class-simplepie.php < prev    next >
Encoding:
PHP Script  |  2016-06-05  |  87.2 KB  |  3,094 lines

  1. <?php
  2. if ( ! class_exists( 'SimplePie', false ) ) :
  3.  
  4. // Load classes we will need.
  5. require ABSPATH . WPINC . '/SimplePie/Misc.php';
  6. require ABSPATH . WPINC . '/SimplePie/Cache.php';
  7. require ABSPATH . WPINC . '/SimplePie/File.php';
  8. require ABSPATH . WPINC . '/SimplePie/Sanitize.php';
  9. require ABSPATH . WPINC . '/SimplePie/Registry.php';
  10. require ABSPATH . WPINC . '/SimplePie/IRI.php';
  11. require ABSPATH . WPINC . '/SimplePie/Locator.php';
  12. require ABSPATH . WPINC . '/SimplePie/Content/Type/Sniffer.php';
  13. require ABSPATH . WPINC . '/SimplePie/XML/Declaration/Parser.php';
  14. require ABSPATH . WPINC . '/SimplePie/Parser.php';
  15. require ABSPATH . WPINC . '/SimplePie/Item.php';
  16. require ABSPATH . WPINC . '/SimplePie/Parse/Date.php';
  17. require ABSPATH . WPINC . '/SimplePie/Author.php';
  18.  
  19. /**
  20.  * WordPress autoloader for SimplePie.
  21.  *
  22.  * @since 3.5.0
  23.  */
  24. function wp_simplepie_autoload( $class ) {
  25.     if ( 0 !== strpos( $class, 'SimplePie_' ) )
  26.         return;
  27.  
  28.     $file = ABSPATH . WPINC . '/' . str_replace( '_', '/', $class ) . '.php';
  29.     include( $file );
  30. }
  31.  
  32. /**
  33.  * We autoload classes we may not need.
  34.  */
  35. spl_autoload_register( 'wp_simplepie_autoload' );
  36.  
  37. /**
  38.  * SimplePie
  39.  *
  40.  * A PHP-Based RSS and Atom Feed Framework.
  41.  * Takes the hard work out of managing a complete RSS/Atom solution.
  42.  *
  43.  * Copyright (c) 2004-2012, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
  44.  * All rights reserved.
  45.  *
  46.  * Redistribution and use in source and binary forms, with or without modification, are
  47.  * permitted provided that the following conditions are met:
  48.  *
  49.  *     * Redistributions of source code must retain the above copyright notice, this list of
  50.  *       conditions and the following disclaimer.
  51.  *
  52.  *     * Redistributions in binary form must reproduce the above copyright notice, this list
  53.  *       of conditions and the following disclaimer in the documentation and/or other materials
  54.  *       provided with the distribution.
  55.  *
  56.  *     * Neither the name of the SimplePie Team nor the names of its contributors may be used
  57.  *       to endorse or promote products derived from this software without specific prior
  58.  *       written permission.
  59.  *
  60.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  61.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  62.  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  63.  * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  64.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  65.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  66.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  67.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  68.  * POSSIBILITY OF SUCH DAMAGE.
  69.  *
  70.  * @package SimplePie
  71.  * @version 1.3.1
  72.  * @copyright 2004-2012 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  73.  * @author Ryan Parman
  74.  * @author Geoffrey Sneddon
  75.  * @author Ryan McCue
  76.  * @link http://simplepie.org/ SimplePie
  77.  * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  78.  */
  79.  
  80. /**
  81.  * SimplePie Name
  82.  */
  83. define('SIMPLEPIE_NAME', 'SimplePie');
  84.  
  85. /**
  86.  * SimplePie Version
  87.  */
  88. define('SIMPLEPIE_VERSION', '1.3.1');
  89.  
  90. /**
  91.  * SimplePie Build
  92.  * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
  93.  */
  94. define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build()));
  95.  
  96. /**
  97.  * SimplePie Website URL
  98.  */
  99. define('SIMPLEPIE_URL', 'http://simplepie.org');
  100.  
  101. /**
  102.  * SimplePie Useragent
  103.  * @see SimplePie::set_useragent()
  104.  */
  105. define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
  106.  
  107. /**
  108.  * SimplePie Linkback
  109.  */
  110. define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
  111.  
  112. /**
  113.  * No Autodiscovery
  114.  * @see SimplePie::set_autodiscovery_level()
  115.  */
  116. define('SIMPLEPIE_LOCATOR_NONE', 0);
  117.  
  118. /**
  119.  * Feed Link Element Autodiscovery
  120.  * @see SimplePie::set_autodiscovery_level()
  121.  */
  122. define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
  123.  
  124. /**
  125.  * Local Feed Extension Autodiscovery
  126.  * @see SimplePie::set_autodiscovery_level()
  127.  */
  128. define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
  129.  
  130. /**
  131.  * Local Feed Body Autodiscovery
  132.  * @see SimplePie::set_autodiscovery_level()
  133.  */
  134. define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
  135.  
  136. /**
  137.  * Remote Feed Extension Autodiscovery
  138.  * @see SimplePie::set_autodiscovery_level()
  139.  */
  140. define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
  141.  
  142. /**
  143.  * Remote Feed Body Autodiscovery
  144.  * @see SimplePie::set_autodiscovery_level()
  145.  */
  146. define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
  147.  
  148. /**
  149.  * All Feed Autodiscovery
  150.  * @see SimplePie::set_autodiscovery_level()
  151.  */
  152. define('SIMPLEPIE_LOCATOR_ALL', 31);
  153.  
  154. /**
  155.  * No known feed type
  156.  */
  157. define('SIMPLEPIE_TYPE_NONE', 0);
  158.  
  159. /**
  160.  * RSS 0.90
  161.  */
  162. define('SIMPLEPIE_TYPE_RSS_090', 1);
  163.  
  164. /**
  165.  * RSS 0.91 (Netscape)
  166.  */
  167. define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
  168.  
  169. /**
  170.  * RSS 0.91 (Userland)
  171.  */
  172. define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
  173.  
  174. /**
  175.  * RSS 0.91 (both Netscape and Userland)
  176.  */
  177. define('SIMPLEPIE_TYPE_RSS_091', 6);
  178.  
  179. /**
  180.  * RSS 0.92
  181.  */
  182. define('SIMPLEPIE_TYPE_RSS_092', 8);
  183.  
  184. /**
  185.  * RSS 0.93
  186.  */
  187. define('SIMPLEPIE_TYPE_RSS_093', 16);
  188.  
  189. /**
  190.  * RSS 0.94
  191.  */
  192. define('SIMPLEPIE_TYPE_RSS_094', 32);
  193.  
  194. /**
  195.  * RSS 1.0
  196.  */
  197. define('SIMPLEPIE_TYPE_RSS_10', 64);
  198.  
  199. /**
  200.  * RSS 2.0
  201.  */
  202. define('SIMPLEPIE_TYPE_RSS_20', 128);
  203.  
  204. /**
  205.  * RDF-based RSS
  206.  */
  207. define('SIMPLEPIE_TYPE_RSS_RDF', 65);
  208.  
  209. /**
  210.  * Non-RDF-based RSS (truly intended as syndication format)
  211.  */
  212. define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
  213.  
  214. /**
  215.  * All RSS
  216.  */
  217. define('SIMPLEPIE_TYPE_RSS_ALL', 255);
  218.  
  219. /**
  220.  * Atom 0.3
  221.  */
  222. define('SIMPLEPIE_TYPE_ATOM_03', 256);
  223.  
  224. /**
  225.  * Atom 1.0
  226.  */
  227. define('SIMPLEPIE_TYPE_ATOM_10', 512);
  228.  
  229. /**
  230.  * All Atom
  231.  */
  232. define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
  233.  
  234. /**
  235.  * All feed types
  236.  */
  237. define('SIMPLEPIE_TYPE_ALL', 1023);
  238.  
  239. /**
  240.  * No construct
  241.  */
  242. define('SIMPLEPIE_CONSTRUCT_NONE', 0);
  243.  
  244. /**
  245.  * Text construct
  246.  */
  247. define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
  248.  
  249. /**
  250.  * HTML construct
  251.  */
  252. define('SIMPLEPIE_CONSTRUCT_HTML', 2);
  253.  
  254. /**
  255.  * XHTML construct
  256.  */
  257. define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
  258.  
  259. /**
  260.  * base64-encoded construct
  261.  */
  262. define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
  263.  
  264. /**
  265.  * IRI construct
  266.  */
  267. define('SIMPLEPIE_CONSTRUCT_IRI', 16);
  268.  
  269. /**
  270.  * A construct that might be HTML
  271.  */
  272. define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
  273.  
  274. /**
  275.  * All constructs
  276.  */
  277. define('SIMPLEPIE_CONSTRUCT_ALL', 63);
  278.  
  279. /**
  280.  * Don't change case
  281.  */
  282. define('SIMPLEPIE_SAME_CASE', 1);
  283.  
  284. /**
  285.  * Change to lowercase
  286.  */
  287. define('SIMPLEPIE_LOWERCASE', 2);
  288.  
  289. /**
  290.  * Change to uppercase
  291.  */
  292. define('SIMPLEPIE_UPPERCASE', 4);
  293.  
  294. /**
  295.  * PCRE for HTML attributes
  296.  */
  297. define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
  298.  
  299. /**
  300.  * PCRE for XML attributes
  301.  */
  302. define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
  303.  
  304. /**
  305.  * XML Namespace
  306.  */
  307. define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
  308.  
  309. /**
  310.  * Atom 1.0 Namespace
  311.  */
  312. define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
  313.  
  314. /**
  315.  * Atom 0.3 Namespace
  316.  */
  317. define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
  318.  
  319. /**
  320.  * RDF Namespace
  321.  */
  322. define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
  323.  
  324. /**
  325.  * RSS 0.90 Namespace
  326.  */
  327. define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
  328.  
  329. /**
  330.  * RSS 1.0 Namespace
  331.  */
  332. define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
  333.  
  334. /**
  335.  * RSS 1.0 Content Module Namespace
  336.  */
  337. define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
  338.  
  339. /**
  340.  * RSS 2.0 Namespace
  341.  * (Stupid, I know, but I'm certain it will confuse people less with support.)
  342.  */
  343. define('SIMPLEPIE_NAMESPACE_RSS_20', '');
  344.  
  345. /**
  346.  * DC 1.0 Namespace
  347.  */
  348. define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
  349.  
  350. /**
  351.  * DC 1.1 Namespace
  352.  */
  353. define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
  354.  
  355. /**
  356.  * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
  357.  */
  358. define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
  359.  
  360. /**
  361.  * GeoRSS Namespace
  362.  */
  363. define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
  364.  
  365. /**
  366.  * Media RSS Namespace
  367.  */
  368. define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
  369.  
  370. /**
  371.  * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
  372.  */
  373. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
  374.  
  375. /**
  376.  * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
  377.  */
  378. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
  379.  
  380. /**
  381.  * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
  382.  */
  383. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
  384.  
  385. /**
  386.  * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
  387.  */
  388. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
  389.  
  390. /**
  391.  * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
  392.  */
  393. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
  394.  
  395. /**
  396.  * iTunes RSS Namespace
  397.  */
  398. define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
  399.  
  400. /**
  401.  * XHTML Namespace
  402.  */
  403. define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
  404.  
  405. /**
  406.  * IANA Link Relations Registry
  407.  */
  408. define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
  409.  
  410. /**
  411.  * No file source
  412.  */
  413. define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
  414.  
  415. /**
  416.  * Remote file source
  417.  */
  418. define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
  419.  
  420. /**
  421.  * Local file source
  422.  */
  423. define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
  424.  
  425. /**
  426.  * fsockopen() file source
  427.  */
  428. define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
  429.  
  430. /**
  431.  * cURL file source
  432.  */
  433. define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
  434.  
  435. /**
  436.  * file_get_contents() file source
  437.  */
  438. define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
  439.  
  440.  
  441.  
  442. /**
  443.  * SimplePie
  444.  *
  445.  * @package SimplePie
  446.  * @subpackage API
  447.  */
  448. class SimplePie
  449. {
  450.     /**
  451.      * @var array Raw data
  452.      * @access private
  453.      */
  454.     public $data = array();
  455.  
  456.     /**
  457.      * @var mixed Error string
  458.      * @access private
  459.      */
  460.     public $error;
  461.  
  462.     /**
  463.      * @var object Instance of SimplePie_Sanitize (or other class)
  464.      * @see SimplePie::set_sanitize_class()
  465.      * @access private
  466.      */
  467.     public $sanitize;
  468.  
  469.     /**
  470.      * @var string SimplePie Useragent
  471.      * @see SimplePie::set_useragent()
  472.      * @access private
  473.      */
  474.     public $useragent = SIMPLEPIE_USERAGENT;
  475.  
  476.     /**
  477.      * @var string Feed URL
  478.      * @see SimplePie::set_feed_url()
  479.      * @access private
  480.      */
  481.     public $feed_url;
  482.  
  483.     /**
  484.      * @var object Instance of SimplePie_File to use as a feed
  485.      * @see SimplePie::set_file()
  486.      * @access private
  487.      */
  488.     public $file;
  489.  
  490.     /**
  491.      * @var string Raw feed data
  492.      * @see SimplePie::set_raw_data()
  493.      * @access private
  494.      */
  495.     public $raw_data;
  496.  
  497.     /**
  498.      * @var int Timeout for fetching remote files
  499.      * @see SimplePie::set_timeout()
  500.      * @access private
  501.      */
  502.     public $timeout = 10;
  503.  
  504.     /**
  505.      * @var bool Forces fsockopen() to be used for remote files instead
  506.      * of cURL, even if a new enough version is installed
  507.      * @see SimplePie::force_fsockopen()
  508.      * @access private
  509.      */
  510.     public $force_fsockopen = false;
  511.  
  512.     /**
  513.      * @var bool Force the given data/URL to be treated as a feed no matter what
  514.      * it appears like
  515.      * @see SimplePie::force_feed()
  516.      * @access private
  517.      */
  518.     public $force_feed = false;
  519.  
  520.     /**
  521.      * @var bool Enable/Disable Caching
  522.      * @see SimplePie::enable_cache()
  523.      * @access private
  524.      */
  525.     public $cache = true;
  526.  
  527.     /**
  528.      * @var int Cache duration (in seconds)
  529.      * @see SimplePie::set_cache_duration()
  530.      * @access private
  531.      */
  532.     public $cache_duration = 3600;
  533.  
  534.     /**
  535.      * @var int Auto-discovery cache duration (in seconds)
  536.      * @see SimplePie::set_autodiscovery_cache_duration()
  537.      * @access private
  538.      */
  539.     public $autodiscovery_cache_duration = 604800; // 7 Days.
  540.  
  541.     /**
  542.      * @var string Cache location (relative to executing script)
  543.      * @see SimplePie::set_cache_location()
  544.      * @access private
  545.      */
  546.     public $cache_location = './cache';
  547.  
  548.     /**
  549.      * @var string Function that creates the cache filename
  550.      * @see SimplePie::set_cache_name_function()
  551.      * @access private
  552.      */
  553.     public $cache_name_function = 'md5';
  554.  
  555.     /**
  556.      * @var bool Reorder feed by date descending
  557.      * @see SimplePie::enable_order_by_date()
  558.      * @access private
  559.      */
  560.     public $order_by_date = true;
  561.  
  562.     /**
  563.      * @var mixed Force input encoding to be set to the follow value
  564.      * (false, or anything type-cast to false, disables this feature)
  565.      * @see SimplePie::set_input_encoding()
  566.      * @access private
  567.      */
  568.     public $input_encoding = false;
  569.  
  570.     /**
  571.      * @var int Feed Autodiscovery Level
  572.      * @see SimplePie::set_autodiscovery_level()
  573.      * @access private
  574.      */
  575.     public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
  576.  
  577.     /**
  578.      * Class registry object
  579.      *
  580.      * @var SimplePie_Registry
  581.      */
  582.     public $registry;
  583.  
  584.     /**
  585.      * @var int Maximum number of feeds to check with autodiscovery
  586.      * @see SimplePie::set_max_checked_feeds()
  587.      * @access private
  588.      */
  589.     public $max_checked_feeds = 10;
  590.  
  591.     /**
  592.      * @var array All the feeds found during the autodiscovery process
  593.      * @see SimplePie::get_all_discovered_feeds()
  594.      * @access private
  595.      */
  596.     public $all_discovered_feeds = array();
  597.  
  598.     /**
  599.      * @var string Web-accessible path to the handler_image.php file.
  600.      * @see SimplePie::set_image_handler()
  601.      * @access private
  602.      */
  603.     public $image_handler = '';
  604.  
  605.     /**
  606.      * @var array Stores the URLs when multiple feeds are being initialized.
  607.      * @see SimplePie::set_feed_url()
  608.      * @access private
  609.      */
  610.     public $multifeed_url = array();
  611.  
  612.     /**
  613.      * @var array Stores SimplePie objects when multiple feeds initialized.
  614.      * @access private
  615.      */
  616.     public $multifeed_objects = array();
  617.  
  618.     /**
  619.      * @var array Stores the get_object_vars() array for use with multifeeds.
  620.      * @see SimplePie::set_feed_url()
  621.      * @access private
  622.      */
  623.     public $config_settings = null;
  624.  
  625.     /**
  626.      * @var integer Stores the number of items to return per-feed with multifeeds.
  627.      * @see SimplePie::set_item_limit()
  628.      * @access private
  629.      */
  630.     public $item_limit = 0;
  631.  
  632.     /**
  633.      * @var array Stores the default attributes to be stripped by strip_attributes().
  634.      * @see SimplePie::strip_attributes()
  635.      * @access private
  636.      */
  637.     public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  638.  
  639.     /**
  640.      * @var array Stores the default tags to be stripped by strip_htmltags().
  641.      * @see SimplePie::strip_htmltags()
  642.      * @access private
  643.      */
  644.     public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  645.  
  646.     /**
  647.      * The SimplePie class contains feed level data and options
  648.      *
  649.      * To use SimplePie, create the SimplePie object with no parameters. You can
  650.      * then set configuration options using the provided methods. After setting
  651.      * them, you must initialise the feed using $feed->init(). At that point the
  652.      * object's methods and properties will be available to you.
  653.      *
  654.      * Previously, it was possible to pass in the feed URL along with cache
  655.      * options directly into the constructor. This has been removed as of 1.3 as
  656.      * it caused a lot of confusion.
  657.      *
  658.      * @since 1.0 Preview Release
  659.      */
  660.     public function __construct()
  661.     {
  662.         if (version_compare(PHP_VERSION, '5.2', '<'))
  663.         {
  664.             trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
  665.             die();
  666.         }
  667.  
  668.         // Other objects, instances created here so we can set options on them
  669.         $this->sanitize = new SimplePie_Sanitize();
  670.         $this->registry = new SimplePie_Registry();
  671.  
  672.         if (func_num_args() > 0)
  673.         {
  674.             $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  675.             trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.', $level);
  676.  
  677.             $args = func_get_args();
  678.             switch (count($args)) {
  679.                 case 3:
  680.                     $this->set_cache_duration($args[2]);
  681.                 case 2:
  682.                     $this->set_cache_location($args[1]);
  683.                 case 1:
  684.                     $this->set_feed_url($args[0]);
  685.                     $this->init();
  686.             }
  687.         }
  688.     }
  689.  
  690.     /**
  691.      * Used for converting object to a string
  692.      */
  693.     public function __toString()
  694.     {
  695.         return md5(serialize($this->data));
  696.     }
  697.  
  698.     /**
  699.      * Remove items that link back to this before destroying this object
  700.      */
  701.     public function __destruct()
  702.     {
  703.         if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  704.         {
  705.             if (!empty($this->data['items']))
  706.             {
  707.                 foreach ($this->data['items'] as $item)
  708.                 {
  709.                     $item->__destruct();
  710.                 }
  711.                 unset($item, $this->data['items']);
  712.             }
  713.             if (!empty($this->data['ordered_items']))
  714.             {
  715.                 foreach ($this->data['ordered_items'] as $item)
  716.                 {
  717.                     $item->__destruct();
  718.                 }
  719.                 unset($item, $this->data['ordered_items']);
  720.             }
  721.         }
  722.     }
  723.  
  724.     /**
  725.      * Force the given data/URL to be treated as a feed
  726.      *
  727.      * This tells SimplePie to ignore the content-type provided by the server.
  728.      * Be careful when using this option, as it will also disable autodiscovery.
  729.      *
  730.      * @since 1.1
  731.      * @param bool $enable Force the given data/URL to be treated as a feed
  732.      */
  733.     public function force_feed($enable = false)
  734.     {
  735.         $this->force_feed = (bool) $enable;
  736.     }
  737.  
  738.     /**
  739.      * Set the URL of the feed you want to parse
  740.      *
  741.      * This allows you to enter the URL of the feed you want to parse, or the
  742.      * website you want to try to use auto-discovery on. This takes priority
  743.      * over any set raw data.
  744.      *
  745.      * You can set multiple feeds to mash together by passing an array instead
  746.      * of a string for the $url. Remember that with each additional feed comes
  747.      * additional processing and resources.
  748.      *
  749.      * @since 1.0 Preview Release
  750.      * @see set_raw_data()
  751.      * @param string|array $url This is the URL (or array of URLs) that you want to parse.
  752.      */
  753.     public function set_feed_url($url)
  754.     {
  755.         $this->multifeed_url = array();
  756.         if (is_array($url))
  757.         {
  758.             foreach ($url as $value)
  759.             {
  760.                 $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
  761.             }
  762.         }
  763.         else
  764.         {
  765.             $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
  766.         }
  767.     }
  768.  
  769.     /**
  770.      * Set an instance of {@see SimplePie_File} to use as a feed
  771.      *
  772.      * @param SimplePie_File &$file
  773.      * @return bool True on success, false on failure
  774.      */
  775.     public function set_file(&$file)
  776.     {
  777.         if ($file instanceof SimplePie_File)
  778.         {
  779.             $this->feed_url = $file->url;
  780.             $this->file =& $file;
  781.             return true;
  782.         }
  783.         return false;
  784.     }
  785.  
  786.     /**
  787.      * Set the raw XML data to parse
  788.      *
  789.      * Allows you to use a string of RSS/Atom data instead of a remote feed.
  790.      *
  791.      * If you have a feed available as a string in PHP, you can tell SimplePie
  792.      * to parse that data string instead of a remote feed. Any set feed URL
  793.      * takes precedence.
  794.      *
  795.      * @since 1.0 Beta 3
  796.      * @param string $data RSS or Atom data as a string.
  797.      * @see set_feed_url()
  798.      */
  799.     public function set_raw_data($data)
  800.     {
  801.         $this->raw_data = $data;
  802.     }
  803.  
  804.     /**
  805.      * Set the the default timeout for fetching remote feeds
  806.      *
  807.      * This allows you to change the maximum time the feed's server to respond
  808.      * and send the feed back.
  809.      *
  810.      * @since 1.0 Beta 3
  811.      * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
  812.      */
  813.     public function set_timeout($timeout = 10)
  814.     {
  815.         $this->timeout = (int) $timeout;
  816.     }
  817.  
  818.     /**
  819.      * Force SimplePie to use fsockopen() instead of cURL
  820.      *
  821.      * @since 1.0 Beta 3
  822.      * @param bool $enable Force fsockopen() to be used
  823.      */
  824.     public function force_fsockopen($enable = false)
  825.     {
  826.         $this->force_fsockopen = (bool) $enable;
  827.     }
  828.  
  829.     /**
  830.      * Enable/disable caching in SimplePie.
  831.      *
  832.      * This option allows you to disable caching all-together in SimplePie.
  833.      * However, disabling the cache can lead to longer load times.
  834.      *
  835.      * @since 1.0 Preview Release
  836.      * @param bool $enable Enable caching
  837.      */
  838.     public function enable_cache($enable = true)
  839.     {
  840.         $this->cache = (bool) $enable;
  841.     }
  842.  
  843.     /**
  844.      * Set the length of time (in seconds) that the contents of a feed will be
  845.      * cached
  846.      *
  847.      * @param int $seconds The feed content cache duration
  848.      */
  849.     public function set_cache_duration($seconds = 3600)
  850.     {
  851.         $this->cache_duration = (int) $seconds;
  852.     }
  853.  
  854.     /**
  855.      * Set the length of time (in seconds) that the autodiscovered feed URL will
  856.      * be cached
  857.      *
  858.      * @param int $seconds The autodiscovered feed URL cache duration.
  859.      */
  860.     public function set_autodiscovery_cache_duration($seconds = 604800)
  861.     {
  862.         $this->autodiscovery_cache_duration = (int) $seconds;
  863.     }
  864.  
  865.     /**
  866.      * Set the file system location where the cached files should be stored
  867.      *
  868.      * @param string $location The file system location.
  869.      */
  870.     public function set_cache_location($location = './cache')
  871.     {
  872.         $this->cache_location = (string) $location;
  873.     }
  874.  
  875.     /**
  876.      * Set whether feed items should be sorted into reverse chronological order
  877.      *
  878.      * @param bool $enable Sort as reverse chronological order.
  879.      */
  880.     public function enable_order_by_date($enable = true)
  881.     {
  882.         $this->order_by_date = (bool) $enable;
  883.     }
  884.  
  885.     /**
  886.      * Set the character encoding used to parse the feed
  887.      *
  888.      * This overrides the encoding reported by the feed, however it will fall
  889.      * back to the normal encoding detection if the override fails
  890.      *
  891.      * @param string $encoding Character encoding
  892.      */
  893.     public function set_input_encoding($encoding = false)
  894.     {
  895.         if ($encoding)
  896.         {
  897.             $this->input_encoding = (string) $encoding;
  898.         }
  899.         else
  900.         {
  901.             $this->input_encoding = false;
  902.         }
  903.     }
  904.  
  905.     /**
  906.      * Set how much feed autodiscovery to do
  907.      *
  908.      * @see SIMPLEPIE_LOCATOR_NONE
  909.      * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
  910.      * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
  911.      * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
  912.      * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
  913.      * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
  914.      * @see SIMPLEPIE_LOCATOR_ALL
  915.      * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
  916.      */
  917.     public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
  918.     {
  919.         $this->autodiscovery = (int) $level;
  920.     }
  921.  
  922.     /**
  923.      * Get the class registry
  924.      *
  925.      * Use this to override SimplePie's default classes
  926.      * @see SimplePie_Registry
  927.      * @return SimplePie_Registry
  928.      */
  929.     public function &get_registry()
  930.     {
  931.         return $this->registry;
  932.     }
  933.  
  934.     /**#@+
  935.      * Useful when you are overloading or extending SimplePie's default classes.
  936.      *
  937.      * @deprecated Use {@see get_registry()} instead
  938.      * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  939.      * @param string $class Name of custom class
  940.      * @return boolean True on success, false otherwise
  941.      */
  942.     /**
  943.      * Set which class SimplePie uses for caching
  944.      */
  945.     public function set_cache_class($class = 'SimplePie_Cache')
  946.     {
  947.         return $this->registry->register('Cache', $class, true);
  948.     }
  949.  
  950.     /**
  951.      * Set which class SimplePie uses for auto-discovery
  952.      */
  953.     public function set_locator_class($class = 'SimplePie_Locator')
  954.     {
  955.         return $this->registry->register('Locator', $class, true);
  956.     }
  957.  
  958.     /**
  959.      * Set which class SimplePie uses for XML parsing
  960.      */
  961.     public function set_parser_class($class = 'SimplePie_Parser')
  962.     {
  963.         return $this->registry->register('Parser', $class, true);
  964.     }
  965.  
  966.     /**
  967.      * Set which class SimplePie uses for remote file fetching
  968.      */
  969.     public function set_file_class($class = 'SimplePie_File')
  970.     {
  971.         return $this->registry->register('File', $class, true);
  972.     }
  973.  
  974.     /**
  975.      * Set which class SimplePie uses for data sanitization
  976.      */
  977.     public function set_sanitize_class($class = 'SimplePie_Sanitize')
  978.     {
  979.         return $this->registry->register('Sanitize', $class, true);
  980.     }
  981.  
  982.     /**
  983.      * Set which class SimplePie uses for handling feed items
  984.      */
  985.     public function set_item_class($class = 'SimplePie_Item')
  986.     {
  987.         return $this->registry->register('Item', $class, true);
  988.     }
  989.  
  990.     /**
  991.      * Set which class SimplePie uses for handling author data
  992.      */
  993.     public function set_author_class($class = 'SimplePie_Author')
  994.     {
  995.         return $this->registry->register('Author', $class, true);
  996.     }
  997.  
  998.     /**
  999.      * Set which class SimplePie uses for handling category data
  1000.      */
  1001.     public function set_category_class($class = 'SimplePie_Category')
  1002.     {
  1003.         return $this->registry->register('Category', $class, true);
  1004.     }
  1005.  
  1006.     /**
  1007.      * Set which class SimplePie uses for feed enclosures
  1008.      */
  1009.     public function set_enclosure_class($class = 'SimplePie_Enclosure')
  1010.     {
  1011.         return $this->registry->register('Enclosure', $class, true);
  1012.     }
  1013.  
  1014.     /**
  1015.      * Set which class SimplePie uses for `<media:text>` captions
  1016.      */
  1017.     public function set_caption_class($class = 'SimplePie_Caption')
  1018.     {
  1019.         return $this->registry->register('Caption', $class, true);
  1020.     }
  1021.  
  1022.     /**
  1023.      * Set which class SimplePie uses for `<media:copyright>`
  1024.      */
  1025.     public function set_copyright_class($class = 'SimplePie_Copyright')
  1026.     {
  1027.         return $this->registry->register('Copyright', $class, true);
  1028.     }
  1029.  
  1030.     /**
  1031.      * Set which class SimplePie uses for `<media:credit>`
  1032.      */
  1033.     public function set_credit_class($class = 'SimplePie_Credit')
  1034.     {
  1035.         return $this->registry->register('Credit', $class, true);
  1036.     }
  1037.  
  1038.     /**
  1039.      * Set which class SimplePie uses for `<media:rating>`
  1040.      */
  1041.     public function set_rating_class($class = 'SimplePie_Rating')
  1042.     {
  1043.         return $this->registry->register('Rating', $class, true);
  1044.     }
  1045.  
  1046.     /**
  1047.      * Set which class SimplePie uses for `<media:restriction>`
  1048.      */
  1049.     public function set_restriction_class($class = 'SimplePie_Restriction')
  1050.     {
  1051.         return $this->registry->register('Restriction', $class, true);
  1052.     }
  1053.  
  1054.     /**
  1055.      * Set which class SimplePie uses for content-type sniffing
  1056.      */
  1057.     public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
  1058.     {
  1059.         return $this->registry->register('Content_Type_Sniffer', $class, true);
  1060.     }
  1061.  
  1062.     /**
  1063.      * Set which class SimplePie uses item sources
  1064.      */
  1065.     public function set_source_class($class = 'SimplePie_Source')
  1066.     {
  1067.         return $this->registry->register('Source', $class, true);
  1068.     }
  1069.     /**#@-*/
  1070.  
  1071.     /**
  1072.      * Set the user agent string
  1073.      *
  1074.      * @param string $ua New user agent string.
  1075.      */
  1076.     public function set_useragent($ua = SIMPLEPIE_USERAGENT)
  1077.     {
  1078.         $this->useragent = (string) $ua;
  1079.     }
  1080.  
  1081.     /**
  1082.      * Set callback function to create cache filename with
  1083.      *
  1084.      * @param mixed $function Callback function
  1085.      */
  1086.     public function set_cache_name_function($function = 'md5')
  1087.     {
  1088.         if (is_callable($function))
  1089.         {
  1090.             $this->cache_name_function = $function;
  1091.         }
  1092.     }
  1093.  
  1094.     /**
  1095.      * Set options to make SP as fast as possible
  1096.      *
  1097.      * Forgoes a substantial amount of data sanitization in favor of speed. This
  1098.      * turns SimplePie into a dumb parser of feeds.
  1099.      *
  1100.      * @param bool $set Whether to set them or not
  1101.      */
  1102.     public function set_stupidly_fast($set = false)
  1103.     {
  1104.         if ($set)
  1105.         {
  1106.             $this->enable_order_by_date(false);
  1107.             $this->remove_div(false);
  1108.             $this->strip_comments(false);
  1109.             $this->strip_htmltags(false);
  1110.             $this->strip_attributes(false);
  1111.             $this->set_image_handler(false);
  1112.         }
  1113.     }
  1114.  
  1115.     /**
  1116.      * Set maximum number of feeds to check with autodiscovery
  1117.      *
  1118.      * @param int $max Maximum number of feeds to check
  1119.      */
  1120.     public function set_max_checked_feeds($max = 10)
  1121.     {
  1122.         $this->max_checked_feeds = (int) $max;
  1123.     }
  1124.  
  1125.     public function remove_div($enable = true)
  1126.     {
  1127.         $this->sanitize->remove_div($enable);
  1128.     }
  1129.  
  1130.     public function strip_htmltags($tags = '', $encode = null)
  1131.     {
  1132.         if ($tags === '')
  1133.         {
  1134.             $tags = $this->strip_htmltags;
  1135.         }
  1136.         $this->sanitize->strip_htmltags($tags);
  1137.         if ($encode !== null)
  1138.         {
  1139.             $this->sanitize->encode_instead_of_strip($tags);
  1140.         }
  1141.     }
  1142.  
  1143.     public function encode_instead_of_strip($enable = true)
  1144.     {
  1145.         $this->sanitize->encode_instead_of_strip($enable);
  1146.     }
  1147.  
  1148.     public function strip_attributes($attribs = '')
  1149.     {
  1150.         if ($attribs === '')
  1151.         {
  1152.             $attribs = $this->strip_attributes;
  1153.         }
  1154.         $this->sanitize->strip_attributes($attribs);
  1155.     }
  1156.  
  1157.     /**
  1158.      * Set the output encoding
  1159.      *
  1160.      * Allows you to override SimplePie's output to match that of your webpage.
  1161.      * This is useful for times when your webpages are not being served as
  1162.      * UTF-8.  This setting will be obeyed by {@see handle_content_type()}, and
  1163.      * is similar to {@see set_input_encoding()}.
  1164.      *
  1165.      * It should be noted, however, that not all character encodings can support
  1166.      * all characters.  If your page is being served as ISO-8859-1 and you try
  1167.      * to display a Japanese feed, you'll likely see garbled characters.
  1168.      * Because of this, it is highly recommended to ensure that your webpages
  1169.      * are served as UTF-8.
  1170.      *
  1171.      * The number of supported character encodings depends on whether your web
  1172.      * host supports {@link http://php.net/mbstring mbstring},
  1173.      * {@link http://php.net/iconv iconv}, or both. See
  1174.      * {@link http://simplepie.org/wiki/faq/Supported_Character_Encodings} for
  1175.      * more information.
  1176.      *
  1177.      * @param string $encoding
  1178.      */
  1179.     public function set_output_encoding($encoding = 'UTF-8')
  1180.     {
  1181.         $this->sanitize->set_output_encoding($encoding);
  1182.     }
  1183.  
  1184.     public function strip_comments($strip = false)
  1185.     {
  1186.         $this->sanitize->strip_comments($strip);
  1187.     }
  1188.  
  1189.     /**
  1190.      * Set element/attribute key/value pairs of HTML attributes
  1191.      * containing URLs that need to be resolved relative to the feed
  1192.      *
  1193.      * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
  1194.      * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
  1195.      * |q|@cite
  1196.      *
  1197.      * @since 1.0
  1198.      * @param array|null $element_attribute Element/attribute key/value pairs, null for default
  1199.      */
  1200.     public function set_url_replacements($element_attribute = null)
  1201.     {
  1202.         $this->sanitize->set_url_replacements($element_attribute);
  1203.     }
  1204.  
  1205.     /**
  1206.      * Set the handler to enable the display of cached images.
  1207.      *
  1208.      * @param str $page Web-accessible path to the handler_image.php file.
  1209.      * @param str $qs The query string that the value should be passed to.
  1210.      */
  1211.     public function set_image_handler($page = false, $qs = 'i')
  1212.     {
  1213.         if ($page !== false)
  1214.         {
  1215.             $this->sanitize->set_image_handler($page . '?' . $qs . '=');
  1216.         }
  1217.         else
  1218.         {
  1219.             $this->image_handler = '';
  1220.         }
  1221.     }
  1222.  
  1223.     /**
  1224.      * Set the limit for items returned per-feed with multifeeds
  1225.      *
  1226.      * @param integer $limit The maximum number of items to return.
  1227.      */
  1228.     public function set_item_limit($limit = 0)
  1229.     {
  1230.         $this->item_limit = (int) $limit;
  1231.     }
  1232.  
  1233.     /**
  1234.      * Initialize the feed object
  1235.      *
  1236.      * This is what makes everything happen.  Period.  This is where all of the
  1237.      * configuration options get processed, feeds are fetched, cached, and
  1238.      * parsed, and all of that other good stuff.
  1239.      *
  1240.      * @return boolean True if successful, false otherwise
  1241.      */
  1242.     public function init()
  1243.     {
  1244.         // Check absolute bare minimum requirements.
  1245.         if (!extension_loaded('xml') || !extension_loaded('pcre'))
  1246.         {
  1247.             return false;
  1248.         }
  1249.         // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
  1250.         elseif (!extension_loaded('xmlreader'))
  1251.         {
  1252.             static $xml_is_sane = null;
  1253.             if ($xml_is_sane === null)
  1254.             {
  1255.                 $parser_check = xml_parser_create();
  1256.                 xml_parse_into_struct($parser_check, '<foo>&</foo>', $values);
  1257.                 xml_parser_free($parser_check);
  1258.                 $xml_is_sane = isset($values[0]['value']);
  1259.             }
  1260.             if (!$xml_is_sane)
  1261.             {
  1262.                 return false;
  1263.             }
  1264.         }
  1265.  
  1266.         if (method_exists($this->sanitize, 'set_registry'))
  1267.         {
  1268.             $this->sanitize->set_registry($this->registry);
  1269.         }
  1270.  
  1271.         // Pass whatever was set with config options over to the sanitizer.
  1272.         // Pass the classes in for legacy support; new classes should use the registry instead
  1273.         $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
  1274.         $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen);
  1275.  
  1276.         if (!empty($this->multifeed_url))
  1277.         {
  1278.             $i = 0;
  1279.             $success = 0;
  1280.             $this->multifeed_objects = array();
  1281.             $this->error = array();
  1282.             foreach ($this->multifeed_url as $url)
  1283.             {
  1284.                 $this->multifeed_objects[$i] = clone $this;
  1285.                 $this->multifeed_objects[$i]->set_feed_url($url);
  1286.                 $single_success = $this->multifeed_objects[$i]->init();
  1287.                 $success |= $single_success;
  1288.                 if (!$single_success)
  1289.                 {
  1290.                     $this->error[$i] = $this->multifeed_objects[$i]->error();
  1291.                 }
  1292.                 $i++;
  1293.             }
  1294.             return (bool) $success;
  1295.         }
  1296.         elseif ($this->feed_url === null && $this->raw_data === null)
  1297.         {
  1298.             return false;
  1299.         }
  1300.  
  1301.         $this->error = null;
  1302.         $this->data = array();
  1303.         $this->multifeed_objects = array();
  1304.         $cache = false;
  1305.  
  1306.         if ($this->feed_url !== null)
  1307.         {
  1308.             $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
  1309.  
  1310.             // Decide whether to enable caching
  1311.             if ($this->cache && $parsed_feed_url['scheme'] !== '')
  1312.             {
  1313.                 $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
  1314.             }
  1315.  
  1316.             // Fetch the data via SimplePie_File into $this->raw_data
  1317.             if (($fetched = $this->fetch_data($cache)) === true)
  1318.             {
  1319.                 return true;
  1320.             }
  1321.             elseif ($fetched === false) {
  1322.                 return false;
  1323.             }
  1324.  
  1325.             list($headers, $sniffed) = $fetched;
  1326.         }
  1327.  
  1328.         // Set up array of possible encodings
  1329.         $encodings = array();
  1330.  
  1331.         // First check to see if input has been overridden.
  1332.         if ($this->input_encoding !== false)
  1333.         {
  1334.             $encodings[] = $this->input_encoding;
  1335.         }
  1336.  
  1337.         $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
  1338.         $text_types = array('text/xml', 'text/xml-external-parsed-entity');
  1339.  
  1340.         // RFC 3023 (only applies to sniffed content)
  1341.         if (isset($sniffed))
  1342.         {
  1343.             if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
  1344.             {
  1345.                 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1346.                 {
  1347.                     $encodings[] = strtoupper($charset[1]);
  1348.                 }
  1349.                 $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
  1350.                 $encodings[] = 'UTF-8';
  1351.             }
  1352.             elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
  1353.             {
  1354.                 if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1355.                 {
  1356.                     $encodings[] = $charset[1];
  1357.                 }
  1358.                 $encodings[] = 'US-ASCII';
  1359.             }
  1360.             // Text MIME-type default
  1361.             elseif (substr($sniffed, 0, 5) === 'text/')
  1362.             {
  1363.                 $encodings[] = 'US-ASCII';
  1364.             }
  1365.         }
  1366.  
  1367.         // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
  1368.         $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
  1369.         $encodings[] = 'UTF-8';
  1370.         $encodings[] = 'ISO-8859-1';
  1371.  
  1372.         // There's no point in trying an encoding twice
  1373.         $encodings = array_unique($encodings);
  1374.  
  1375.         // Loop through each possible encoding, till we return something, or run out of possibilities
  1376.         foreach ($encodings as $encoding)
  1377.         {
  1378.             // Change the encoding to UTF-8 (as we always use UTF-8 internally)
  1379.             if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
  1380.             {
  1381.                 // Create new parser
  1382.                 $parser = $this->registry->create('Parser');
  1383.  
  1384.                 // If it's parsed fine
  1385.                 if ($parser->parse($utf8_data, 'UTF-8'))
  1386.                 {
  1387.                     $this->data = $parser->get_data();
  1388.                     if (!($this->get_type() & ~SIMPLEPIE_TYPE_NONE))
  1389.                     {
  1390.                         $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
  1391.                         $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
  1392.                         return false;
  1393.                     }
  1394.  
  1395.                     if (isset($headers))
  1396.                     {
  1397.                         $this->data['headers'] = $headers;
  1398.                     }
  1399.                     $this->data['build'] = SIMPLEPIE_BUILD;
  1400.  
  1401.                     // Cache the file if caching is enabled
  1402.                     if ($cache && !$cache->save($this))
  1403.                     {
  1404.                         trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  1405.                     }
  1406.                     return true;
  1407.                 }
  1408.             }
  1409.         }
  1410.  
  1411.         if (isset($parser))
  1412.         {
  1413.             // We have an error, just set SimplePie_Misc::error to it and quit
  1414.             $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
  1415.         }
  1416.         else
  1417.         {
  1418.             $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
  1419.         }
  1420.  
  1421.         $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
  1422.  
  1423.         return false;
  1424.     }
  1425.  
  1426.     /**
  1427.      * Fetch the data via SimplePie_File
  1428.      *
  1429.      * If the data is already cached, attempt to fetch it from there instead
  1430.      * @param SimplePie_Cache|false $cache Cache handler, or false to not load from the cache
  1431.      * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
  1432.      */
  1433.     protected function fetch_data(&$cache)
  1434.     {
  1435.         // If it's enabled, use the cache
  1436.         if ($cache)
  1437.         {
  1438.             // Load the Cache
  1439.             $this->data = $cache->load();
  1440.             if (!empty($this->data))
  1441.             {
  1442.                 // If the cache is for an outdated build of SimplePie
  1443.                 if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
  1444.                 {
  1445.                     $cache->unlink();
  1446.                     $this->data = array();
  1447.                 }
  1448.                 // If we've hit a collision just rerun it with caching disabled
  1449.                 elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
  1450.                 {
  1451.                     $cache = false;
  1452.                     $this->data = array();
  1453.                 }
  1454.                 // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
  1455.                 elseif (isset($this->data['feed_url']))
  1456.                 {
  1457.                     // If the autodiscovery cache is still valid use it.
  1458.                     if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
  1459.                     {
  1460.                         // Do not need to do feed autodiscovery yet.
  1461.                         if ($this->data['feed_url'] !== $this->data['url'])
  1462.                         {
  1463.                             $this->set_feed_url($this->data['feed_url']);
  1464.                             return $this->init();
  1465.                         }
  1466.  
  1467.                         $cache->unlink();
  1468.                         $this->data = array();
  1469.                     }
  1470.                 }
  1471.                 // Check if the cache has been updated
  1472.                 elseif ($cache->mtime() + $this->cache_duration < time())
  1473.                 {
  1474.                     // If we have last-modified and/or etag set
  1475.                     if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
  1476.                     {
  1477.                         $headers = array(
  1478.                             'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  1479.                         );
  1480.                         if (isset($this->data['headers']['last-modified']))
  1481.                         {
  1482.                             $headers['if-modified-since'] = $this->data['headers']['last-modified'];
  1483.                         }
  1484.                         if (isset($this->data['headers']['etag']))
  1485.                         {
  1486.                             $headers['if-none-match'] = $this->data['headers']['etag'];
  1487.                         }
  1488.  
  1489.                         $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen));
  1490.  
  1491.                         if ($file->success)
  1492.                         {
  1493.                             if ($file->status_code === 304)
  1494.                             {
  1495.                                 $cache->touch();
  1496.                                 return true;
  1497.                             }
  1498.                         }
  1499.                         else
  1500.                         {
  1501.                             unset($file);
  1502.                         }
  1503.                     }
  1504.                 }
  1505.                 // If the cache is still valid, just return true
  1506.                 else
  1507.                 {
  1508.                     $this->raw_data = false;
  1509.                     return true;
  1510.                 }
  1511.             }
  1512.             // If the cache is empty, delete it
  1513.             else
  1514.             {
  1515.                 $cache->unlink();
  1516.                 $this->data = array();
  1517.             }
  1518.         }
  1519.         // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
  1520.         if (!isset($file))
  1521.         {
  1522.             if ($this->file instanceof SimplePie_File && $this->file->url === $this->feed_url)
  1523.             {
  1524.                 $file =& $this->file;
  1525.             }
  1526.             else
  1527.             {
  1528.                 $headers = array(
  1529.                     'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  1530.                 );
  1531.                 $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen));
  1532.             }
  1533.         }
  1534.         // If the file connection has an error, set SimplePie::error to that and quit
  1535.         if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  1536.         {
  1537.             $this->error = $file->error;
  1538.             return !empty($this->data);
  1539.         }
  1540.  
  1541.         if (!$this->force_feed)
  1542.         {
  1543.             // Check if the supplied URL is a feed, if it isn't, look for it.
  1544.             $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
  1545.  
  1546.             if (!$locate->is_feed($file))
  1547.             {
  1548.                 // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
  1549.                 unset($file);
  1550.                 try
  1551.                 {
  1552.                     if (!($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds)))
  1553.                     {
  1554.                         $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
  1555.                         $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
  1556.                         return false;
  1557.                     }
  1558.                 }
  1559.                 catch (SimplePie_Exception $e)
  1560.                 {
  1561.                     // This is usually because DOMDocument doesn't exist
  1562.                     $this->error = $e->getMessage();
  1563.                     $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
  1564.                     return false;
  1565.                 }
  1566.                 if ($cache)
  1567.                 {
  1568.                     $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
  1569.                     if (!$cache->save($this))
  1570.                     {
  1571.                         trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  1572.                     }
  1573.                     $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
  1574.                 }
  1575.                 $this->feed_url = $file->url;
  1576.             }
  1577.             $locate = null;
  1578.         }
  1579.  
  1580.         $this->raw_data = $file->body;
  1581.  
  1582.         $headers = $file->headers;
  1583.         $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
  1584.         $sniffed = $sniffer->get_type();
  1585.  
  1586.         return array($headers, $sniffed);
  1587.     }
  1588.  
  1589.     /**
  1590.      * Get the error message for the occurred error.
  1591.      *
  1592.      * @return string|array Error message, or array of messages for multifeeds
  1593.      */
  1594.     public function error()
  1595.     {
  1596.         return $this->error;
  1597.     }
  1598.  
  1599.     /**
  1600.      * Get the raw XML
  1601.      *
  1602.      * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
  1603.      * the data instead of printing it.
  1604.      *
  1605.      * @return string|boolean Raw XML data, false if the cache is used
  1606.      */
  1607.     public function get_raw_data()
  1608.     {
  1609.         return $this->raw_data;
  1610.     }
  1611.  
  1612.     /**
  1613.      * Get the character encoding used for output
  1614.      *
  1615.      * @since Preview Release
  1616.      * @return string
  1617.      */
  1618.     public function get_encoding()
  1619.     {
  1620.         return $this->sanitize->output_encoding;
  1621.     }
  1622.  
  1623.     /**
  1624.      * Send the content-type header with correct encoding
  1625.      *
  1626.      * This method ensures that the SimplePie-enabled page is being served with
  1627.      * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
  1628.      * and character encoding HTTP headers (character encoding determined by the
  1629.      * {@see set_output_encoding} config option).
  1630.      *
  1631.      * This won't work properly if any content or whitespace has already been
  1632.      * sent to the browser, because it relies on PHP's
  1633.      * {@link http://php.net/header header()} function, and these are the
  1634.      * circumstances under which the function works.
  1635.      *
  1636.      * Because it's setting these settings for the entire page (as is the nature
  1637.      * of HTTP headers), this should only be used once per page (again, at the
  1638.      * top).
  1639.      *
  1640.      * @param string $mime MIME type to serve the page as
  1641.      */
  1642.     public function handle_content_type($mime = 'text/html')
  1643.     {
  1644.         if (!headers_sent())
  1645.         {
  1646.             $header = "Content-type: $mime;";
  1647.             if ($this->get_encoding())
  1648.             {
  1649.                 $header .= ' charset=' . $this->get_encoding();
  1650.             }
  1651.             else
  1652.             {
  1653.                 $header .= ' charset=UTF-8';
  1654.             }
  1655.             header($header);
  1656.         }
  1657.     }
  1658.  
  1659.     /**
  1660.      * Get the type of the feed
  1661.      *
  1662.      * This returns a SIMPLEPIE_TYPE_* constant, which can be tested against
  1663.      * using {@link http://php.net/language.operators.bitwise bitwise operators}
  1664.      *
  1665.      * @since 0.8 (usage changed to using constants in 1.0)
  1666.      * @see SIMPLEPIE_TYPE_NONE Unknown.
  1667.      * @see SIMPLEPIE_TYPE_RSS_090 RSS 0.90.
  1668.      * @see SIMPLEPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
  1669.      * @see SIMPLEPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
  1670.      * @see SIMPLEPIE_TYPE_RSS_091 RSS 0.91.
  1671.      * @see SIMPLEPIE_TYPE_RSS_092 RSS 0.92.
  1672.      * @see SIMPLEPIE_TYPE_RSS_093 RSS 0.93.
  1673.      * @see SIMPLEPIE_TYPE_RSS_094 RSS 0.94.
  1674.      * @see SIMPLEPIE_TYPE_RSS_10 RSS 1.0.
  1675.      * @see SIMPLEPIE_TYPE_RSS_20 RSS 2.0.x.
  1676.      * @see SIMPLEPIE_TYPE_RSS_RDF RDF-based RSS.
  1677.      * @see SIMPLEPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
  1678.      * @see SIMPLEPIE_TYPE_RSS_ALL Any version of RSS.
  1679.      * @see SIMPLEPIE_TYPE_ATOM_03 Atom 0.3.
  1680.      * @see SIMPLEPIE_TYPE_ATOM_10 Atom 1.0.
  1681.      * @see SIMPLEPIE_TYPE_ATOM_ALL Any version of Atom.
  1682.      * @see SIMPLEPIE_TYPE_ALL Any known/supported feed type.
  1683.      * @return int SIMPLEPIE_TYPE_* constant
  1684.      */
  1685.     public function get_type()
  1686.     {
  1687.         if (!isset($this->data['type']))
  1688.         {
  1689.             $this->data['type'] = SIMPLEPIE_TYPE_ALL;
  1690.             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
  1691.             {
  1692.                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
  1693.             }
  1694.             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
  1695.             {
  1696.                 $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
  1697.             }
  1698.             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
  1699.             {
  1700.                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
  1701.                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
  1702.                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
  1703.                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
  1704.                 {
  1705.                     $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
  1706.                 }
  1707.                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
  1708.                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
  1709.                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
  1710.                 || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
  1711.                 {
  1712.                     $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
  1713.                 }
  1714.             }
  1715.             elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
  1716.             {
  1717.                 $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
  1718.                 if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1719.                 {
  1720.                     switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1721.                     {
  1722.                         case '0.91':
  1723.                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
  1724.                             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1725.                             {
  1726.                                 switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1727.                                 {
  1728.                                     case '0':
  1729.                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
  1730.                                         break;
  1731.  
  1732.                                     case '24':
  1733.                                         $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
  1734.                                         break;
  1735.                                 }
  1736.                             }
  1737.                             break;
  1738.  
  1739.                         case '0.92':
  1740.                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
  1741.                             break;
  1742.  
  1743.                         case '0.93':
  1744.                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
  1745.                             break;
  1746.  
  1747.                         case '0.94':
  1748.                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
  1749.                             break;
  1750.  
  1751.                         case '2.0':
  1752.                             $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
  1753.                             break;
  1754.                     }
  1755.                 }
  1756.             }
  1757.             else
  1758.             {
  1759.                 $this->data['type'] = SIMPLEPIE_TYPE_NONE;
  1760.             }
  1761.         }
  1762.         return $this->data['type'];
  1763.     }
  1764.  
  1765.     /**
  1766.      * Get the URL for the feed
  1767.      *
  1768.      * May or may not be different from the URL passed to {@see set_feed_url()},
  1769.      * depending on whether auto-discovery was used.
  1770.      *
  1771.      * @since Preview Release (previously called `get_feed_url()` since SimplePie 0.8.)
  1772.      * @todo If we have a perm redirect we should return the new URL
  1773.      * @todo When we make the above change, let's support <itunes:new-feed-url> as well
  1774.      * @todo Also, |atom:link|@rel=self
  1775.      * @return string|null
  1776.      */
  1777.     public function subscribe_url()
  1778.     {
  1779.         if ($this->feed_url !== null)
  1780.         {
  1781.             return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
  1782.         }
  1783.         else
  1784.         {
  1785.             return null;
  1786.         }
  1787.     }
  1788.  
  1789.     /**
  1790.      * Get data for an feed-level element
  1791.      *
  1792.      * This method allows you to get access to ANY element/attribute that is a
  1793.      * sub-element of the opening feed tag.
  1794.      *
  1795.      * The return value is an indexed array of elements matching the given
  1796.      * namespace and tag name. Each element has `attribs`, `data` and `child`
  1797.      * subkeys. For `attribs` and `child`, these contain namespace subkeys.
  1798.      * `attribs` then has one level of associative name => value data (where
  1799.      * `value` is a string) after the namespace. `child` has tag-indexed keys
  1800.      * after the namespace, each member of which is an indexed array matching
  1801.      * this same format.
  1802.      *
  1803.      * For example:
  1804.      * <pre>
  1805.      * // This is probably a bad example because we already support
  1806.      * // <media:content> natively, but it shows you how to parse through
  1807.      * // the nodes.
  1808.      * $group = $item->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group');
  1809.      * $content = $group[0]['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'];
  1810.      * $file = $content[0]['attribs']['']['url'];
  1811.      * echo $file;
  1812.      * </pre>
  1813.      *
  1814.      * @since 1.0
  1815.      * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
  1816.      * @param string $namespace The URL of the XML namespace of the elements you're trying to access
  1817.      * @param string $tag Tag name
  1818.      * @return array
  1819.      */
  1820.     public function get_feed_tags($namespace, $tag)
  1821.     {
  1822.         $type = $this->get_type();
  1823.         if ($type & SIMPLEPIE_TYPE_ATOM_10)
  1824.         {
  1825.             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
  1826.             {
  1827.                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
  1828.             }
  1829.         }
  1830.         if ($type & SIMPLEPIE_TYPE_ATOM_03)
  1831.         {
  1832.             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
  1833.             {
  1834.                 return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
  1835.             }
  1836.         }
  1837.         if ($type & SIMPLEPIE_TYPE_RSS_RDF)
  1838.         {
  1839.             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
  1840.             {
  1841.                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
  1842.             }
  1843.         }
  1844.         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1845.         {
  1846.             if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
  1847.             {
  1848.                 return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
  1849.             }
  1850.         }
  1851.         return null;
  1852.     }
  1853.  
  1854.     /**
  1855.      * Get data for an channel-level element
  1856.      *
  1857.      * This method allows you to get access to ANY element/attribute in the
  1858.      * channel/header section of the feed.
  1859.      *
  1860.      * See {@see SimplePie::get_feed_tags()} for a description of the return value
  1861.      *
  1862.      * @since 1.0
  1863.      * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
  1864.      * @param string $namespace The URL of the XML namespace of the elements you're trying to access
  1865.      * @param string $tag Tag name
  1866.      * @return array
  1867.      */
  1868.     public function get_channel_tags($namespace, $tag)
  1869.     {
  1870.         $type = $this->get_type();
  1871.         if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
  1872.         {
  1873.             if ($return = $this->get_feed_tags($namespace, $tag))
  1874.             {
  1875.                 return $return;
  1876.             }
  1877.         }
  1878.         if ($type & SIMPLEPIE_TYPE_RSS_10)
  1879.         {
  1880.             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
  1881.             {
  1882.                 if (isset($channel[0]['child'][$namespace][$tag]))
  1883.                 {
  1884.                     return $channel[0]['child'][$namespace][$tag];
  1885.                 }
  1886.             }
  1887.         }
  1888.         if ($type & SIMPLEPIE_TYPE_RSS_090)
  1889.         {
  1890.             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
  1891.             {
  1892.                 if (isset($channel[0]['child'][$namespace][$tag]))
  1893.                 {
  1894.                     return $channel[0]['child'][$namespace][$tag];
  1895.                 }
  1896.             }
  1897.         }
  1898.         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1899.         {
  1900.             if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
  1901.             {
  1902.                 if (isset($channel[0]['child'][$namespace][$tag]))
  1903.                 {
  1904.                     return $channel[0]['child'][$namespace][$tag];
  1905.                 }
  1906.             }
  1907.         }
  1908.         return null;
  1909.     }
  1910.  
  1911.     /**
  1912.      * Get data for an channel-level element
  1913.      *
  1914.      * This method allows you to get access to ANY element/attribute in the
  1915.      * image/logo section of the feed.
  1916.      *
  1917.      * See {@see SimplePie::get_feed_tags()} for a description of the return value
  1918.      *
  1919.      * @since 1.0
  1920.      * @see http://simplepie.org/wiki/faq/supported_xml_namespaces
  1921.      * @param string $namespace The URL of the XML namespace of the elements you're trying to access
  1922.      * @param string $tag Tag name
  1923.      * @return array
  1924.      */
  1925.     public function get_image_tags($namespace, $tag)
  1926.     {
  1927.         $type = $this->get_type();
  1928.         if ($type & SIMPLEPIE_TYPE_RSS_10)
  1929.         {
  1930.             if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
  1931.             {
  1932.                 if (isset($image[0]['child'][$namespace][$tag]))
  1933.                 {
  1934.                     return $image[0]['child'][$namespace][$tag];
  1935.                 }
  1936.             }
  1937.         }
  1938.         if ($type & SIMPLEPIE_TYPE_RSS_090)
  1939.         {
  1940.             if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
  1941.             {
  1942.                 if (isset($image[0]['child'][$namespace][$tag]))
  1943.                 {
  1944.                     return $image[0]['child'][$namespace][$tag];
  1945.                 }
  1946.             }
  1947.         }
  1948.         if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1949.         {
  1950.             if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
  1951.             {
  1952.                 if (isset($image[0]['child'][$namespace][$tag]))
  1953.                 {
  1954.                     return $image[0]['child'][$namespace][$tag];
  1955.                 }
  1956.             }
  1957.         }
  1958.         return null;
  1959.     }
  1960.  
  1961.     /**
  1962.      * Get the base URL value from the feed
  1963.      *
  1964.      * Uses `<xml:base>` if available, otherwise uses the first link in the
  1965.      * feed, or failing that, the URL of the feed itself.
  1966.      *
  1967.      * @see get_link
  1968.      * @see subscribe_url
  1969.      *
  1970.      * @param array $element
  1971.      * @return string
  1972.      */
  1973.     public function get_base($element = array())
  1974.     {
  1975.         if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
  1976.         {
  1977.             return $element['xml_base'];
  1978.         }
  1979.         elseif ($this->get_link() !== null)
  1980.         {
  1981.             return $this->get_link();
  1982.         }
  1983.         else
  1984.         {
  1985.             return $this->subscribe_url();
  1986.         }
  1987.     }
  1988.  
  1989.     /**
  1990.      * Sanitize feed data
  1991.      *
  1992.      * @access private
  1993.      * @see SimplePie_Sanitize::sanitize()
  1994.      * @param string $data Data to sanitize
  1995.      * @param int $type One of the SIMPLEPIE_CONSTRUCT_* constants
  1996.      * @param string $base Base URL to resolve URLs against
  1997.      * @return string Sanitized data
  1998.      */
  1999.     public function sanitize($data, $type, $base = '')
  2000.     {
  2001.         return $this->sanitize->sanitize($data, $type, $base);
  2002.     }
  2003.  
  2004.     /**
  2005.      * Get the title of the feed
  2006.      *
  2007.      * Uses `<atom:title>`, `<title>` or `<dc:title>`
  2008.      *
  2009.      * @since 1.0 (previously called `get_feed_title` since 0.8)
  2010.      * @return string|null
  2011.      */
  2012.     public function get_title()
  2013.     {
  2014.         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  2015.         {
  2016.             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2017.         }
  2018.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  2019.         {
  2020.             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2021.         }
  2022.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2023.         {
  2024.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2025.         }
  2026.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2027.         {
  2028.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2029.         }
  2030.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2031.         {
  2032.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2033.         }
  2034.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2035.         {
  2036.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2037.         }
  2038.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2039.         {
  2040.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2041.         }
  2042.         else
  2043.         {
  2044.             return null;
  2045.         }
  2046.     }
  2047.  
  2048.     /**
  2049.      * Get a category for the feed
  2050.      *
  2051.      * @since Unknown
  2052.      * @param int $key The category that you want to return.  Remember that arrays begin with 0, not 1
  2053.      * @return SimplePie_Category|null
  2054.      */
  2055.     public function get_category($key = 0)
  2056.     {
  2057.         $categories = $this->get_categories();
  2058.         if (isset($categories[$key]))
  2059.         {
  2060.             return $categories[$key];
  2061.         }
  2062.         else
  2063.         {
  2064.             return null;
  2065.         }
  2066.     }
  2067.  
  2068.     /**
  2069.      * Get all categories for the feed
  2070.      *
  2071.      * Uses `<atom:category>`, `<category>` or `<dc:subject>`
  2072.      *
  2073.      * @since Unknown
  2074.      * @return array|null List of {@see SimplePie_Category} objects
  2075.      */
  2076.     public function get_categories()
  2077.     {
  2078.         $categories = array();
  2079.  
  2080.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  2081.         {
  2082.             $term = null;
  2083.             $scheme = null;
  2084.             $label = null;
  2085.             if (isset($category['attribs']['']['term']))
  2086.             {
  2087.                 $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  2088.             }
  2089.             if (isset($category['attribs']['']['scheme']))
  2090.             {
  2091.                 $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  2092.             }
  2093.             if (isset($category['attribs']['']['label']))
  2094.             {
  2095.                 $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  2096.             }
  2097.             $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
  2098.         }
  2099.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  2100.         {
  2101.             // This is really the label, but keep this as the term also for BC.
  2102.             // Label will also work on retrieving because that falls back to term.
  2103.             $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2104.             if (isset($category['attribs']['']['domain']))
  2105.             {
  2106.                 $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  2107.             }
  2108.             else
  2109.             {
  2110.                 $scheme = null;
  2111.             }
  2112.             $categories[] = $this->registry->create('Category', array($term, $scheme, null));
  2113.         }
  2114.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  2115.         {
  2116.             $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  2117.         }
  2118.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  2119.         {
  2120.             $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  2121.         }
  2122.  
  2123.         if (!empty($categories))
  2124.         {
  2125.             return array_unique($categories);
  2126.         }
  2127.         else
  2128.         {
  2129.             return null;
  2130.         }
  2131.     }
  2132.  
  2133.     /**
  2134.      * Get an author for the feed
  2135.      *
  2136.      * @since 1.1
  2137.      * @param int $key The author that you want to return.  Remember that arrays begin with 0, not 1
  2138.      * @return SimplePie_Author|null
  2139.      */
  2140.     public function get_author($key = 0)
  2141.     {
  2142.         $authors = $this->get_authors();
  2143.         if (isset($authors[$key]))
  2144.         {
  2145.             return $authors[$key];
  2146.         }
  2147.         else
  2148.         {
  2149.             return null;
  2150.         }
  2151.     }
  2152.  
  2153.     /**
  2154.      * Get all authors for the feed
  2155.      *
  2156.      * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
  2157.      *
  2158.      * @since 1.1
  2159.      * @return array|null List of {@see SimplePie_Author} objects
  2160.      */
  2161.     public function get_authors()
  2162.     {
  2163.         $authors = array();
  2164.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  2165.         {
  2166.             $name = null;
  2167.             $uri = null;
  2168.             $email = null;
  2169.             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2170.             {
  2171.                 $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2172.             }
  2173.             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2174.             {
  2175.                 $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  2176.             }
  2177.             if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2178.             {
  2179.                 $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2180.             }
  2181.             if ($name !== null || $email !== null || $uri !== null)
  2182.             {
  2183.                 $authors[] = $this->registry->create('Author', array($name, $uri, $email));
  2184.             }
  2185.         }
  2186.         if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  2187.         {
  2188.             $name = null;
  2189.             $url = null;
  2190.             $email = null;
  2191.             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2192.             {
  2193.                 $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2194.             }
  2195.             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2196.             {
  2197.                 $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  2198.             }
  2199.             if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2200.             {
  2201.                 $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2202.             }
  2203.             if ($name !== null || $email !== null || $url !== null)
  2204.             {
  2205.                 $authors[] = $this->registry->create('Author', array($name, $url, $email));
  2206.             }
  2207.         }
  2208.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  2209.         {
  2210.             $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  2211.         }
  2212.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  2213.         {
  2214.             $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  2215.         }
  2216.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  2217.         {
  2218.             $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
  2219.         }
  2220.  
  2221.         if (!empty($authors))
  2222.         {
  2223.             return array_unique($authors);
  2224.         }
  2225.         else
  2226.         {
  2227.             return null;
  2228.         }
  2229.     }
  2230.  
  2231.     /**
  2232.      * Get a contributor for the feed
  2233.      *
  2234.      * @since 1.1
  2235.      * @param int $key The contrbutor that you want to return.  Remember that arrays begin with 0, not 1
  2236.      * @return SimplePie_Author|null
  2237.      */
  2238.     public function get_contributor($key = 0)
  2239.     {
  2240.         $contributors = $this->get_contributors();
  2241.         if (isset($contributors[$key]))
  2242.         {
  2243.             return $contributors[$key];
  2244.         }
  2245.         else
  2246.         {
  2247.             return null;
  2248.         }
  2249.     }
  2250.  
  2251.     /**
  2252.      * Get all contributors for the feed
  2253.      *
  2254.      * Uses `<atom:contributor>`
  2255.      *
  2256.      * @since 1.1
  2257.      * @return array|null List of {@see SimplePie_Author} objects
  2258.      */
  2259.     public function get_contributors()
  2260.     {
  2261.         $contributors = array();
  2262.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  2263.         {
  2264.             $name = null;
  2265.             $uri = null;
  2266.             $email = null;
  2267.             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2268.             {
  2269.                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2270.             }
  2271.             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2272.             {
  2273.                 $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  2274.             }
  2275.             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2276.             {
  2277.                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2278.             }
  2279.             if ($name !== null || $email !== null || $uri !== null)
  2280.             {
  2281.                 $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
  2282.             }
  2283.         }
  2284.         foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  2285.         {
  2286.             $name = null;
  2287.             $url = null;
  2288.             $email = null;
  2289.             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2290.             {
  2291.                 $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2292.             }
  2293.             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2294.             {
  2295.                 $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  2296.             }
  2297.             if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2298.             {
  2299.                 $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2300.             }
  2301.             if ($name !== null || $email !== null || $url !== null)
  2302.             {
  2303.                 $contributors[] = $this->registry->create('Author', array($name, $url, $email));
  2304.             }
  2305.         }
  2306.  
  2307.         if (!empty($contributors))
  2308.         {
  2309.             return array_unique($contributors);
  2310.         }
  2311.         else
  2312.         {
  2313.             return null;
  2314.         }
  2315.     }
  2316.  
  2317.     /**
  2318.      * Get a single link for the feed
  2319.      *
  2320.      * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
  2321.      * @param int $key The link that you want to return.  Remember that arrays begin with 0, not 1
  2322.      * @param string $rel The relationship of the link to return
  2323.      * @return string|null Link URL
  2324.      */
  2325.     public function get_link($key = 0, $rel = 'alternate')
  2326.     {
  2327.         $links = $this->get_links($rel);
  2328.         if (isset($links[$key]))
  2329.         {
  2330.             return $links[$key];
  2331.         }
  2332.         else
  2333.         {
  2334.             return null;
  2335.         }
  2336.     }
  2337.  
  2338.     /**
  2339.      * Get the permalink for the item
  2340.      *
  2341.      * Returns the first link available with a relationship of "alternate".
  2342.      * Identical to {@see get_link()} with key 0
  2343.      *
  2344.      * @see get_link
  2345.      * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
  2346.      * @internal Added for parity between the parent-level and the item/entry-level.
  2347.      * @return string|null Link URL
  2348.      */
  2349.     public function get_permalink()
  2350.     {
  2351.         return $this->get_link(0);
  2352.     }
  2353.  
  2354.     /**
  2355.      * Get all links for the feed
  2356.      *
  2357.      * Uses `<atom:link>` or `<link>`
  2358.      *
  2359.      * @since Beta 2
  2360.      * @param string $rel The relationship of links to return
  2361.      * @return array|null Links found for the feed (strings)
  2362.      */
  2363.     public function get_links($rel = 'alternate')
  2364.     {
  2365.         if (!isset($this->data['links']))
  2366.         {
  2367.             $this->data['links'] = array();
  2368.             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  2369.             {
  2370.                 foreach ($links as $link)
  2371.                 {
  2372.                     if (isset($link['attribs']['']['href']))
  2373.                     {
  2374.                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2375.                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2376.                     }
  2377.                 }
  2378.             }
  2379.             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  2380.             {
  2381.                 foreach ($links as $link)
  2382.                 {
  2383.                     if (isset($link['attribs']['']['href']))
  2384.                     {
  2385.                         $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2386.                         $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2387.  
  2388.                     }
  2389.                 }
  2390.             }
  2391.             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2392.             {
  2393.                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2394.             }
  2395.             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2396.             {
  2397.                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2398.             }
  2399.             if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2400.             {
  2401.                 $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2402.             }
  2403.  
  2404.             $keys = array_keys($this->data['links']);
  2405.             foreach ($keys as $key)
  2406.             {
  2407.                 if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
  2408.                 {
  2409.                     if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  2410.                     {
  2411.                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  2412.                         $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  2413.                     }
  2414.                     else
  2415.                     {
  2416.                         $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  2417.                     }
  2418.                 }
  2419.                 elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  2420.                 {
  2421.                     $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  2422.                 }
  2423.                 $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  2424.             }
  2425.         }
  2426.  
  2427.         if (isset($this->data['links'][$rel]))
  2428.         {
  2429.             return $this->data['links'][$rel];
  2430.         }
  2431.         else
  2432.         {
  2433.             return null;
  2434.         }
  2435.     }
  2436.  
  2437.     public function get_all_discovered_feeds()
  2438.     {
  2439.         return $this->all_discovered_feeds;
  2440.     }
  2441.  
  2442.     /**
  2443.      * Get the content for the item
  2444.      *
  2445.      * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
  2446.      * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
  2447.      *
  2448.      * @since 1.0 (previously called `get_feed_description()` since 0.8)
  2449.      * @return string|null
  2450.      */
  2451.     public function get_description()
  2452.     {
  2453.         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  2454.         {
  2455.             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2456.         }
  2457.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  2458.         {
  2459.             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2460.         }
  2461.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  2462.         {
  2463.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2464.         }
  2465.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  2466.         {
  2467.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2468.         }
  2469.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  2470.         {
  2471.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2472.         }
  2473.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  2474.         {
  2475.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2476.         }
  2477.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  2478.         {
  2479.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2480.         }
  2481.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  2482.         {
  2483.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2484.         }
  2485.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  2486.         {
  2487.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2488.         }
  2489.         else
  2490.         {
  2491.             return null;
  2492.         }
  2493.     }
  2494.  
  2495.     /**
  2496.      * Get the copyright info for the feed
  2497.      *
  2498.      * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
  2499.      *
  2500.      * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
  2501.      * @return string|null
  2502.      */
  2503.     public function get_copyright()
  2504.     {
  2505.         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  2506.         {
  2507.             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2508.         }
  2509.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  2510.         {
  2511.             return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
  2512.         }
  2513.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  2514.         {
  2515.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2516.         }
  2517.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  2518.         {
  2519.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2520.         }
  2521.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  2522.         {
  2523.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2524.         }
  2525.         else
  2526.         {
  2527.             return null;
  2528.         }
  2529.     }
  2530.  
  2531.     /**
  2532.      * Get the language for the feed
  2533.      *
  2534.      * Uses `<language>`, `<dc:language>`, or @xml_lang
  2535.      *
  2536.      * @since 1.0 (previously called `get_feed_language()` since 0.8)
  2537.      * @return string|null
  2538.      */
  2539.     public function get_language()
  2540.     {
  2541.         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  2542.         {
  2543.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2544.         }
  2545.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  2546.         {
  2547.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2548.         }
  2549.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  2550.         {
  2551.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2552.         }
  2553.         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
  2554.         {
  2555.             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2556.         }
  2557.         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
  2558.         {
  2559.             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2560.         }
  2561.         elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
  2562.         {
  2563.             return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2564.         }
  2565.         elseif (isset($this->data['headers']['content-language']))
  2566.         {
  2567.             return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
  2568.         }
  2569.         else
  2570.         {
  2571.             return null;
  2572.         }
  2573.     }
  2574.  
  2575.     /**
  2576.      * Get the latitude coordinates for the item
  2577.      *
  2578.      * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
  2579.      *
  2580.      * Uses `<geo:lat>` or `<georss:point>`
  2581.      *
  2582.      * @since 1.0
  2583.      * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
  2584.      * @link http://www.georss.org/ GeoRSS
  2585.      * @return string|null
  2586.      */
  2587.     public function get_latitude()
  2588.     {
  2589.  
  2590.         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  2591.         {
  2592.             return (float) $return[0]['data'];
  2593.         }
  2594.         elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  2595.         {
  2596.             return (float) $match[1];
  2597.         }
  2598.         else
  2599.         {
  2600.             return null;
  2601.         }
  2602.     }
  2603.  
  2604.     /**
  2605.      * Get the longitude coordinates for the feed
  2606.      *
  2607.      * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
  2608.      *
  2609.      * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
  2610.      *
  2611.      * @since 1.0
  2612.      * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
  2613.      * @link http://www.georss.org/ GeoRSS
  2614.      * @return string|null
  2615.      */
  2616.     public function get_longitude()
  2617.     {
  2618.         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  2619.         {
  2620.             return (float) $return[0]['data'];
  2621.         }
  2622.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  2623.         {
  2624.             return (float) $return[0]['data'];
  2625.         }
  2626.         elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  2627.         {
  2628.             return (float) $match[2];
  2629.         }
  2630.         else
  2631.         {
  2632.             return null;
  2633.         }
  2634.     }
  2635.  
  2636.     /**
  2637.      * Get the feed logo's title
  2638.      *
  2639.      * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
  2640.      *
  2641.      * Uses `<image><title>` or `<image><dc:title>`
  2642.      *
  2643.      * @return string|null
  2644.      */
  2645.     public function get_image_title()
  2646.     {
  2647.         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2648.         {
  2649.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2650.         }
  2651.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2652.         {
  2653.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2654.         }
  2655.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2656.         {
  2657.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2658.         }
  2659.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2660.         {
  2661.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2662.         }
  2663.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2664.         {
  2665.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2666.         }
  2667.         else
  2668.         {
  2669.             return null;
  2670.         }
  2671.     }
  2672.  
  2673.     /**
  2674.      * Get the feed logo's URL
  2675.      *
  2676.      * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
  2677.      * have a "feed logo" URL. This points directly to the image itself.
  2678.      *
  2679.      * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
  2680.      * `<image><title>` or `<image><dc:title>`
  2681.      *
  2682.      * @return string|null
  2683.      */
  2684.     public function get_image_url()
  2685.     {
  2686.         if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  2687.         {
  2688.             return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  2689.         }
  2690.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  2691.         {
  2692.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2693.         }
  2694.         elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  2695.         {
  2696.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2697.         }
  2698.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
  2699.         {
  2700.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2701.         }
  2702.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
  2703.         {
  2704.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2705.         }
  2706.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2707.         {
  2708.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2709.         }
  2710.         else
  2711.         {
  2712.             return null;
  2713.         }
  2714.     }
  2715.  
  2716.  
  2717.     /**
  2718.      * Get the feed logo's link
  2719.      *
  2720.      * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
  2721.      * points to a human-readable page that the image should link to.
  2722.      *
  2723.      * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
  2724.      * `<image><title>` or `<image><dc:title>`
  2725.      *
  2726.      * @return string|null
  2727.      */
  2728.     public function get_image_link()
  2729.     {
  2730.         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2731.         {
  2732.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2733.         }
  2734.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2735.         {
  2736.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2737.         }
  2738.         elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2739.         {
  2740.             return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2741.         }
  2742.         else
  2743.         {
  2744.             return null;
  2745.         }
  2746.     }
  2747.  
  2748.     /**
  2749.      * Get the feed logo's link
  2750.      *
  2751.      * RSS 2.0 feeds are allowed to have a "feed logo" width.
  2752.      *
  2753.      * Uses `<image><width>` or defaults to 88.0 if no width is specified and
  2754.      * the feed is an RSS 2.0 feed.
  2755.      *
  2756.      * @return int|float|null
  2757.      */
  2758.     public function get_image_width()
  2759.     {
  2760.         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
  2761.         {
  2762.             return round($return[0]['data']);
  2763.         }
  2764.         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2765.         {
  2766.             return 88.0;
  2767.         }
  2768.         else
  2769.         {
  2770.             return null;
  2771.         }
  2772.     }
  2773.  
  2774.     /**
  2775.      * Get the feed logo's height
  2776.      *
  2777.      * RSS 2.0 feeds are allowed to have a "feed logo" height.
  2778.      *
  2779.      * Uses `<image><height>` or defaults to 31.0 if no height is specified and
  2780.      * the feed is an RSS 2.0 feed.
  2781.      *
  2782.      * @return int|float|null
  2783.      */
  2784.     public function get_image_height()
  2785.     {
  2786.         if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
  2787.         {
  2788.             return round($return[0]['data']);
  2789.         }
  2790.         elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2791.         {
  2792.             return 31.0;
  2793.         }
  2794.         else
  2795.         {
  2796.             return null;
  2797.         }
  2798.     }
  2799.  
  2800.     /**
  2801.      * Get the number of items in the feed
  2802.      *
  2803.      * This is well-suited for {@link http://php.net/for for()} loops with
  2804.      * {@see get_item()}
  2805.      *
  2806.      * @param int $max Maximum value to return. 0 for no limit
  2807.      * @return int Number of items in the feed
  2808.      */
  2809.     public function get_item_quantity($max = 0)
  2810.     {
  2811.         $max = (int) $max;
  2812.         $qty = count($this->get_items());
  2813.         if ($max === 0)
  2814.         {
  2815.             return $qty;
  2816.         }
  2817.         else
  2818.         {
  2819.             return ($qty > $max) ? $max : $qty;
  2820.         }
  2821.     }
  2822.  
  2823.     /**
  2824.      * Get a single item from the feed
  2825.      *
  2826.      * This is better suited for {@link http://php.net/for for()} loops, whereas
  2827.      * {@see get_items()} is better suited for
  2828.      * {@link http://php.net/foreach foreach()} loops.
  2829.      *
  2830.      * @see get_item_quantity()
  2831.      * @since Beta 2
  2832.      * @param int $key The item that you want to return.  Remember that arrays begin with 0, not 1
  2833.      * @return SimplePie_Item|null
  2834.      */
  2835.     public function get_item($key = 0)
  2836.     {
  2837.         $items = $this->get_items();
  2838.         if (isset($items[$key]))
  2839.         {
  2840.             return $items[$key];
  2841.         }
  2842.         else
  2843.         {
  2844.             return null;
  2845.         }
  2846.     }
  2847.  
  2848.     /**
  2849.      * Get all items from the feed
  2850.      *
  2851.      * This is better suited for {@link http://php.net/for for()} loops, whereas
  2852.      * {@see get_items()} is better suited for
  2853.      * {@link http://php.net/foreach foreach()} loops.
  2854.      *
  2855.      * @see get_item_quantity
  2856.      * @since Beta 2
  2857.      * @param int $start Index to start at
  2858.      * @param int $end Number of items to return. 0 for all items after `$start`
  2859.      * @return array|null List of {@see SimplePie_Item} objects
  2860.      */
  2861.     public function get_items($start = 0, $end = 0)
  2862.     {
  2863.         if (!isset($this->data['items']))
  2864.         {
  2865.             if (!empty($this->multifeed_objects))
  2866.             {
  2867.                 $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
  2868.             }
  2869.             else
  2870.             {
  2871.                 $this->data['items'] = array();
  2872.                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
  2873.                 {
  2874.                     $keys = array_keys($items);
  2875.                     foreach ($keys as $key)
  2876.                     {
  2877.                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2878.                     }
  2879.                 }
  2880.                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
  2881.                 {
  2882.                     $keys = array_keys($items);
  2883.                     foreach ($keys as $key)
  2884.                     {
  2885.                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2886.                     }
  2887.                 }
  2888.                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
  2889.                 {
  2890.                     $keys = array_keys($items);
  2891.                     foreach ($keys as $key)
  2892.                     {
  2893.                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2894.                     }
  2895.                 }
  2896.                 if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
  2897.                 {
  2898.                     $keys = array_keys($items);
  2899.                     foreach ($keys as $key)
  2900.                     {
  2901.                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2902.                     }
  2903.                 }
  2904.                 if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
  2905.                 {
  2906.                     $keys = array_keys($items);
  2907.                     foreach ($keys as $key)
  2908.                     {
  2909.                         $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
  2910.                     }
  2911.                 }
  2912.             }
  2913.         }
  2914.  
  2915.         if (!empty($this->data['items']))
  2916.         {
  2917.             // If we want to order it by date, check if all items have a date, and then sort it
  2918.             if ($this->order_by_date && empty($this->multifeed_objects))
  2919.             {
  2920.                 if (!isset($this->data['ordered_items']))
  2921.                 {
  2922.                     $do_sort = true;
  2923.                     foreach ($this->data['items'] as $item)
  2924.                     {
  2925.                         if (!$item->get_date('U'))
  2926.                         {
  2927.                             $do_sort = false;
  2928.                             break;
  2929.                         }
  2930.                     }
  2931.                     $item = null;
  2932.                     $this->data['ordered_items'] = $this->data['items'];
  2933.                     if ($do_sort)
  2934.                     {
  2935.                         usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
  2936.                     }
  2937.                 }
  2938.                 $items = $this->data['ordered_items'];
  2939.             }
  2940.             else
  2941.             {
  2942.                 $items = $this->data['items'];
  2943.             }
  2944.  
  2945.             // Slice the data as desired
  2946.             if ($end === 0)
  2947.             {
  2948.                 return array_slice($items, $start);
  2949.             }
  2950.             else
  2951.             {
  2952.                 return array_slice($items, $start, $end);
  2953.             }
  2954.         }
  2955.         else
  2956.         {
  2957.             return array();
  2958.         }
  2959.     }
  2960.  
  2961.     /**
  2962.      * Set the favicon handler
  2963.      *
  2964.      * @deprecated Use your own favicon handling instead
  2965.      */
  2966.     public function set_favicon_handler($page = false, $qs = 'i')
  2967.     {
  2968.         $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  2969.         trigger_error('Favicon handling has been removed, please use your own handling', $level);
  2970.         return false;
  2971.     }
  2972.  
  2973.     /**
  2974.      * Get the favicon for the current feed
  2975.      *
  2976.      * @deprecated Use your own favicon handling instead
  2977.      */
  2978.     public function get_favicon()
  2979.     {
  2980.         $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  2981.         trigger_error('Favicon handling has been removed, please use your own handling', $level);
  2982.  
  2983.         if (($url = $this->get_link()) !== null)
  2984.         {
  2985.             return 'http://g.etfv.co/' . urlencode($url);
  2986.         }
  2987.  
  2988.         return false;
  2989.     }
  2990.  
  2991.     /**
  2992.      * Magic method handler
  2993.      *
  2994.      * @param string $method Method name
  2995.      * @param array $args Arguments to the method
  2996.      * @return mixed
  2997.      */
  2998.     public function __call($method, $args)
  2999.     {
  3000.         if (strpos($method, 'subscribe_') === 0)
  3001.         {
  3002.             $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  3003.             trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
  3004.             return '';
  3005.         }
  3006.         if ($method === 'enable_xml_dump')
  3007.         {
  3008.             $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
  3009.             trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
  3010.             return false;
  3011.         }
  3012.  
  3013.         $class = get_class($this);
  3014.         $trace = debug_backtrace();
  3015.         $file = $trace[0]['file'];
  3016.         $line = $trace[0]['line'];
  3017.         trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
  3018.     }
  3019.  
  3020.     /**
  3021.      * Sorting callback for items
  3022.      *
  3023.      * @access private
  3024.      * @param SimplePie $a
  3025.      * @param SimplePie $b
  3026.      * @return boolean
  3027.      */
  3028.     public static function sort_items($a, $b)
  3029.     {
  3030.         return $a->get_date('U') <= $b->get_date('U');
  3031.     }
  3032.  
  3033.     /**
  3034.      * Merge items from several feeds into one
  3035.      *
  3036.      * If you're merging multiple feeds together, they need to all have dates
  3037.      * for the items or else SimplePie will refuse to sort them.
  3038.      *
  3039.      * @link http://simplepie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
  3040.      * @param array $urls List of SimplePie feed objects to merge
  3041.      * @param int $start Starting item
  3042.      * @param int $end Number of items to return
  3043.      * @param int $limit Maximum number of items per feed
  3044.      * @return array
  3045.      */
  3046.     public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
  3047.     {
  3048.         if (is_array($urls) && sizeof($urls) > 0)
  3049.         {
  3050.             $items = array();
  3051.             foreach ($urls as $arg)
  3052.             {
  3053.                 if ($arg instanceof SimplePie)
  3054.                 {
  3055.                     $items = array_merge($items, $arg->get_items(0, $limit));
  3056.                 }
  3057.                 else
  3058.                 {
  3059.                     trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
  3060.                 }
  3061.             }
  3062.  
  3063.             $do_sort = true;
  3064.             foreach ($items as $item)
  3065.             {
  3066.                 if (!$item->get_date('U'))
  3067.                 {
  3068.                     $do_sort = false;
  3069.                     break;
  3070.                 }
  3071.             }
  3072.             $item = null;
  3073.             if ($do_sort)
  3074.             {
  3075.                 usort($items, array(get_class($urls[0]), 'sort_items'));
  3076.             }
  3077.  
  3078.             if ($end === 0)
  3079.             {
  3080.                 return array_slice($items, $start);
  3081.             }
  3082.             else
  3083.             {
  3084.                 return array_slice($items, $start, $end);
  3085.             }
  3086.         }
  3087.         else
  3088.         {
  3089.             trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
  3090.             return array();
  3091.         }
  3092.     }
  3093. }
  3094. endif;