[ Index ]

PHP Cross Reference of WordPress

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


Generated: Thu Apr 25 01:00:03 2024 Cross-referenced by PHPXref 0.7.1