[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> rss.php (source)

   1  <?php
   2  /**
   3   * MagpieRSS: a simple RSS integration tool
   4   *
   5   * A compiled file for RSS syndication
   6   *
   7   * @author Kellan Elliott-McCrea <kellan@protest.net>
   8   * @version 0.51
   9   * @license GPL
  10   *
  11   * @package External
  12   * @subpackage MagpieRSS
  13   * @deprecated 3.0.0 Use SimplePie instead.
  14   */
  15  
  16  /**
  17   * Deprecated. Use SimplePie (class-simplepie.php) instead.
  18   */
  19  _deprecated_file( basename( __FILE__ ), '3.0.0', WPINC . '/class-simplepie.php' );
  20  
  21  /**
  22   * Fires before MagpieRSS is loaded, to optionally replace it.
  23   *
  24   * @since 2.3.0
  25   * @deprecated 3.0.0
  26   */
  27  do_action( 'load_feed_engine' );
  28  
  29  /** RSS feed constant. */
  30  define('RSS', 'RSS');
  31  define('ATOM', 'Atom');
  32  define('MAGPIE_USER_AGENT', 'WordPress/' . $GLOBALS['wp_version']);
  33  
  34  class MagpieRSS {
  35      var $parser;
  36      var $current_item    = array();    // item currently being parsed
  37      var $items            = array();    // collection of parsed items
  38      var $channel        = array();    // hash of channel fields
  39      var $textinput        = array();
  40      var $image            = array();
  41      var $feed_type;
  42      var $feed_version;
  43  
  44      // parser variables
  45      var $stack                = array(); // parser stack
  46      var $inchannel            = false;
  47      var $initem             = false;
  48      var $incontent            = false; // if in Atom <content mode="xml"> field
  49      var $intextinput        = false;
  50      var $inimage             = false;
  51      var $current_field        = '';
  52      var $current_namespace    = false;
  53  
  54      //var $ERROR = "";
  55  
  56      var $_CONTENT_CONSTRUCTS = array('content', 'summary', 'info', 'title', 'tagline', 'copyright');
  57  
  58      /**
  59       * PHP5 constructor.
  60       */
  61  	function __construct( $source ) {
  62  
  63          # Check if PHP xml isn't compiled
  64          #
  65          if ( ! function_exists('xml_parser_create') ) {
  66              wp_trigger_error( '', "PHP's XML extension is not available. Please contact your hosting provider to enable PHP's XML extension." );
  67              return;
  68          }
  69  
  70          $parser = xml_parser_create();
  71  
  72          $this->parser = $parser;
  73  
  74          # pass in parser, and a reference to this object
  75          # set up handlers
  76          #
  77          xml_set_element_handler($this->parser,
  78                  array( $this, 'feed_start_element' ), array( $this, 'feed_end_element' ) );
  79  
  80          xml_set_character_data_handler( $this->parser, array( $this, 'feed_cdata' ) );
  81  
  82          $status = xml_parse( $this->parser, $source );
  83  
  84          if (! $status ) {
  85              $errorcode = xml_get_error_code( $this->parser );
  86              if ( $errorcode != XML_ERROR_NONE ) {
  87                  $xml_error = xml_error_string( $errorcode );
  88                  $error_line = xml_get_current_line_number($this->parser);
  89                  $error_col = xml_get_current_column_number($this->parser);
  90                  $errormsg = "$xml_error at line $error_line, column $error_col";
  91  
  92                  $this->error( $errormsg );
  93              }
  94          }
  95  
  96          if ( PHP_VERSION_ID < 80000 ) { // xml_parser_free() has no effect as of PHP 8.0.
  97              xml_parser_free( $this->parser );
  98          }
  99  
 100          unset( $this->parser );
 101  
 102          $this->normalize();
 103      }
 104  
 105      /**
 106       * PHP4 constructor.
 107       */
 108  	public function MagpieRSS( $source ) {
 109          self::__construct( $source );
 110      }
 111  
 112  	function feed_start_element($p, $element, &$attrs) {
 113          $el = $element = strtolower($element);
 114          $attrs = array_change_key_case($attrs, CASE_LOWER);
 115  
 116          // check for a namespace, and split if found
 117          $ns    = false;
 118          if ( strpos( $element, ':' ) ) {
 119              list($ns, $el) = explode( ':', $element, 2);
 120          }
 121          if ( $ns and $ns != 'rdf' ) {
 122              $this->current_namespace = $ns;
 123          }
 124  
 125          # if feed type isn't set, then this is first element of feed
 126          # identify feed from root element
 127          #
 128          if (!isset($this->feed_type) ) {
 129              if ( $el == 'rdf' ) {
 130                  $this->feed_type = RSS;
 131                  $this->feed_version = '1.0';
 132              }
 133              elseif ( $el == 'rss' ) {
 134                  $this->feed_type = RSS;
 135                  $this->feed_version = $attrs['version'];
 136              }
 137              elseif ( $el == 'feed' ) {
 138                  $this->feed_type = ATOM;
 139                  $this->feed_version = $attrs['version'];
 140                  $this->inchannel = true;
 141              }
 142              return;
 143          }
 144  
 145          if ( $el == 'channel' )
 146          {
 147              $this->inchannel = true;
 148          }
 149          elseif ($el == 'item' or $el == 'entry' )
 150          {
 151              $this->initem = true;
 152              if ( isset($attrs['rdf:about']) ) {
 153                  $this->current_item['about'] = $attrs['rdf:about'];
 154              }
 155          }
 156  
 157          // if we're in the default namespace of an RSS feed,
 158          //  record textinput or image fields
 159          elseif (
 160              $this->feed_type == RSS and
 161              $this->current_namespace == '' and
 162              $el == 'textinput' )
 163          {
 164              $this->intextinput = true;
 165          }
 166  
 167          elseif (
 168              $this->feed_type == RSS and
 169              $this->current_namespace == '' and
 170              $el == 'image' )
 171          {
 172              $this->inimage = true;
 173          }
 174  
 175          # handle atom content constructs
 176          elseif ( $this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) )
 177          {
 178              // avoid clashing w/ RSS mod_content
 179              if ($el == 'content' ) {
 180                  $el = 'atom_content';
 181              }
 182  
 183              $this->incontent = $el;
 184  
 185          }
 186  
 187          // if inside an Atom content construct (e.g. content or summary) field treat tags as text
 188          elseif ($this->feed_type == ATOM and $this->incontent )
 189          {
 190              // if tags are inlined, then flatten
 191              $attrs_str = join(' ',
 192                      array_map(array('MagpieRSS', 'map_attrs'),
 193                      array_keys($attrs),
 194                      array_values($attrs) ) );
 195  
 196              $this->append_content( "<$element $attrs_str>"  );
 197  
 198              array_unshift( $this->stack, $el );
 199          }
 200  
 201          // Atom support many links per containing element.
 202          // Magpie treats link elements of type rel='alternate'
 203          // as being equivalent to RSS's simple link element.
 204          //
 205          elseif ($this->feed_type == ATOM and $el == 'link' )
 206          {
 207              if ( isset($attrs['rel']) and $attrs['rel'] == 'alternate' )
 208              {
 209                  $link_el = 'link';
 210              }
 211              else {
 212                  $link_el = 'link_' . $attrs['rel'];
 213              }
 214  
 215              $this->append($link_el, $attrs['href']);
 216          }
 217          // set stack[0] to current element
 218          else {
 219              array_unshift($this->stack, $el);
 220          }
 221      }
 222  
 223  	function feed_cdata ($p, $text) {
 224  
 225          if ($this->feed_type == ATOM and $this->incontent)
 226          {
 227              $this->append_content( $text );
 228          }
 229          else {
 230              $current_el = join('_', array_reverse($this->stack));
 231              $this->append($current_el, $text);
 232          }
 233      }
 234  
 235  	function feed_end_element ($p, $el) {
 236          $el = strtolower($el);
 237  
 238          if ( $el == 'item' or $el == 'entry' )
 239          {
 240              $this->items[] = $this->current_item;
 241              $this->current_item = array();
 242              $this->initem = false;
 243          }
 244          elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'textinput' )
 245          {
 246              $this->intextinput = false;
 247          }
 248          elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'image' )
 249          {
 250              $this->inimage = false;
 251          }
 252          elseif ($this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) )
 253          {
 254              $this->incontent = false;
 255          }
 256          elseif ($el == 'channel' or $el == 'feed' )
 257          {
 258              $this->inchannel = false;
 259          }
 260          elseif ($this->feed_type == ATOM and $this->incontent  ) {
 261              // balance tags properly
 262              // note: This may not actually be necessary
 263              if ( $this->stack[0] == $el )
 264              {
 265                  $this->append_content("</$el>");
 266              }
 267              else {
 268                  $this->append_content("<$el />");
 269              }
 270  
 271              array_shift( $this->stack );
 272          }
 273          else {
 274              array_shift( $this->stack );
 275          }
 276  
 277          $this->current_namespace = false;
 278      }
 279  
 280  	function concat (&$str1, $str2="") {
 281          if (!isset($str1) ) {
 282              $str1="";
 283          }
 284          $str1 .= $str2;
 285      }
 286  
 287  	function append_content($text) {
 288          if ( $this->initem ) {
 289              $this->concat( $this->current_item[ $this->incontent ], $text );
 290          }
 291          elseif ( $this->inchannel ) {
 292              $this->concat( $this->channel[ $this->incontent ], $text );
 293          }
 294      }
 295  
 296      // smart append - field and namespace aware
 297  	function append($el, $text) {
 298          if (!$el) {
 299              return;
 300          }
 301          if ( $this->current_namespace )
 302          {
 303              if ( $this->initem ) {
 304                  $this->concat(
 305                      $this->current_item[ $this->current_namespace ][ $el ], $text);
 306              }
 307              elseif ($this->inchannel) {
 308                  $this->concat(
 309                      $this->channel[ $this->current_namespace][ $el ], $text );
 310              }
 311              elseif ($this->intextinput) {
 312                  $this->concat(
 313                      $this->textinput[ $this->current_namespace][ $el ], $text );
 314              }
 315              elseif ($this->inimage) {
 316                  $this->concat(
 317                      $this->image[ $this->current_namespace ][ $el ], $text );
 318              }
 319          }
 320          else {
 321              if ( $this->initem ) {
 322                  $this->concat(
 323                      $this->current_item[ $el ], $text);
 324              }
 325              elseif ($this->intextinput) {
 326                  $this->concat(
 327                      $this->textinput[ $el ], $text );
 328              }
 329              elseif ($this->inimage) {
 330                  $this->concat(
 331                      $this->image[ $el ], $text );
 332              }
 333              elseif ($this->inchannel) {
 334                  $this->concat(
 335                      $this->channel[ $el ], $text );
 336              }
 337  
 338          }
 339      }
 340  
 341  	function normalize () {
 342          // if atom populate rss fields
 343          if ( $this->is_atom() ) {
 344              $this->channel['description'] = $this->channel['tagline'];
 345              for ( $i = 0; $i < count($this->items); $i++) {
 346                  $item = $this->items[$i];
 347                  if ( isset($item['summary']) )
 348                      $item['description'] = $item['summary'];
 349                  if ( isset($item['atom_content']))
 350                      $item['content']['encoded'] = $item['atom_content'];
 351  
 352                  $this->items[$i] = $item;
 353              }
 354          }
 355          elseif ( $this->is_rss() ) {
 356              $this->channel['tagline'] = $this->channel['description'];
 357              for ( $i = 0; $i < count($this->items); $i++) {
 358                  $item = $this->items[$i];
 359                  if ( isset($item['description']))
 360                      $item['summary'] = $item['description'];
 361                  if ( isset($item['content']['encoded'] ) )
 362                      $item['atom_content'] = $item['content']['encoded'];
 363  
 364                  $this->items[$i] = $item;
 365              }
 366          }
 367      }
 368  
 369  	function is_rss () {
 370          if ( $this->feed_type == RSS ) {
 371              return $this->feed_version;
 372          }
 373          else {
 374              return false;
 375          }
 376      }
 377  
 378  	function is_atom() {
 379          if ( $this->feed_type == ATOM ) {
 380              return $this->feed_version;
 381          }
 382          else {
 383              return false;
 384          }
 385      }
 386  
 387  	function map_attrs($k, $v) {
 388          return "$k=\"$v\"";
 389      }
 390  
 391  	function error( $errormsg, $lvl = E_USER_WARNING ) {
 392          if ( MAGPIE_DEBUG ) {
 393              wp_trigger_error('', $errormsg, $lvl);
 394          } else {
 395              error_log( $errormsg, 0);
 396          }
 397      }
 398  
 399  }
 400  
 401  if ( !function_exists('fetch_rss') ) :
 402  /**
 403   * Build Magpie object based on RSS from URL.
 404   *
 405   * @since 1.5.0
 406   * @package External
 407   * @subpackage MagpieRSS
 408   *
 409   * @param string $url URL to retrieve feed.
 410   * @return MagpieRSS|false MagpieRSS object on success, false on failure.
 411   */
 412  function fetch_rss ($url) {
 413      // initialize constants
 414      init();
 415  
 416      if ( !isset($url) ) {
 417          // error("fetch_rss called without a url");
 418          return false;
 419      }
 420  
 421      // if cache is disabled
 422      if ( !MAGPIE_CACHE_ON ) {
 423          // fetch file, and parse it
 424          $resp = _fetch_remote_file( $url );
 425          if ( is_success( $resp->status ) ) {
 426              return _response_to_rss( $resp );
 427          }
 428          else {
 429              // error("Failed to fetch $url and cache is off");
 430              return false;
 431          }
 432      }
 433      // else cache is ON
 434      else {
 435          // Flow
 436          // 1. check cache
 437          // 2. if there is a hit, make sure it's fresh
 438          // 3. if cached obj fails freshness check, fetch remote
 439          // 4. if remote fails, return stale object, or error
 440  
 441          $cache = new RSSCache( MAGPIE_CACHE_DIR, MAGPIE_CACHE_AGE );
 442  
 443          if (MAGPIE_DEBUG and $cache->ERROR) {
 444              debug($cache->ERROR, E_USER_WARNING);
 445          }
 446  
 447          $cache_status      = 0;        // response of check_cache
 448          $request_headers = array(); // HTTP headers to send with fetch
 449          $rss              = 0;        // parsed RSS object
 450          $errormsg         = 0;        // errors, if any
 451  
 452          if (!$cache->ERROR) {
 453              // return cache HIT, MISS, or STALE
 454              $cache_status = $cache->check_cache( $url );
 455          }
 456  
 457          // if object cached, and cache is fresh, return cached obj
 458          if ( $cache_status == 'HIT' ) {
 459              $rss = $cache->get( $url );
 460              if ( isset($rss) and $rss ) {
 461                  $rss->from_cache = 1;
 462                  if ( MAGPIE_DEBUG > 1) {
 463                  debug("MagpieRSS: Cache HIT", E_USER_NOTICE);
 464              }
 465                  return $rss;
 466              }
 467          }
 468  
 469          // else attempt a conditional get
 470  
 471          // set up headers
 472          if ( $cache_status == 'STALE' ) {
 473              $rss = $cache->get( $url );
 474              if ( isset($rss->etag) and $rss->last_modified ) {
 475                  $request_headers['If-None-Match'] = $rss->etag;
 476                  $request_headers['If-Last-Modified'] = $rss->last_modified;
 477              }
 478          }
 479  
 480          $resp = _fetch_remote_file( $url, $request_headers );
 481  
 482          if (isset($resp) and $resp) {
 483              if ($resp->status == '304' ) {
 484                  // we have the most current copy
 485                  if ( MAGPIE_DEBUG > 1) {
 486                      debug("Got 304 for $url");
 487                  }
 488                  // reset cache on 304 (at minutillo insistent prodding)
 489                  $cache->set($url, $rss);
 490                  return $rss;
 491              }
 492              elseif ( is_success( $resp->status ) ) {
 493                  $rss = _response_to_rss( $resp );
 494                  if ( $rss ) {
 495                      if (MAGPIE_DEBUG > 1) {
 496                          debug("Fetch successful");
 497                      }
 498                      // add object to cache
 499                      $cache->set( $url, $rss );
 500                      return $rss;
 501                  }
 502              }
 503              else {
 504                  $errormsg = "Failed to fetch $url. ";
 505                  if ( $resp->error ) {
 506                      # compensate for Snoopy's annoying habit to tacking
 507                      # on '\n'
 508                      $http_error = substr($resp->error, 0, -2);
 509                      $errormsg .= "(HTTP Error: $http_error)";
 510                  }
 511                  else {
 512                      $errormsg .=  "(HTTP Response: " . $resp->response_code .')';
 513                  }
 514              }
 515          }
 516          else {
 517              $errormsg = "Unable to retrieve RSS file for unknown reasons.";
 518          }
 519  
 520          // else fetch failed
 521  
 522          // attempt to return cached object
 523          if ($rss) {
 524              if ( MAGPIE_DEBUG ) {
 525                  debug("Returning STALE object for $url");
 526              }
 527              return $rss;
 528          }
 529  
 530          // else we totally failed
 531          // error( $errormsg );
 532  
 533          return false;
 534  
 535      } // end if ( !MAGPIE_CACHE_ON ) {
 536  } // end fetch_rss()
 537  endif;
 538  
 539  /**
 540   * Retrieve URL headers and content using WP HTTP Request API.
 541   *
 542   * @since 1.5.0
 543   * @package External
 544   * @subpackage MagpieRSS
 545   *
 546   * @param string $url URL to retrieve
 547   * @param array $headers Optional. Headers to send to the URL. Default empty string.
 548   * @return Snoopy style response
 549   */
 550  function _fetch_remote_file($url, $headers = "" ) {
 551      $resp = wp_safe_remote_request( $url, array( 'headers' => $headers, 'timeout' => MAGPIE_FETCH_TIME_OUT ) );
 552      if ( is_wp_error($resp) ) {
 553          $error = array_shift($resp->errors);
 554  
 555          $resp = new stdClass;
 556          $resp->status = 500;
 557          $resp->response_code = 500;
 558          $resp->error = $error[0] . "\n"; //\n = Snoopy compatibility
 559          return $resp;
 560      }
 561  
 562      // Snoopy returns headers unprocessed.
 563      // Also note, WP_HTTP lowercases all keys, Snoopy did not.
 564      $return_headers = array();
 565      foreach ( wp_remote_retrieve_headers( $resp ) as $key => $value ) {
 566          if ( !is_array($value) ) {
 567              $return_headers[] = "$key: $value";
 568          } else {
 569              foreach ( $value as $v )
 570                  $return_headers[] = "$key: $v";
 571          }
 572      }
 573  
 574      $response = new stdClass;
 575      $response->status = wp_remote_retrieve_response_code( $resp );
 576      $response->response_code = wp_remote_retrieve_response_code( $resp );
 577      $response->headers = $return_headers;
 578      $response->results = wp_remote_retrieve_body( $resp );
 579  
 580      return $response;
 581  }
 582  
 583  /**
 584   * Retrieve
 585   *
 586   * @since 1.5.0
 587   * @package External
 588   * @subpackage MagpieRSS
 589   *
 590   * @param array $resp
 591   * @return MagpieRSS|bool
 592   */
 593  function _response_to_rss ($resp) {
 594      $rss = new MagpieRSS( $resp->results );
 595  
 596      // if RSS parsed successfully
 597      if ( $rss && (!isset($rss->ERROR) || !$rss->ERROR) ) {
 598  
 599          // find Etag, and Last-Modified
 600          foreach ( (array) $resp->headers as $h) {
 601              // 2003-03-02 - Nicola Asuni (www.tecnick.com) - fixed bug "Undefined offset: 1"
 602              if (strpos($h, ": ")) {
 603                  list($field, $val) = explode(": ", $h, 2);
 604              }
 605              else {
 606                  $field = $h;
 607                  $val = "";
 608              }
 609  
 610              if ( $field == 'etag' ) {
 611                  $rss->etag = $val;
 612              }
 613  
 614              if ( $field == 'last-modified' ) {
 615                  $rss->last_modified = $val;
 616              }
 617          }
 618  
 619          return $rss;
 620      } // else construct error message
 621      else {
 622          $errormsg = "Failed to parse RSS file.";
 623  
 624          if ($rss) {
 625              $errormsg .= " (" . $rss->ERROR . ")";
 626          }
 627          // error($errormsg);
 628  
 629          return false;
 630      } // end if ($rss and !$rss->error)
 631  }
 632  
 633  /**
 634   * Set up constants with default values, unless user overrides.
 635   *
 636   * @since 1.5.0
 637   * 
 638   * @global string $wp_version The WordPress version string.
 639   * 
 640   * @package External
 641   * @subpackage MagpieRSS
 642   */
 643  function init () {
 644      if ( defined('MAGPIE_INITALIZED') ) {
 645          return;
 646      }
 647      else {
 648          define('MAGPIE_INITALIZED', 1);
 649      }
 650  
 651      if ( !defined('MAGPIE_CACHE_ON') ) {
 652          define('MAGPIE_CACHE_ON', 1);
 653      }
 654  
 655      if ( !defined('MAGPIE_CACHE_DIR') ) {
 656          define('MAGPIE_CACHE_DIR', './cache');
 657      }
 658  
 659      if ( !defined('MAGPIE_CACHE_AGE') ) {
 660          define('MAGPIE_CACHE_AGE', 60*60); // one hour
 661      }
 662  
 663      if ( !defined('MAGPIE_CACHE_FRESH_ONLY') ) {
 664          define('MAGPIE_CACHE_FRESH_ONLY', 0);
 665      }
 666  
 667          if ( !defined('MAGPIE_DEBUG') ) {
 668          define('MAGPIE_DEBUG', 0);
 669      }
 670  
 671      if ( !defined('MAGPIE_USER_AGENT') ) {
 672          $ua = 'WordPress/' . $GLOBALS['wp_version'];
 673  
 674          if ( MAGPIE_CACHE_ON ) {
 675              $ua = $ua . ')';
 676          }
 677          else {
 678              $ua = $ua . '; No cache)';
 679          }
 680  
 681          define('MAGPIE_USER_AGENT', $ua);
 682      }
 683  
 684      if ( !defined('MAGPIE_FETCH_TIME_OUT') ) {
 685          define('MAGPIE_FETCH_TIME_OUT', 2);    // 2 second timeout
 686      }
 687  
 688      // use gzip encoding to fetch rss files if supported?
 689      if ( !defined('MAGPIE_USE_GZIP') ) {
 690          define('MAGPIE_USE_GZIP', true);
 691      }
 692  }
 693  
 694  function is_info ($sc) {
 695      return $sc >= 100 && $sc < 200;
 696  }
 697  
 698  function is_success ($sc) {
 699      return $sc >= 200 && $sc < 300;
 700  }
 701  
 702  function is_redirect ($sc) {
 703      return $sc >= 300 && $sc < 400;
 704  }
 705  
 706  function is_error ($sc) {
 707      return $sc >= 400 && $sc < 600;
 708  }
 709  
 710  function is_client_error ($sc) {
 711      return $sc >= 400 && $sc < 500;
 712  }
 713  
 714  function is_server_error ($sc) {
 715      return $sc >= 500 && $sc < 600;
 716  }
 717  
 718  class RSSCache {
 719      var $BASE_CACHE;    // where the cache files are stored
 720      var $MAX_AGE    = 43200;          // when are files stale, default twelve hours
 721      var $ERROR         = '';            // accumulate error messages
 722  
 723      /**
 724       * PHP5 constructor.
 725       */
 726  	function __construct( $base = '', $age = '' ) {
 727          $this->BASE_CACHE = WP_CONTENT_DIR . '/cache';
 728          if ( $base ) {
 729              $this->BASE_CACHE = $base;
 730          }
 731          if ( $age ) {
 732              $this->MAX_AGE = $age;
 733          }
 734  
 735      }
 736  
 737      /**
 738       * PHP4 constructor.
 739       */
 740  	public function RSSCache( $base = '', $age = '' ) {
 741          self::__construct( $base, $age );
 742      }
 743  
 744  /*=======================================================================*\
 745      Function:    set
 746      Purpose:    add an item to the cache, keyed on url
 747      Input:        url from which the rss file was fetched
 748      Output:        true on success
 749  \*=======================================================================*/
 750  	function set ($url, $rss) {
 751          $cache_option = 'rss_' . $this->file_name( $url );
 752  
 753          set_transient($cache_option, $rss, $this->MAX_AGE);
 754  
 755          return $cache_option;
 756      }
 757  
 758  /*=======================================================================*\
 759      Function:    get
 760      Purpose:    fetch an item from the cache
 761      Input:        url from which the rss file was fetched
 762      Output:        cached object on HIT, false on MISS
 763  \*=======================================================================*/
 764  	function get ($url) {
 765          $this->ERROR = "";
 766          $cache_option = 'rss_' . $this->file_name( $url );
 767  
 768          if ( ! $rss = get_transient( $cache_option ) ) {
 769              $this->debug(
 770                  "Cache does not contain: $url (cache option: $cache_option)"
 771              );
 772              return 0;
 773          }
 774  
 775          return $rss;
 776      }
 777  
 778  /*=======================================================================*\
 779      Function:    check_cache
 780      Purpose:    check a url for membership in the cache
 781                  and whether the object is older then MAX_AGE (ie. STALE)
 782      Input:        url from which the rss file was fetched
 783      Output:        cached object on HIT, false on MISS
 784  \*=======================================================================*/
 785  	function check_cache ( $url ) {
 786          $this->ERROR = "";
 787          $cache_option = 'rss_' . $this->file_name( $url );
 788  
 789          if ( get_transient($cache_option) ) {
 790              // object exists and is current
 791                  return 'HIT';
 792          } else {
 793              // object does not exist
 794              return 'MISS';
 795          }
 796      }
 797  
 798  /*=======================================================================*\
 799      Function:    serialize
 800  \*=======================================================================*/
 801  	function serialize ( $rss ) {
 802          return serialize( $rss );
 803      }
 804  
 805  /*=======================================================================*\
 806      Function:    unserialize
 807  \*=======================================================================*/
 808  	function unserialize ( $data ) {
 809          return unserialize( $data );
 810      }
 811  
 812  /*=======================================================================*\
 813      Function:    file_name
 814      Purpose:    map url to location in cache
 815      Input:        url from which the rss file was fetched
 816      Output:        a file name
 817  \*=======================================================================*/
 818  	function file_name ($url) {
 819          return md5( $url );
 820      }
 821  
 822  /*=======================================================================*\
 823      Function:    error
 824      Purpose:    register error
 825  \*=======================================================================*/
 826  	function error ($errormsg, $lvl=E_USER_WARNING) {
 827          $this->ERROR = $errormsg;
 828          if ( MAGPIE_DEBUG ) {
 829              wp_trigger_error( '', $errormsg, $lvl);
 830          }
 831          else {
 832              error_log( $errormsg, 0);
 833          }
 834      }
 835  			function debug ($debugmsg, $lvl=E_USER_NOTICE) {
 836          if ( MAGPIE_DEBUG ) {
 837              $this->error("MagpieRSS [debug] $debugmsg", $lvl);
 838          }
 839      }
 840  }
 841  
 842  if ( !function_exists('parse_w3cdtf') ) :
 843  function parse_w3cdtf ( $date_str ) {
 844  
 845      # regex to match W3C date/time formats
 846      $pat = "/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/";
 847  
 848      if ( preg_match( $pat, $date_str, $match ) ) {
 849          list( $year, $month, $day, $hours, $minutes, $seconds) =
 850              array( $match[1], $match[2], $match[3], $match[4], $match[5], $match[7]);
 851  
 852          # calc epoch for current date assuming GMT
 853          $epoch = gmmktime( $hours, $minutes, $seconds, $month, $day, $year);
 854  
 855          $offset = 0;
 856          if ( $match[11] == 'Z' ) {
 857              # zulu time, aka GMT
 858          }
 859          else {
 860              list( $tz_mod, $tz_hour, $tz_min ) =
 861                  array( $match[8], $match[9], $match[10]);
 862  
 863              # zero out the variables
 864              if ( ! $tz_hour ) { $tz_hour = 0; }
 865              if ( ! $tz_min ) { $tz_min = 0; }
 866  
 867              $offset_secs = (($tz_hour*60)+$tz_min)*60;
 868  
 869              # is timezone ahead of GMT?  then subtract offset
 870              #
 871              if ( $tz_mod == '+' ) {
 872                  $offset_secs = $offset_secs * -1;
 873              }
 874  
 875              $offset = $offset_secs;
 876          }
 877          $epoch = $epoch + $offset;
 878          return $epoch;
 879      }
 880      else {
 881          return -1;
 882      }
 883  }
 884  endif;
 885  
 886  if ( !function_exists('wp_rss') ) :
 887  /**
 888   * Display all RSS items in a HTML ordered list.
 889   *
 890   * @since 1.5.0
 891   * @package External
 892   * @subpackage MagpieRSS
 893   *
 894   * @param string $url URL of feed to display. Will not auto sense feed URL.
 895   * @param int $num_items Optional. Number of items to display, default is all.
 896   */
 897  function wp_rss( $url, $num_items = -1 ) {
 898      if ( $rss = fetch_rss( $url ) ) {
 899          echo '<ul>';
 900  
 901          if ( $num_items !== -1 ) {
 902              $rss->items = array_slice( $rss->items, 0, $num_items );
 903          }
 904  
 905          foreach ( (array) $rss->items as $item ) {
 906              printf(
 907                  '<li><a href="%1$s" title="%2$s">%3$s</a></li>',
 908                  esc_url( $item['link'] ),
 909                  esc_attr( strip_tags( $item['description'] ) ),
 910                  esc_html( $item['title'] )
 911              );
 912          }
 913  
 914          echo '</ul>';
 915      } else {
 916          _e( 'An error has occurred, which probably means the feed is down. Try again later.' );
 917      }
 918  }
 919  endif;
 920  
 921  if ( !function_exists('get_rss') ) :
 922  /**
 923   * Display RSS items in HTML list items.
 924   *
 925   * You have to specify which HTML list you want, either ordered or unordered
 926   * before using the function. You also have to specify how many items you wish
 927   * to display. You can't display all of them like you can with wp_rss()
 928   * function.
 929   *
 930   * @since 1.5.0
 931   * @package External
 932   * @subpackage MagpieRSS
 933   *
 934   * @param string $url URL of feed to display. Will not auto sense feed URL.
 935   * @param int $num_items Optional. Number of items to display, default is all.
 936   * @return bool False on failure.
 937   */
 938  function get_rss ($url, $num_items = 5) { // Like get posts, but for RSS
 939      $rss = fetch_rss($url);
 940      if ( $rss ) {
 941          $rss->items = array_slice($rss->items, 0, $num_items);
 942          foreach ( (array) $rss->items as $item ) {
 943              echo "<li>\n";
 944              echo "<a href='$item[link]' title='$item[description]'>";
 945              echo esc_html($item['title']);
 946              echo "</a><br />\n";
 947              echo "</li>\n";
 948          }
 949      } else {
 950          return false;
 951      }
 952  }
 953  endif;


Generated : Sat Sep 13 08:20:04 2025 Cross-referenced by PHPXref