WordPress.org

Make WordPress Core

Ticket #44838: 44838.1.diff

File 44838.1.diff, 19.2 KB (added by mobeen-abdullah, 14 months ago)

First patch as a new contributor :)

Line 
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 */
26function 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 */
54function 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 */
78function 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 */
100function get_wp_title_rss( $deprecated = '&#8211;' ) {
101        if ( '&#8211;' !== $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 */
126function wp_title_rss( $deprecated = '&#8211;' ) {
127        if ( '&#8211;' !== $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 */
153function 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 */
172function 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 */
185function 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(']]>', ']]&gt;', $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 */
211function 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 */
220function 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 */
237function 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 */
254function 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 */
273function 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 */
285function 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 */
302function 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 */
322function 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 */
340function 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 */
349function 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 */
374function 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 */
425function 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 */
436function 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 */
459function 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 */
498function 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 */
536function 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 */
575function 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 */
587function 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 */
613function self_link( $echo = true ) {
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        $current_feed_url = esc_url( apply_filters( 'self_link', set_url_scheme( 'http://' . $host['host'] . wp_unslash( $_SERVER['REQUEST_URI'] ) ) ) );
626
627        if ( $echo === true ) {
628                echo $current_feed_url;
629        } else {
630                return $current_feed_url;
631        }
632}
633
634/**
635 * Return the content type for specified feed type.
636 *
637 * @since 2.8.0
638 *
639 * @param string $type Type of feed. Possible values include 'rss', rss2', 'atom', and 'rdf'.
640 */
641function feed_content_type( $type = '' ) {
642        if ( empty($type) )
643                $type = get_default_feed();
644
645        $types = array(
646                'rss'      => 'application/rss+xml',
647                'rss2'     => 'application/rss+xml',
648                'rss-http' => 'text/xml',
649                'atom'     => 'application/atom+xml',
650                'rdf'      => 'application/rdf+xml'
651        );
652
653        $content_type = ( !empty($types[$type]) ) ? $types[$type] : 'application/octet-stream';
654
655        /**
656         * Filters the content type for a specific feed type.
657         *
658         * @since 2.8.0
659         *
660         * @param string $content_type Content type indicating the type of data that a feed contains.
661         * @param string $type         Type of feed. Possible values include 'rss', rss2', 'atom', and 'rdf'.
662         */
663        return apply_filters( 'feed_content_type', $content_type, $type );
664}
665
666/**
667 * Build SimplePie object based on RSS or Atom feed from URL.
668 *
669 * @since 2.8.0
670 *
671 * @param mixed $url URL of feed to retrieve. If an array of URLs, the feeds are merged
672 * using SimplePie's multifeed feature.
673 * See also {@link ​http://simplepie.org/wiki/faq/typical_multifeed_gotchas}
674 *
675 * @return WP_Error|SimplePie WP_Error object on failure or SimplePie object on success
676 */
677function fetch_feed( $url ) {
678        if ( ! class_exists( 'SimplePie', false ) ) {
679                require_once( ABSPATH . WPINC . '/class-simplepie.php' );
680        }
681
682        require_once( ABSPATH . WPINC . '/class-wp-feed-cache.php' );
683        require_once( ABSPATH . WPINC . '/class-wp-feed-cache-transient.php' );
684        require_once( ABSPATH . WPINC . '/class-wp-simplepie-file.php' );
685        require_once( ABSPATH . WPINC . '/class-wp-simplepie-sanitize-kses.php' );
686
687        $feed = new SimplePie();
688
689        $feed->set_sanitize_class( 'WP_SimplePie_Sanitize_KSES' );
690        // We must manually overwrite $feed->sanitize because SimplePie's
691        // constructor sets it before we have a chance to set the sanitization class
692        $feed->sanitize = new WP_SimplePie_Sanitize_KSES();
693
694        $feed->set_cache_class( 'WP_Feed_Cache' );
695        $feed->set_file_class( 'WP_SimplePie_File' );
696
697        $feed->set_feed_url( $url );
698        /** This filter is documented in wp-includes/class-wp-feed-cache-transient.php */
699        $feed->set_cache_duration( apply_filters( 'wp_feed_cache_transient_lifetime', 12 * HOUR_IN_SECONDS, $url ) );
700        /**
701         * Fires just before processing the SimplePie feed object.
702         *
703         * @since 3.0.0
704         *
705         * @param object $feed SimplePie feed object (passed by reference).
706         * @param mixed  $url  URL of feed to retrieve. If an array of URLs, the feeds are merged.
707         */
708        do_action_ref_array( 'wp_feed_options', array( &$feed, $url ) );
709        $feed->init();
710        $feed->set_output_encoding( get_option( 'blog_charset' ) );
711
712        if ( $feed->error() )
713                return new WP_Error( 'simplepie-error', $feed->error() );
714
715        return $feed;
716}