Wordpress 2.9.2-scripts
[autoinstalls/wordpress.git] / 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  */
11
12 /**
13  * RSS container for the bloginfo function.
14  *
15  * You can retrieve anything that you can using the get_bloginfo() function.
16  * Everything will be stripped of tags and characters converted, when the values
17  * are retrieved for use in the feeds.
18  *
19  * @package WordPress
20  * @subpackage Feed
21  * @since 1.5.1
22  * @uses apply_filters() Calls 'get_bloginfo_rss' hook with two parameters.
23  * @see get_bloginfo() For the list of possible values to display.
24  *
25  * @param string $show See get_bloginfo() for possible values.
26  * @return string
27  */
28 function get_bloginfo_rss($show = '') {
29         $info = strip_tags(get_bloginfo($show));
30         return apply_filters('get_bloginfo_rss', convert_chars($info), $show);
31 }
32
33 /**
34  * Display RSS container for the bloginfo function.
35  *
36  * You can retrieve anything that you can using the get_bloginfo() function.
37  * Everything will be stripped of tags and characters converted, when the values
38  * are retrieved for use in the feeds.
39  *
40  * @package WordPress
41  * @subpackage Feed
42  * @since 0.71
43  * @uses apply_filters() Calls 'bloginfo_rss' hook with two parameters.
44  * @see get_bloginfo() For the list of possible values to display.
45  *
46  * @param string $show See get_bloginfo() for possible values.
47  */
48 function bloginfo_rss($show = '') {
49         echo apply_filters('bloginfo_rss', get_bloginfo_rss($show), $show);
50 }
51
52 /**
53  * Retrieve the default feed.
54  *
55  * The default feed is 'rss2', unless a plugin changes it through the
56  * 'default_feed' filter.
57  *
58  * @package WordPress
59  * @subpackage Feed
60  * @since 2.5
61  * @uses apply_filters() Calls 'default_feed' hook on the default feed string.
62  *
63  * @return string Default feed, or for example 'rss2', 'atom', etc.
64  */
65 function get_default_feed() {
66         return apply_filters('default_feed', 'rss2');
67 }
68
69 /**
70  * Retrieve the blog title for the feed title.
71  *
72  * @package WordPress
73  * @subpackage Feed
74  * @since 2.2.0
75  * @uses apply_filters() Calls 'get_wp_title_rss' hook on title.
76  * @uses wp_title() See function for $sep parameter usage.
77  *
78  * @param string $sep Optional.How to separate the title. See wp_title() for more info.
79  * @return string Error message on failure or blog title on success.
80  */
81 function get_wp_title_rss($sep = '&#187;') {
82         $title = wp_title($sep, false);
83         if ( is_wp_error( $title ) )
84                 return $title->get_error_message();
85         $title = apply_filters('get_wp_title_rss', $title);
86         return $title;
87 }
88
89 /**
90  * Display the blog title for display of the feed title.
91  *
92  * @package WordPress
93  * @subpackage Feed
94  * @since 2.2.0
95  * @uses apply_filters() Calls 'wp_title_rss' on the blog title.
96  * @see wp_title() $sep parameter usage.
97  *
98  * @param string $sep Optional.
99  */
100 function wp_title_rss($sep = '&#187;') {
101         echo apply_filters('wp_title_rss', get_wp_title_rss($sep));
102 }
103
104 /**
105  * Retrieve the current post title for the feed.
106  *
107  * @package WordPress
108  * @subpackage Feed
109  * @since 2.0.0
110  * @uses apply_filters() Calls 'the_title_rss' on the post title.
111  *
112  * @return string Current post title.
113  */
114 function get_the_title_rss() {
115         $title = get_the_title();
116         $title = apply_filters('the_title_rss', $title);
117         return $title;
118 }
119
120 /**
121  * Display the post title in the feed.
122  *
123  * @package WordPress
124  * @subpackage Feed
125  * @since 0.71
126  * @uses get_the_title_rss() Used to retrieve current post title.
127  */
128 function the_title_rss() {
129         echo get_the_title_rss();
130 }
131
132 /**
133  * Retrieve the post content for feeds.
134  *
135  * @package WordPress
136  * @subpackage Feed
137  * @since 2.9.0
138  * @uses apply_filters() Calls 'the_content_feed' on the content before processing.
139  * @see get_the_content()
140  *
141  * @param string $feed_type The type of feed. rss2 | atom | rss | rdf
142  */
143 function get_the_content_feed($feed_type = null) {
144         if ( !$feed_type )
145                 $feed_type = get_default_feed();
146
147         $content = apply_filters('the_content', get_the_content());
148         $content = str_replace(']]>', ']]&gt;', $content);
149         return apply_filters('the_content_feed', $content, $feed_type);
150 }
151
152 /**
153  * Display the post content for feeds.
154  *
155  * @package WordPress
156  * @subpackage Feed
157  * @since 2.9.0
158  * @uses apply_filters() Calls 'the_content_feed' on the content before processing.
159  * @see get_the_content()
160  *
161  * @param string $feed_type The type of feed. rss2 | atom | rss | rdf
162  */
163 function the_content_feed($feed_type = null) {
164         echo get_the_content_feed();
165 }
166
167 /**
168  * Display the post excerpt for the feed.
169  *
170  * @package WordPress
171  * @subpackage Feed
172  * @since 0.71
173  * @uses apply_filters() Calls 'the_excerpt_rss' hook on the excerpt.
174  */
175 function the_excerpt_rss() {
176         $output = get_the_excerpt();
177         echo apply_filters('the_excerpt_rss', $output);
178 }
179
180 /**
181  * Display the permalink to the post for use in feeds.
182  *
183  * @package WordPress
184  * @subpackage Feed
185  * @since 2.3.0
186  * @uses apply_filters() Call 'the_permalink_rss' on the post permalink
187  */
188 function the_permalink_rss() {
189         echo apply_filters('the_permalink_rss', get_permalink());
190 }
191
192 /**
193  * Display the feed GUID for the current comment.
194  *
195  * @package WordPress
196  * @subpackage Feed
197  * @since unknown
198  *
199  * @param int|object $comment_id Optional comment object or id. Defaults to global comment object.
200  */
201 function comment_guid($comment_id = null) {
202         echo get_comment_guid($comment_id);
203 }
204
205 /**
206  * Retrieve the feed GUID for the current comment.
207  *
208  * @package WordPress
209  * @subpackage Feed
210  * @since unknown
211  *
212  * @param int|object $comment_id Optional comment object or id. Defaults to global comment object.
213  * @return bool|string false on failure or guid for comment on success.
214  */
215 function get_comment_guid($comment_id = null) {
216         $comment = get_comment($comment_id);
217
218         if ( !is_object($comment) )
219                 return false;
220
221         return get_the_guid($comment->comment_post_ID) . '#comment-' . $comment->comment_ID;
222 }
223
224 /**
225  * Display the link to the comments.
226  *
227  * @since 1.5.0
228  */
229 function comment_link() {
230         echo esc_url( get_comment_link() );
231 }
232
233 /**
234  * Retrieve the current comment author for use in the feeds.
235  *
236  * @package WordPress
237  * @subpackage Feed
238  * @since 2.0.0
239  * @uses apply_filters() Calls 'comment_author_rss' hook on comment author.
240  * @uses get_comment_author()
241  *
242  * @return string Comment Author
243  */
244 function get_comment_author_rss() {
245         return apply_filters('comment_author_rss', get_comment_author() );
246 }
247
248 /**
249  * Display the current comment author in the feed.
250  *
251  * @package WordPress
252  * @subpackage Feed
253  * @since 1.0.0
254  */
255 function comment_author_rss() {
256         echo get_comment_author_rss();
257 }
258
259 /**
260  * Display the current comment content for use in the feeds.
261  *
262  * @package WordPress
263  * @subpackage Feed
264  * @since 1.0.0
265  * @uses apply_filters() Calls 'comment_text_rss' filter on comment content.
266  * @uses get_comment_text()
267  */
268 function comment_text_rss() {
269         $comment_text = get_comment_text();
270         $comment_text = apply_filters('comment_text_rss', $comment_text);
271         echo $comment_text;
272 }
273
274 /**
275  * Retrieve all of the post categories, formatted for use in feeds.
276  *
277  * All of the categories for the current post in the feed loop, will be
278  * retrieved and have feed markup added, so that they can easily be added to the
279  * RSS2, Atom, or RSS1 and RSS0.91 RDF feeds.
280  *
281  * @package WordPress
282  * @subpackage Feed
283  * @since 2.1.0
284  * @uses apply_filters()
285  *
286  * @param string $type Optional, default is the type returned by get_default_feed().
287  * @return string All of the post categories for displaying in the feed.
288  */
289 function get_the_category_rss($type = null) {
290         if ( empty($type) )
291                 $type = get_default_feed();
292         $categories = get_the_category();
293         $tags = get_the_tags();
294         $the_list = '';
295         $cat_names = array();
296
297         $filter = 'rss';
298         if ( 'atom' == $type )
299                 $filter = 'raw';
300
301         if ( !empty($categories) ) foreach ( (array) $categories as $category ) {
302                 $cat_names[] = sanitize_term_field('name', $category->name, $category->term_id, 'category', $filter);
303         }
304
305         if ( !empty($tags) ) foreach ( (array) $tags as $tag ) {
306                 $cat_names[] = sanitize_term_field('name', $tag->name, $tag->term_id, 'post_tag', $filter);
307         }
308
309         $cat_names = array_unique($cat_names);
310
311         foreach ( $cat_names as $cat_name ) {
312                 if ( 'rdf' == $type )
313                         $the_list .= "\t\t<dc:subject><![CDATA[$cat_name]]></dc:subject>\n";
314                 elseif ( 'atom' == $type )
315                         $the_list .= sprintf( '<category scheme="%1$s" term="%2$s" />', esc_attr( apply_filters( 'get_bloginfo_rss', get_bloginfo( 'url' ) ) ), esc_attr( $cat_name ) );
316                 else
317                         $the_list .= "\t\t<category><![CDATA[" . @html_entity_decode( $cat_name, ENT_COMPAT, get_option('blog_charset') ) . "]]></category>\n";
318         }
319
320         return apply_filters('the_category_rss', $the_list, $type);
321 }
322
323 /**
324  * Display the post categories in the feed.
325  *
326  * @package WordPress
327  * @subpackage Feed
328  * @since 0.71
329  * @see get_the_category_rss() For better explanation.
330  *
331  * @param string $type Optional, default is the type returned by get_default_feed().
332  */
333 function the_category_rss($type = null) {
334         echo get_the_category_rss($type);
335 }
336
337 /**
338  * Display the HTML type based on the blog setting.
339  *
340  * The two possible values are either 'xhtml' or 'html'.
341  *
342  * @package WordPress
343  * @subpackage Feed
344  * @since 2.2.0
345  */
346 function html_type_rss() {
347         $type = get_bloginfo('html_type');
348         if (strpos($type, 'xhtml') !== false)
349                 $type = 'xhtml';
350         else
351                 $type = 'html';
352         echo $type;
353 }
354
355 /**
356  * Display the rss enclosure for the current post.
357  *
358  * Uses the global $post to check whether the post requires a password and if
359  * the user has the password for the post. If not then it will return before
360  * displaying.
361  *
362  * Also uses the function get_post_custom() to get the post's 'enclosure'
363  * metadata field and parses the value to display the enclosure(s). The
364  * enclosure(s) consist of enclosure HTML tag(s) with a URI and other
365  * attributes.
366  *
367  * @package WordPress
368  * @subpackage Template
369  * @since 1.5.0
370  * @uses apply_filters() Calls 'rss_enclosure' hook on rss enclosure.
371  * @uses get_post_custom() To get the current post enclosure metadata.
372  */
373 function rss_enclosure() {
374         if ( post_password_required() )
375                 return;
376
377         foreach ( (array) get_post_custom() as $key => $val) {
378                 if ($key == 'enclosure') {
379                         foreach ( (array) $val as $enc ) {
380                                 $enclosure = explode("\n", $enc);
381
382                                 //only get the the first element eg, audio/mpeg from 'audio/mpeg mpga mp2 mp3'
383                                 $t = preg_split('/[ \t]/', trim($enclosure[2]) );
384                                 $type = $t[0];
385
386                                 echo apply_filters('rss_enclosure', '<enclosure url="' . trim(htmlspecialchars($enclosure[0])) . '" length="' . trim($enclosure[1]) . '" type="' . $type . '" />' . "\n");
387                         }
388                 }
389         }
390 }
391
392 /**
393  * Display the atom enclosure for the current post.
394  *
395  * Uses the global $post to check whether the post requires a password and if
396  * the user has the password for the post. If not then it will return before
397  * displaying.
398  *
399  * Also uses the function get_post_custom() to get the post's 'enclosure'
400  * metadata field and parses the value to display the enclosure(s). The
401  * enclosure(s) consist of link HTML tag(s) with a URI and other attributes.
402  *
403  * @package WordPress
404  * @subpackage Template
405  * @since 2.2.0
406  * @uses apply_filters() Calls 'atom_enclosure' hook on atom enclosure.
407  * @uses get_post_custom() To get the current post enclosure metadata.
408  */
409 function atom_enclosure() {
410         if ( post_password_required() )
411                 return;
412
413         foreach ( (array) get_post_custom() as $key => $val ) {
414                 if ($key == 'enclosure') {
415                         foreach ( (array) $val as $enc ) {
416                                 $enclosure = split("\n", $enc);
417                                 echo apply_filters('atom_enclosure', '<link href="' . trim(htmlspecialchars($enclosure[0])) . '" rel="enclosure" length="' . trim($enclosure[1]) . '" type="' . trim($enclosure[2]) . '" />' . "\n");
418                         }
419                 }
420         }
421 }
422
423 /**
424  * Determine the type of a string of data with the data formatted.
425  *
426  * Tell whether the type is text, html, or xhtml, per RFC 4287 section 3.1.
427  *
428  * In the case of WordPress, text is defined as containing no markup,
429  * xhtml is defined as "well formed", and html as tag soup (i.e., the rest).
430  *
431  * Container div tags are added to xhtml values, per section 3.1.1.3.
432  *
433  * @link http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rfc.section.3.1
434  *
435  * @package WordPress
436  * @subpackage Feed
437  * @since 2.5
438  *
439  * @param string $data Input string
440  * @return array array(type, value)
441  */
442 function prep_atom_text_construct($data) {
443         if (strpos($data, '<') === false && strpos($data, '&') === false) {
444                 return array('text', $data);
445         }
446
447         $parser = xml_parser_create();
448         xml_parse($parser, '<div>' . $data . '</div>', true);
449         $code = xml_get_error_code($parser);
450         xml_parser_free($parser);
451
452         if (!$code) {
453                 if (strpos($data, '<') === false) {
454                         return array('text', $data);
455                 } else {
456                         $data = "<div xmlns='http://www.w3.org/1999/xhtml'>$data</div>";
457                         return array('xhtml', $data);
458                 }
459         }
460
461         if (strpos($data, ']]>') == false) {
462                 return array('html', "<![CDATA[$data]]>");
463         } else {
464                 return array('html', htmlspecialchars($data));
465         }
466 }
467
468 /**
469  * Display the link for the currently displayed feed in a XSS safe way.
470  *
471  * Generate a correct link for the atom:self element.
472  *
473  * @package WordPress
474  * @subpackage Feed
475  * @since 2.5
476  */
477 function self_link() {
478         $host = @parse_url(get_option('home'));
479         $host = $host['host'];
480         echo esc_url(
481                 'http'
482                 . ( (isset($_SERVER['https']) && $_SERVER['https'] == 'on') ? 's' : '' ) . '://'
483                 . $host
484                 . stripslashes($_SERVER['REQUEST_URI'])
485                 );
486 }
487
488 /**
489  * Return the content type for specified feed type.
490  *
491  * @package WordPress
492  * @subpackage Feed
493  * @since 2.8.0
494  */
495 function feed_content_type( $type = '' ) {
496         if ( empty($type) )
497                 $type = get_default_feed();
498
499         $types = array(
500                 'rss'  => 'application/rss+xml',
501                 'rss2' => 'application/rss+xml',
502                 'rss-http'  => 'text/xml',
503                 'atom' => 'application/atom+xml',
504                 'rdf'  => 'application/rdf+xml'
505         );
506
507         $content_type = ( !empty($types[$type]) ) ? $types[$type] : 'application/octet-stream';
508
509         return apply_filters( 'feed_content_type', $content_type, $type );
510 }
511
512 /**
513  * Build SimplePie object based on RSS or Atom feed from URL.
514  *
515  * @since 2.8
516  *
517  * @param string $url URL to retrieve feed
518  * @return WP_Error|SimplePie WP_Error object on failure or SimplePie object on success
519  */
520 function fetch_feed($url) {
521         require_once (ABSPATH . WPINC . '/class-feed.php');
522
523         $feed = new SimplePie();
524         $feed->set_feed_url($url);
525         $feed->set_cache_class('WP_Feed_Cache');
526         $feed->set_file_class('WP_SimplePie_File');
527         $feed->set_cache_duration(apply_filters('wp_feed_cache_transient_lifetime', 43200));
528         $feed->init();
529         $feed->handle_content_type();
530
531         if ( $feed->error() )
532                 return new WP_Error('simplepie-error', $feed->error());
533
534         return $feed;
535 }