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


Generated: Fri May 25 03:56:23 2012 Hosted by follow the white rabbit.