[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Sat Sep 13 08:20:04 2025 | Cross-referenced by PHPXref |