/wp-includes/feed.php

  1. <?php 
  2. /** 
  3. * WordPress Feed API 
  4. * 
  5. * Many of the functions used in here belong in The Loop, or The Loop for the 
  6. * Feeds. 
  7. * 
  8. * @package WordPress 
  9. * @subpackage Feed 
  10. * @since 2.1.0 
  11. */ 
  12.  
  13. /** 
  14. * RSS container for the bloginfo function. 
  15. * 
  16. * You can retrieve anything that you can using the get_bloginfo() function. 
  17. * Everything will be stripped of tags and characters converted, when the values 
  18. * are retrieved for use in the feeds. 
  19. * 
  20. * @since 1.5.1 
  21. * @see get_bloginfo() For the list of possible values to display. 
  22. * 
  23. * @param string $show See get_bloginfo() for possible values. 
  24. * @return string 
  25. */ 
  26. function get_bloginfo_rss($show = '') { 
  27. $info = strip_tags(get_bloginfo($show)); 
  28. /** 
  29. * Filters the bloginfo for use in RSS feeds. 
  30. * 
  31. * @since 2.2.0 
  32. * 
  33. * @see convert_chars() 
  34. * @see get_bloginfo() 
  35. * 
  36. * @param string $info Converted string value of the blog information. 
  37. * @param string $show The type of blog information to retrieve. 
  38. */ 
  39. return apply_filters( 'get_bloginfo_rss', convert_chars( $info ), $show ); 
  40.  
  41. /** 
  42. * Display RSS container for the bloginfo function. 
  43. * 
  44. * You can retrieve anything that you can using the get_bloginfo() function. 
  45. * Everything will be stripped of tags and characters converted, when the values 
  46. * are retrieved for use in the feeds. 
  47. * 
  48. * @since 0.71 
  49. * @see get_bloginfo() For the list of possible values to display. 
  50. * 
  51. * @param string $show See get_bloginfo() for possible values. 
  52. */ 
  53. function bloginfo_rss($show = '') { 
  54. /** 
  55. * Filters the bloginfo for display in RSS feeds. 
  56. * 
  57. * @since 2.1.0 
  58. * 
  59. * @see get_bloginfo() 
  60. * 
  61. * @param string $rss_container RSS container for the blog information. 
  62. * @param string $show The type of blog information to retrieve. 
  63. */ 
  64. echo apply_filters( 'bloginfo_rss', get_bloginfo_rss( $show ), $show ); 
  65.  
  66. /** 
  67. * Retrieve the default feed. 
  68. * 
  69. * The default feed is 'rss2', unless a plugin changes it through the 
  70. * {@see 'default_feed'} filter. 
  71. * 
  72. * @since 2.5.0 
  73. * 
  74. * @return string Default feed, or for example 'rss2', 'atom', etc. 
  75. */ 
  76. function get_default_feed() { 
  77. /** 
  78. * Filters the default feed type. 
  79. * 
  80. * @since 2.5.0 
  81. * 
  82. * @param string $feed_type Type of default feed. Possible values include 'rss2', 'atom'. 
  83. * Default 'rss2'. 
  84. */ 
  85. $default_feed = apply_filters( 'default_feed', 'rss2' ); 
  86. return 'rss' == $default_feed ? 'rss2' : $default_feed; 
  87.  
  88. /** 
  89. * Retrieve the blog title for the feed title. 
  90. * 
  91. * @since 2.2.0 
  92. * @since 4.4.0 The optional `$sep` parameter was deprecated and renamed to `$deprecated`. 
  93. * 
  94. * @param string $deprecated Unused.. 
  95. * @return string The document title. 
  96. */ 
  97. function get_wp_title_rss( $deprecated = '–' ) { 
  98. if ( '–' !== $deprecated ) { 
  99. /** translators: %s: 'document_title_separator' filter name */ 
  100. _deprecated_argument( __FUNCTION__, '4.4.0', sprintf( __( 'Use the %s filter instead.' ), '<code>document_title_separator</code>' ) ); 
  101.  
  102. /** 
  103. * Filters the blog title for use as the feed title. 
  104. * 
  105. * @since 2.2.0 
  106. * @since 4.4.0 The `$sep` parameter was deprecated and renamed to `$deprecated`. 
  107. * 
  108. * @param string $title The current blog title. 
  109. * @param string $deprecated Unused. 
  110. */ 
  111. return apply_filters( 'get_wp_title_rss', wp_get_document_title(), $deprecated ); 
  112.  
  113. /** 
  114. * Display the blog title for display of the feed title. 
  115. * 
  116. * @since 2.2.0 
  117. * @since 4.4.0 The optional `$sep` parameter was deprecated and renamed to `$deprecated`. 
  118. * 
  119. * @param string $deprecated Unused. 
  120. */ 
  121. function wp_title_rss( $deprecated = '–' ) { 
  122. if ( '–' !== $deprecated ) { 
  123. /** translators: %s: 'document_title_separator' filter name */ 
  124. _deprecated_argument( __FUNCTION__, '4.4.0', sprintf( __( 'Use the %s filter instead.' ), '<code>document_title_separator</code>' ) ); 
  125.  
  126. /** 
  127. * Filters the blog title for display of the feed title. 
  128. * 
  129. * @since 2.2.0 
  130. * @since 4.4.0 The `$sep` parameter was deprecated and renamed to `$deprecated`. 
  131. * 
  132. * @see get_wp_title_rss() 
  133. * 
  134. * @param string $wp_title_rss The current blog title. 
  135. * @param string $deprecated Unused. 
  136. */ 
  137. echo apply_filters( 'wp_title_rss', get_wp_title_rss(), $deprecated ); 
  138.  
  139. /** 
  140. * Retrieve the current post title for the feed. 
  141. * 
  142. * @since 2.0.0 
  143. * 
  144. * @return string Current post title. 
  145. */ 
  146. function get_the_title_rss() { 
  147. $title = get_the_title(); 
  148.  
  149. /** 
  150. * Filters the post title for use in a feed. 
  151. * 
  152. * @since 1.2.0 
  153. * 
  154. * @param string $title The current post title. 
  155. */ 
  156. $title = apply_filters( 'the_title_rss', $title ); 
  157. return $title; 
  158.  
  159. /** 
  160. * Display the post title in the feed. 
  161. * 
  162. * @since 0.71 
  163. */ 
  164. function the_title_rss() { 
  165. echo get_the_title_rss(); 
  166.  
  167. /** 
  168. * Retrieve the post content for feeds. 
  169. * 
  170. * @since 2.9.0 
  171. * @see get_the_content() 
  172. * 
  173. * @param string $feed_type The type of feed. rss2 | atom | rss | rdf 
  174. * @return string The filtered content. 
  175. */ 
  176. function get_the_content_feed($feed_type = null) { 
  177. if ( !$feed_type ) 
  178. $feed_type = get_default_feed(); 
  179.  
  180. /** This filter is documented in wp-includes/post-template.php */ 
  181. $content = apply_filters( 'the_content', get_the_content() ); 
  182. $content = str_replace(']]>', ']]>', $content); 
  183. /** 
  184. * Filters the post content for use in feeds. 
  185. * 
  186. * @since 2.9.0 
  187. * 
  188. * @param string $content The current post content. 
  189. * @param string $feed_type Type of feed. Possible values include 'rss2', 'atom'. 
  190. * Default 'rss2'. 
  191. */ 
  192. return apply_filters( 'the_content_feed', $content, $feed_type ); 
  193.  
  194. /** 
  195. * Display the post content for feeds. 
  196. * 
  197. * @since 2.9.0 
  198. * 
  199. * @param string $feed_type The type of feed. rss2 | atom | rss | rdf 
  200. */ 
  201. function the_content_feed($feed_type = null) { 
  202. echo get_the_content_feed($feed_type); 
  203.  
  204. /** 
  205. * Display the post excerpt for the feed. 
  206. * 
  207. * @since 0.71 
  208. */ 
  209. function the_excerpt_rss() { 
  210. $output = get_the_excerpt(); 
  211. /** 
  212. * Filters the post excerpt for a feed. 
  213. * 
  214. * @since 1.2.0 
  215. * 
  216. * @param string $output The current post excerpt. 
  217. */ 
  218. echo apply_filters( 'the_excerpt_rss', $output ); 
  219.  
  220. /** 
  221. * Display the permalink to the post for use in feeds. 
  222. * 
  223. * @since 2.3.0 
  224. */ 
  225. function the_permalink_rss() { 
  226. /** 
  227. * Filters the permalink to the post for use in feeds. 
  228. * 
  229. * @since 2.3.0 
  230. * 
  231. * @param string $post_permalink The current post permalink. 
  232. */ 
  233. echo esc_url( apply_filters( 'the_permalink_rss', get_permalink() ) ); 
  234.  
  235. /** 
  236. * Outputs the link to the comments for the current post in an xml safe way 
  237. * 
  238. * @since 3.0.0 
  239. * @return none 
  240. */ 
  241. function comments_link_feed() { 
  242. /** 
  243. * Filters the comments permalink for the current post. 
  244. * 
  245. * @since 3.6.0 
  246. * 
  247. * @param string $comment_permalink The current comment permalink with 
  248. * '#comments' appended. 
  249. */ 
  250. echo esc_url( apply_filters( 'comments_link_feed', get_comments_link() ) ); 
  251.  
  252. /** 
  253. * Display the feed GUID for the current comment. 
  254. * 
  255. * @since 2.5.0 
  256. * 
  257. * @param int|WP_Comment $comment_id Optional comment object or id. Defaults to global comment object. 
  258. */ 
  259. function comment_guid($comment_id = null) { 
  260. echo esc_url( get_comment_guid($comment_id) ); 
  261.  
  262. /** 
  263. * Retrieve the feed GUID for the current comment. 
  264. * 
  265. * @since 2.5.0 
  266. * 
  267. * @param int|WP_Comment $comment_id Optional comment object or id. Defaults to global comment object. 
  268. * @return false|string false on failure or guid for comment on success. 
  269. */ 
  270. function get_comment_guid($comment_id = null) { 
  271. $comment = get_comment($comment_id); 
  272.  
  273. if ( !is_object($comment) ) 
  274. return false; 
  275.  
  276. return get_the_guid($comment->comment_post_ID) . '#comment-' . $comment->comment_ID; 
  277.  
  278. /** 
  279. * Display the link to the comments. 
  280. * 
  281. * @since 1.5.0 
  282. * @since 4.4.0 Introduced the `$comment` argument. 
  283. * 
  284. * @param int|WP_Comment $comment Optional. Comment object or id. Defaults to global comment object. 
  285. */ 
  286. function comment_link( $comment = null ) { 
  287. /** 
  288. * Filters the current comment's permalink. 
  289. * 
  290. * @since 3.6.0 
  291. * 
  292. * @see get_comment_link() 
  293. * 
  294. * @param string $comment_permalink The current comment permalink. 
  295. */ 
  296. echo esc_url( apply_filters( 'comment_link', get_comment_link( $comment ) ) ); 
  297.  
  298. /** 
  299. * Retrieve the current comment author for use in the feeds. 
  300. * 
  301. * @since 2.0.0 
  302. * 
  303. * @return string Comment Author 
  304. */ 
  305. function get_comment_author_rss() { 
  306. /** 
  307. * Filters the current comment author for use in a feed. 
  308. * 
  309. * @since 1.5.0 
  310. * 
  311. * @see get_comment_author() 
  312. * 
  313. * @param string $comment_author The current comment author. 
  314. */ 
  315. return apply_filters( 'comment_author_rss', get_comment_author() ); 
  316.  
  317. /** 
  318. * Display the current comment author in the feed. 
  319. * 
  320. * @since 1.0.0 
  321. */ 
  322. function comment_author_rss() { 
  323. echo get_comment_author_rss(); 
  324.  
  325. /** 
  326. * Display the current comment content for use in the feeds. 
  327. * 
  328. * @since 1.0.0 
  329. */ 
  330. function comment_text_rss() { 
  331. $comment_text = get_comment_text(); 
  332. /** 
  333. * Filters the current comment content for use in a feed. 
  334. * 
  335. * @since 1.5.0 
  336. * 
  337. * @param string $comment_text The content of the current comment. 
  338. */ 
  339. $comment_text = apply_filters( 'comment_text_rss', $comment_text ); 
  340. echo $comment_text; 
  341.  
  342. /** 
  343. * Retrieve all of the post categories, formatted for use in feeds. 
  344. * 
  345. * All of the categories for the current post in the feed loop, will be 
  346. * retrieved and have feed markup added, so that they can easily be added to the 
  347. * RSS2, Atom, or RSS1 and RSS0.91 RDF feeds. 
  348. * 
  349. * @since 2.1.0 
  350. * 
  351. * @param string $type Optional, default is the type returned by get_default_feed(). 
  352. * @return string All of the post categories for displaying in the feed. 
  353. */ 
  354. function get_the_category_rss($type = null) { 
  355. if ( empty($type) ) 
  356. $type = get_default_feed(); 
  357. $categories = get_the_category(); 
  358. $tags = get_the_tags(); 
  359. $the_list = ''; 
  360. $cat_names = array(); 
  361.  
  362. $filter = 'rss'; 
  363. if ( 'atom' == $type ) 
  364. $filter = 'raw'; 
  365.  
  366. if ( !empty($categories) ) foreach ( (array) $categories as $category ) { 
  367. $cat_names[] = sanitize_term_field('name', $category->name, $category->term_id, 'category', $filter); 
  368.  
  369. if ( !empty($tags) ) foreach ( (array) $tags as $tag ) { 
  370. $cat_names[] = sanitize_term_field('name', $tag->name, $tag->term_id, 'post_tag', $filter); 
  371.  
  372. $cat_names = array_unique($cat_names); 
  373.  
  374. foreach ( $cat_names as $cat_name ) { 
  375. if ( 'rdf' == $type ) 
  376. $the_list .= "\t\t<dc:subject><![CDATA[$cat_name]]></dc:subject>\n"; 
  377. elseif ( 'atom' == $type ) 
  378. $the_list .= sprintf( '<category scheme="%1$s" term="%2$s" />', esc_attr( get_bloginfo_rss( 'url' ) ), esc_attr( $cat_name ) ); 
  379. else 
  380. $the_list .= "\t\t<category><![CDATA[" . @html_entity_decode( $cat_name, ENT_COMPAT, get_option('blog_charset') ) . "]]></category>\n"; 
  381.  
  382. /** 
  383. * Filters all of the post categories for display in a feed. 
  384. * 
  385. * @since 1.2.0 
  386. * 
  387. * @param string $the_list All of the RSS post categories. 
  388. * @param string $type Type of feed. Possible values include 'rss2', 'atom'. 
  389. * Default 'rss2'. 
  390. */ 
  391. return apply_filters( 'the_category_rss', $the_list, $type ); 
  392.  
  393. /** 
  394. * Display the post categories in the feed. 
  395. * 
  396. * @since 0.71 
  397. * @see get_the_category_rss() For better explanation. 
  398. * 
  399. * @param string $type Optional, default is the type returned by get_default_feed(). 
  400. */ 
  401. function the_category_rss($type = null) { 
  402. echo get_the_category_rss($type); 
  403.  
  404. /** 
  405. * Display the HTML type based on the blog setting. 
  406. * 
  407. * The two possible values are either 'xhtml' or 'html'. 
  408. * 
  409. * @since 2.2.0 
  410. */ 
  411. function html_type_rss() { 
  412. $type = get_bloginfo('html_type'); 
  413. if (strpos($type, 'xhtml') !== false) 
  414. $type = 'xhtml'; 
  415. else 
  416. $type = 'html'; 
  417. echo $type; 
  418.  
  419. /** 
  420. * Display the rss enclosure for the current post. 
  421. * 
  422. * Uses the global $post to check whether the post requires a password and if 
  423. * the user has the password for the post. If not then it will return before 
  424. * displaying. 
  425. * 
  426. * Also uses the function get_post_custom() to get the post's 'enclosure' 
  427. * metadata field and parses the value to display the enclosure(s). The 
  428. * enclosure(s) consist of enclosure HTML tag(s) with a URI and other 
  429. * attributes. 
  430. * 
  431. * @since 1.5.0 
  432. */ 
  433. function rss_enclosure() { 
  434. if ( post_password_required() ) 
  435. return; 
  436.  
  437. foreach ( (array) get_post_custom() as $key => $val) { 
  438. if ($key == 'enclosure') { 
  439. foreach ( (array) $val as $enc ) { 
  440. $enclosure = explode("\n", $enc); 
  441.  
  442. // only get the first element, e.g. audio/mpeg from 'audio/mpeg mpga mp2 mp3' 
  443. $t = preg_split('/[ \t]/', trim($enclosure[2]) ); 
  444. $type = $t[0]; 
  445.  
  446. /** 
  447. * Filters the RSS enclosure HTML link tag for the current post. 
  448. * 
  449. * @since 2.2.0 
  450. * 
  451. * @param string $html_link_tag The HTML link tag with a URI and other attributes. 
  452. */ 
  453. echo apply_filters( 'rss_enclosure', '<enclosure url="' . trim( htmlspecialchars( $enclosure[0] ) ) . '" length="' . trim( $enclosure[1] ) . '" type="' . $type . '" />' . "\n" ); 
  454.  
  455. /** 
  456. * Display the atom enclosure for the current post. 
  457. * 
  458. * Uses the global $post to check whether the post requires a password and if 
  459. * the user has the password for the post. If not then it will return before 
  460. * displaying. 
  461. * 
  462. * Also uses the function get_post_custom() to get the post's 'enclosure' 
  463. * metadata field and parses the value to display the enclosure(s). The 
  464. * enclosure(s) consist of link HTML tag(s) with a URI and other attributes. 
  465. * 
  466. * @since 2.2.0 
  467. */ 
  468. function atom_enclosure() { 
  469. if ( post_password_required() ) 
  470. return; 
  471.  
  472. foreach ( (array) get_post_custom() as $key => $val ) { 
  473. if ($key == 'enclosure') { 
  474. foreach ( (array) $val as $enc ) { 
  475. $enclosure = explode("\n", $enc); 
  476. /** 
  477. * Filters the atom enclosure HTML link tag for the current post. 
  478. * 
  479. * @since 2.2.0 
  480. * 
  481. * @param string $html_link_tag The HTML link tag with a URI and other attributes. 
  482. */ 
  483. echo apply_filters( 'atom_enclosure', '<link href="' . trim( htmlspecialchars( $enclosure[0] ) ) . '" rel="enclosure" length="' . trim( $enclosure[1] ) . '" type="' . trim( $enclosure[2] ) . '" />' . "\n" ); 
  484.  
  485. /** 
  486. * Determine the type of a string of data with the data formatted. 
  487. * 
  488. * Tell whether the type is text, html, or xhtml, per RFC 4287 section 3.1. 
  489. * 
  490. * In the case of WordPress, text is defined as containing no markup,  
  491. * xhtml is defined as "well formed", and html as tag soup (i.e., the rest). 
  492. * 
  493. * Container div tags are added to xhtml values, per section 3.1.1.3. 
  494. * 
  495. * @link http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rfc.section.3.1 
  496. * 
  497. * @since 2.5.0 
  498. * 
  499. * @param string $data Input string 
  500. * @return array array(type, value) 
  501. */ 
  502. function prep_atom_text_construct($data) { 
  503. if (strpos($data, '<') === false && strpos($data, '&') === false) { 
  504. return array('text', $data); 
  505.  
  506. if ( ! function_exists( 'xml_parser_create' ) ) { 
  507. trigger_error( __( "PHP's XML extension is not available. Please contact your hosting provider to enable PHP's XML extension." ) ); 
  508.  
  509. return array( 'html', "<![CDATA[$data]]>" ); 
  510.  
  511. $parser = xml_parser_create(); 
  512. xml_parse($parser, '<div>' . $data . '</div>', true); 
  513. $code = xml_get_error_code($parser); 
  514. xml_parser_free($parser); 
  515.  
  516. if (!$code) { 
  517. if (strpos($data, '<') === false) { 
  518. return array('text', $data); 
  519. } else { 
  520. $data = "<div xmlns='http://www.w3.org/1999/xhtml'>$data</div>"; 
  521. return array('xhtml', $data); 
  522.  
  523. if (strpos($data, ']]>') === false) { 
  524. return array('html', "<![CDATA[$data]]>"); 
  525. } else { 
  526. return array('html', htmlspecialchars($data)); 
  527.  
  528. /** 
  529. * Displays Site Icon in atom feeds. 
  530. * 
  531. * @since 4.3.0 
  532. * 
  533. * @see get_site_icon_url() 
  534. */ 
  535. function atom_site_icon() { 
  536. $url = get_site_icon_url( 32 ); 
  537. if ( $url ) { 
  538. echo "<icon>$url</icon>\n"; 
  539.  
  540. /** 
  541. * Displays Site Icon in RSS2. 
  542. * 
  543. * @since 4.3.0 
  544. */ 
  545. function rss2_site_icon() { 
  546. $rss_title = get_wp_title_rss(); 
  547. if ( empty( $rss_title ) ) { 
  548. $rss_title = get_bloginfo_rss( 'name' ); 
  549.  
  550. $url = get_site_icon_url( 32 ); 
  551. if ( $url ) { 
  552. echo ' 
  553. <image> 
  554. <url>' . convert_chars( $url ) . '</url> 
  555. <title>' . $rss_title . '</title> 
  556. <link>' . get_bloginfo_rss( 'url' ) . '</link> 
  557. <width>32</width> 
  558. <height>32</height> 
  559. </image> ' . "\n"; 
  560.  
  561. /** 
  562. * Display the link for the currently displayed feed in a XSS safe way. 
  563. * 
  564. * Generate a correct link for the atom:self element. 
  565. * 
  566. * @since 2.5.0 
  567. */ 
  568. function self_link() { 
  569. $host = @parse_url(home_url()); 
  570. /** 
  571. * Filters the current feed URL. 
  572. * 
  573. * @since 3.6.0 
  574. * 
  575. * @see set_url_scheme() 
  576. * @see wp_unslash() 
  577. * 
  578. * @param string $feed_link The link for the feed with set URL scheme. 
  579. */ 
  580. echo esc_url( apply_filters( 'self_link', set_url_scheme( 'http://' . $host['host'] . wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) ); 
  581.  
  582. /** 
  583. * Return the content type for specified feed type. 
  584. * 
  585. * @since 2.8.0 
  586. * 
  587. * @param string $type Type of feed. Possible values include 'rss', rss2', 'atom', and 'rdf'. 
  588. */ 
  589. function feed_content_type( $type = '' ) { 
  590. if ( empty($type) ) 
  591. $type = get_default_feed(); 
  592.  
  593. $types = array( 
  594. 'rss' => 'application/rss+xml',  
  595. 'rss2' => 'application/rss+xml',  
  596. 'rss-http' => 'text/xml',  
  597. 'atom' => 'application/atom+xml',  
  598. 'rdf' => 'application/rdf+xml' 
  599. ); 
  600.  
  601. $content_type = ( !empty($types[$type]) ) ? $types[$type] : 'application/octet-stream'; 
  602.  
  603. /** 
  604. * Filters the content type for a specific feed type. 
  605. * 
  606. * @since 2.8.0 
  607. * 
  608. * @param string $content_type Content type indicating the type of data that a feed contains. 
  609. * @param string $type Type of feed. Possible values include 'rss', rss2', 'atom', and 'rdf'. 
  610. */ 
  611. return apply_filters( 'feed_content_type', $content_type, $type ); 
  612.  
  613. /** 
  614. * Build SimplePie object based on RSS or Atom feed from URL. 
  615. * 
  616. * @since 2.8.0 
  617. * 
  618. * @param mixed $url URL of feed to retrieve. If an array of URLs, the feeds are merged 
  619. * using SimplePie's multifeed feature. 
  620. * See also {@link *http://simplepie.org/wiki/faq/typical_multifeed_gotchas} 
  621. * 
  622. * @return WP_Error|SimplePie WP_Error object on failure or SimplePie object on success 
  623. */ 
  624. function fetch_feed( $url ) { 
  625. if ( ! class_exists( 'SimplePie', false ) ) { 
  626. require_once( ABSPATH . WPINC . '/class-simplepie.php' ); 
  627.  
  628. require_once( ABSPATH . WPINC . '/class-wp-feed-cache.php' ); 
  629. require_once( ABSPATH . WPINC . '/class-wp-feed-cache-transient.php' ); 
  630. require_once( ABSPATH . WPINC . '/class-wp-simplepie-file.php' ); 
  631. require_once( ABSPATH . WPINC . '/class-wp-simplepie-sanitize-kses.php' ); 
  632.  
  633. $feed = new SimplePie(); 
  634.  
  635. $feed->set_sanitize_class( 'WP_SimplePie_Sanitize_KSES' ); 
  636. // We must manually overwrite $feed->sanitize because SimplePie's 
  637. // constructor sets it before we have a chance to set the sanitization class 
  638. $feed->sanitize = new WP_SimplePie_Sanitize_KSES(); 
  639.  
  640. $feed->set_cache_class( 'WP_Feed_Cache' ); 
  641. $feed->set_file_class( 'WP_SimplePie_File' ); 
  642.  
  643. $feed->set_feed_url( $url ); 
  644. /** This filter is documented in wp-includes/class-wp-feed-cache-transient.php */ 
  645. $feed->set_cache_duration( apply_filters( 'wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url ) ); 
  646. /** 
  647. * Fires just before processing the SimplePie feed object. 
  648. * 
  649. * @since 3.0.0 
  650. * 
  651. * @param object &$feed SimplePie feed object, passed by reference. 
  652. * @param mixed $url URL of feed to retrieve. If an array of URLs, the feeds are merged. 
  653. */ 
  654. do_action_ref_array( 'wp_feed_options', array( &$feed, $url ) ); 
  655. $feed->init(); 
  656. $feed->set_output_encoding( get_option( 'blog_charset' ) ); 
  657.  
  658. if ( $feed->error() ) 
  659. return new WP_Error( 'simplepie-error', $feed->error() ); 
  660.  
  661. return $feed; 
.