home *** CD-ROM | disk | FTP | other *** search
/ HTML Examples / WP.iso / wordpress / wp-includes / feed.php < prev    next >
Encoding:
PHP Script  |  2017-11-29  |  19.1 KB  |  711 lines

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