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