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