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