~canonical-sysadmins/wordpress/4.7.4

« back to all changes in this revision

Viewing changes to wp-includes/post-template.php

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * WordPress Post Template Functions.
 
4
 *
 
5
 * Gets content for the current post in the loop.
 
6
 *
 
7
 * @package WordPress
 
8
 * @subpackage Template
 
9
 */
 
10
 
 
11
/**
 
12
 * Display the ID of the current item in the WordPress Loop.
 
13
 *
 
14
 * @since 0.71
 
15
 */
 
16
function the_ID() {
 
17
        echo get_the_ID();
 
18
}
 
19
 
 
20
/**
 
21
 * Retrieve the ID of the current item in the WordPress Loop.
 
22
 *
 
23
 * @since 2.1.0
 
24
 * @uses $post
 
25
 *
 
26
 * @return int|bool The ID of the current item in the WordPress Loop. False if $post is not set.
 
27
 */
 
28
function get_the_ID() {
 
29
        $post = get_post();
 
30
        return ! empty( $post ) ? $post->ID : false;
 
31
}
 
32
 
 
33
/**
 
34
 * Display or retrieve the current post title with optional content.
 
35
 *
 
36
 * @since 0.71
 
37
 *
 
38
 * @param string $before Optional. Content to prepend to the title.
 
39
 * @param string $after Optional. Content to append to the title.
 
40
 * @param bool $echo Optional, default to true.Whether to display or return.
 
41
 * @return null|string Null on no title. String if $echo parameter is false.
 
42
 */
 
43
function the_title($before = '', $after = '', $echo = true) {
 
44
        $title = get_the_title();
 
45
 
 
46
        if ( strlen($title) == 0 )
 
47
                return;
 
48
 
 
49
        $title = $before . $title . $after;
 
50
 
 
51
        if ( $echo )
 
52
                echo $title;
 
53
        else
 
54
                return $title;
 
55
}
 
56
 
 
57
/**
 
58
 * Sanitize the current title when retrieving or displaying.
 
59
 *
 
60
 * Works like {@link the_title()}, except the parameters can be in a string or
 
61
 * an array. See the function for what can be override in the $args parameter.
 
62
 *
 
63
 * The title before it is displayed will have the tags stripped and {@link
 
64
 * esc_attr()} before it is passed to the user or displayed. The default
 
65
 * as with {@link the_title()}, is to display the title.
 
66
 *
 
67
 * @since 2.3.0
 
68
 *
 
69
 * @param string|array $args {
 
70
 *     Title attribute arguments. Optional.
 
71
 *
 
72
 *     @type string  $before Markup to prepend to the title. Default empty.
 
73
 *     @type string  $after  Markup to append to the title. Default empty.
 
74
 *     @type bool    $echo   Whether to echo or return the title. Default true for echo.
 
75
 *     @type WP_Post $post   Current post object to retrieve the title for.
 
76
 * }
 
77
 * @return string|null Null on failure or display. String when echo is false.
 
78
 */
 
79
function the_title_attribute( $args = '' ) {
 
80
        $defaults = array( 'before' => '', 'after' =>  '', 'echo' => true, 'post' => get_post() );
 
81
        $r = wp_parse_args( $args, $defaults );
 
82
 
 
83
        $title = get_the_title( $r['post'] );
 
84
 
 
85
        if ( strlen( $title ) == 0 ) {
 
86
                return;
 
87
        }
 
88
 
 
89
        $title = $r['before'] . $title . $r['after'];
 
90
        $title = esc_attr( strip_tags( $title ) );
 
91
 
 
92
        if ( $r['echo'] ) {
 
93
                echo $title;
 
94
        } else {
 
95
                return $title;
 
96
        }
 
97
}
 
98
 
 
99
/**
 
100
 * Retrieve post title.
 
101
 *
 
102
 * If the post is protected and the visitor is not an admin, then "Protected"
 
103
 * will be displayed before the post title. If the post is private, then
 
104
 * "Private" will be located before the post title.
 
105
 *
 
106
 * @since 0.71
 
107
 *
 
108
 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
 
109
 * @return string
 
110
 */
 
111
function get_the_title( $post = 0 ) {
 
112
        $post = get_post( $post );
 
113
 
 
114
        $title = isset( $post->post_title ) ? $post->post_title : '';
 
115
        $id = isset( $post->ID ) ? $post->ID : 0;
 
116
 
 
117
        if ( ! is_admin() ) {
 
118
                if ( ! empty( $post->post_password ) ) {
 
119
 
 
120
                        /**
 
121
                         * Filter the text prepended to the post title for protected posts.
 
122
                         *
 
123
                         * The filter is only applied on the front end.
 
124
                         *
 
125
                         * @since 2.8.0
 
126
                         *
 
127
                         * @param string  $prepend Text displayed before the post title.
 
128
                         *                         Default 'Protected: %s'.
 
129
                         * @param WP_Post $post    Current post object.
 
130
                         */
 
131
                        $protected_title_format = apply_filters( 'protected_title_format', __( 'Protected: %s' ), $post );
 
132
                        $title = sprintf( $protected_title_format, $title );
 
133
                } else if ( isset( $post->post_status ) && 'private' == $post->post_status ) {
 
134
 
 
135
                        /**
 
136
                         * Filter the text prepended to the post title of private posts.
 
137
                         *
 
138
                         * The filter is only applied on the front end.
 
139
                         *
 
140
                         * @since 2.8.0
 
141
                         *
 
142
                         * @param string  $prepend Text displayed before the post title.
 
143
                         *                         Default 'Private: %s'.
 
144
                         * @param WP_Post $post    Current post object.
 
145
                         */
 
146
                        $private_title_format = apply_filters( 'private_title_format', __( 'Private: %s' ), $post );
 
147
                        $title = sprintf( $private_title_format, $title );
 
148
                }
 
149
        }
 
150
 
 
151
        /**
 
152
         * Filter the post title.
 
153
         *
 
154
         * @since 0.71
 
155
         *
 
156
         * @param string $title The post title.
 
157
         * @param int    $id    The post ID.
 
158
         */
 
159
        return apply_filters( 'the_title', $title, $id );
 
160
}
 
161
 
 
162
/**
 
163
 * Display the Post Global Unique Identifier (guid).
 
164
 *
 
165
 * The guid will appear to be a link, but should not be used as an link to the
 
166
 * post. The reason you should not use it as a link, is because of moving the
 
167
 * blog across domains.
 
168
 *
 
169
 * Url is escaped to make it xml safe
 
170
 *
 
171
 * @since 1.5.0
 
172
 *
 
173
 * @param int|WP_Post $id Optional. Post ID or post object.
 
174
 */
 
175
function the_guid( $id = 0 ) {
 
176
        echo esc_url( get_the_guid( $id ) );
 
177
}
 
178
 
 
179
/**
 
180
 * Retrieve the Post Global Unique Identifier (guid).
 
181
 *
 
182
 * The guid will appear to be a link, but should not be used as an link to the
 
183
 * post. The reason you should not use it as a link, is because of moving the
 
184
 * blog across domains.
 
185
 *
 
186
 * @since 1.5.0
 
187
 *
 
188
 * @param int|WP_Post $id Optional. Post ID or post object.
 
189
 * @return string
 
190
 */
 
191
function get_the_guid( $id = 0 ) {
 
192
        $post = get_post($id);
 
193
 
 
194
        /**
 
195
         * Filter the Global Unique Identifier (guid) of the post.
 
196
         *
 
197
         * @since 1.5.0
 
198
         *
 
199
         * @param string $post_guid Global Unique Identifier (guid) of the post.
 
200
         */
 
201
        return apply_filters( 'get_the_guid', $post->guid );
 
202
}
 
203
 
 
204
/**
 
205
 * Display the post content.
 
206
 *
 
207
 * @since 0.71
 
208
 *
 
209
 * @param string $more_link_text Optional. Content for when there is more text.
 
210
 * @param bool $strip_teaser Optional. Strip teaser content before the more text. Default is false.
 
211
 */
 
212
function the_content( $more_link_text = null, $strip_teaser = false) {
 
213
        $content = get_the_content( $more_link_text, $strip_teaser );
 
214
 
 
215
        /**
 
216
         * Filter the post content.
 
217
         *
 
218
         * @since 0.71
 
219
         *
 
220
         * @param string $content Content of the current post.
 
221
         */
 
222
        $content = apply_filters( 'the_content', $content );
 
223
        $content = str_replace( ']]>', ']]&gt;', $content );
 
224
        echo $content;
 
225
}
 
226
 
 
227
/**
 
228
 * Retrieve the post content.
 
229
 *
 
230
 * @since 0.71
 
231
 *
 
232
 * @param string $more_link_text Optional. Content for when there is more text.
 
233
 * @param bool $stripteaser Optional. Strip teaser content before the more text. Default is false.
 
234
 * @return string
 
235
 */
 
236
function get_the_content( $more_link_text = null, $strip_teaser = false ) {
 
237
        global $page, $more, $preview, $pages, $multipage;
 
238
 
 
239
        $post = get_post();
 
240
 
 
241
        if ( null === $more_link_text )
 
242
                $more_link_text = __( '(more&hellip;)' );
 
243
 
 
244
        $output = '';
 
245
        $has_teaser = false;
 
246
 
 
247
        // If post password required and it doesn't match the cookie.
 
248
        if ( post_password_required( $post ) )
 
249
                return get_the_password_form( $post );
 
250
 
 
251
        if ( $page > count( $pages ) ) // if the requested page doesn't exist
 
252
                $page = count( $pages ); // give them the highest numbered page that DOES exist
 
253
 
 
254
        $content = $pages[$page - 1];
 
255
        if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
 
256
                $content = explode( $matches[0], $content, 2 );
 
257
                if ( ! empty( $matches[1] ) && ! empty( $more_link_text ) )
 
258
                        $more_link_text = strip_tags( wp_kses_no_null( trim( $matches[1] ) ) );
 
259
 
 
260
                $has_teaser = true;
 
261
        } else {
 
262
                $content = array( $content );
 
263
        }
 
264
 
 
265
        if ( false !== strpos( $post->post_content, '<!--noteaser-->' ) && ( ! $multipage || $page == 1 ) )
 
266
                $strip_teaser = true;
 
267
 
 
268
        $teaser = $content[0];
 
269
 
 
270
        if ( $more && $strip_teaser && $has_teaser )
 
271
                $teaser = '';
 
272
 
 
273
        $output .= $teaser;
 
274
 
 
275
        if ( count( $content ) > 1 ) {
 
276
                if ( $more ) {
 
277
                        $output .= '<span id="more-' . $post->ID . '"></span>' . $content[1];
 
278
                } else {
 
279
                        if ( ! empty( $more_link_text ) )
 
280
 
 
281
                                /**
 
282
                                 * Filter the Read More link text.
 
283
                                 *
 
284
                                 * @since 2.8.0
 
285
                                 *
 
286
                                 * @param string $more_link_element Read More link element.
 
287
                                 * @param string $more_link_text    Read More text.
 
288
                                 */
 
289
                                $output .= apply_filters( 'the_content_more_link', ' <a href="' . get_permalink() . "#more-{$post->ID}\" class=\"more-link\">$more_link_text</a>", $more_link_text );
 
290
                        $output = force_balance_tags( $output );
 
291
                }
 
292
        }
 
293
 
 
294
        if ( $preview ) // preview fix for javascript bug with foreign languages
 
295
                $output =       preg_replace_callback( '/\%u([0-9A-F]{4})/', '_convert_urlencoded_to_entities', $output );
 
296
 
 
297
        return $output;
 
298
}
 
299
 
 
300
/**
 
301
 * Preview fix for javascript bug with foreign languages
 
302
 *
 
303
 * @since 3.1.0
 
304
 * @access private
 
305
 * @param array $match Match array from preg_replace_callback
 
306
 * @return string
 
307
 */
 
308
function _convert_urlencoded_to_entities( $match ) {
 
309
        return '&#' . base_convert( $match[1], 16, 10 ) . ';';
 
310
}
 
311
 
 
312
/**
 
313
 * Display the post excerpt.
 
314
 *
 
315
 * @since 0.71
 
316
 */
 
317
function the_excerpt() {
 
318
 
 
319
        /**
 
320
         * Filter the displayed post excerpt.
 
321
         *
 
322
         * @since 0.71
 
323
         *
 
324
         * @see get_the_excerpt()
 
325
         *
 
326
         * @param string $post_excerpt The post excerpt.
 
327
         */
 
328
        echo apply_filters( 'the_excerpt', get_the_excerpt() );
 
329
}
 
330
 
 
331
/**
 
332
 * Retrieve the post excerpt.
 
333
 *
 
334
 * @since 0.71
 
335
 *
 
336
 * @param mixed $deprecated Not used.
 
337
 * @return string
 
338
 */
 
339
function get_the_excerpt( $deprecated = '' ) {
 
340
        if ( !empty( $deprecated ) )
 
341
                _deprecated_argument( __FUNCTION__, '2.3' );
 
342
 
 
343
        $post = get_post();
 
344
        if ( empty( $post ) ) {
 
345
                return '';
 
346
        }
 
347
 
 
348
        if ( post_password_required() ) {
 
349
                return __( 'There is no excerpt because this is a protected post.' );
 
350
        }
 
351
 
 
352
        /**
 
353
         * Filter the retrieved post excerpt.
 
354
         *
 
355
         * @since 1.2.0
 
356
         *
 
357
         * @param string $post_excerpt The post excerpt.
 
358
         */
 
359
        return apply_filters( 'get_the_excerpt', $post->post_excerpt );
 
360
}
 
361
 
 
362
/**
 
363
 * Whether post has excerpt.
 
364
 *
 
365
 * @since 2.3.0
 
366
 *
 
367
 * @param int|WP_Post $id Optional. Post ID or post object.
 
368
 * @return bool
 
369
 */
 
370
function has_excerpt( $id = 0 ) {
 
371
        $post = get_post( $id );
 
372
        return ( !empty( $post->post_excerpt ) );
 
373
}
 
374
 
 
375
/**
 
376
 * Display the classes for the post div.
 
377
 *
 
378
 * @since 2.7.0
 
379
 *
 
380
 * @param string|array $class One or more classes to add to the class list.
 
381
 * @param int|WP_Post $post_id Optional. Post ID or post object.
 
382
 */
 
383
function post_class( $class = '', $post_id = null ) {
 
384
        // Separates classes with a single space, collates classes for post DIV
 
385
        echo 'class="' . join( ' ', get_post_class( $class, $post_id ) ) . '"';
 
386
}
 
387
 
 
388
/**
 
389
 * Retrieve the classes for the post div as an array.
 
390
 *
 
391
 * The class names are many. If the post is a sticky, then the 'sticky'
 
392
 * class name. The class 'hentry' is always added to each post. If the post has a
 
393
 * post thumbnail, 'has-post-thumbnail' is added as a class. For each
 
394
 * category, the class will be added with 'category-' with category slug is
 
395
 * added. The tags are the same way as the categories with 'tag-' before the tag
 
396
 * slug. All classes are passed through the filter, 'post_class' with the list
 
397
 * of classes, followed by $class parameter value, with the post ID as the last
 
398
 * parameter.
 
399
 *
 
400
 * @since 2.7.0
 
401
 *
 
402
 * @param string|array $class One or more classes to add to the class list.
 
403
 * @param int|WP_Post $post_id Optional. Post ID or post object.
 
404
 * @return array Array of classes.
 
405
 */
 
406
function get_post_class( $class = '', $post_id = null ) {
 
407
        $post = get_post($post_id);
 
408
 
 
409
        $classes = array();
 
410
 
 
411
        if ( empty($post) )
 
412
                return $classes;
 
413
 
 
414
        $classes[] = 'post-' . $post->ID;
 
415
        if ( ! is_admin() )
 
416
                $classes[] = $post->post_type;
 
417
        $classes[] = 'type-' . $post->post_type;
 
418
        $classes[] = 'status-' . $post->post_status;
 
419
 
 
420
        // Post Format
 
421
        if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
 
422
                $post_format = get_post_format( $post->ID );
 
423
 
 
424
                if ( $post_format && !is_wp_error($post_format) )
 
425
                        $classes[] = 'format-' . sanitize_html_class( $post_format );
 
426
                else
 
427
                        $classes[] = 'format-standard';
 
428
        }
 
429
 
 
430
        // Post requires password
 
431
        if ( post_password_required( $post->ID ) ) {
 
432
                $classes[] = 'post-password-required';
 
433
        // Post thumbnails
 
434
        } elseif ( ! is_attachment( $post ) && current_theme_supports( 'post-thumbnails' ) && has_post_thumbnail( $post->ID ) ) {
 
435
                $classes[] = 'has-post-thumbnail';
 
436
        }
 
437
 
 
438
        // sticky for Sticky Posts
 
439
        if ( is_sticky( $post->ID ) ) {
 
440
                if ( is_home() && ! is_paged() ) {
 
441
                        $classes[] = 'sticky';
 
442
                } elseif ( is_admin() ) {
 
443
                        $classes[] = 'status-sticky';
 
444
                }
 
445
        }
 
446
 
 
447
        // hentry for hAtom compliance
 
448
        $classes[] = 'hentry';
 
449
 
 
450
        // Categories
 
451
        if ( is_object_in_taxonomy( $post->post_type, 'category' ) ) {
 
452
                foreach ( (array) get_the_category($post->ID) as $cat ) {
 
453
                        if ( empty($cat->slug ) )
 
454
                                continue;
 
455
                        $classes[] = 'category-' . sanitize_html_class($cat->slug, $cat->term_id);
 
456
                }
 
457
        }
 
458
 
 
459
        // Tags
 
460
        if ( is_object_in_taxonomy( $post->post_type, 'post_tag' ) ) {
 
461
                foreach ( (array) get_the_tags($post->ID) as $tag ) {
 
462
                        if ( empty($tag->slug ) )
 
463
                                continue;
 
464
                        $classes[] = 'tag-' . sanitize_html_class($tag->slug, $tag->term_id);
 
465
                }
 
466
        }
 
467
 
 
468
        if ( !empty($class) ) {
 
469
                if ( !is_array( $class ) )
 
470
                        $class = preg_split('#\s+#', $class);
 
471
                $classes = array_merge($classes, $class);
 
472
        }
 
473
 
 
474
        $classes = array_map('esc_attr', $classes);
 
475
 
 
476
        /**
 
477
         * Filter the list of CSS classes for the current post.
 
478
         *
 
479
         * @since 2.7.0
 
480
         *
 
481
         * @param array  $classes An array of post classes.
 
482
         * @param string $class   A comma-separated list of additional classes added to the post.
 
483
         * @param int    $post_id The post ID.
 
484
         */
 
485
        $classes = apply_filters( 'post_class', $classes, $class, $post->ID );
 
486
 
 
487
        return array_unique( $classes );
 
488
}
 
489
 
 
490
/**
 
491
 * Display the classes for the body element.
 
492
 *
 
493
 * @since 2.8.0
 
494
 *
 
495
 * @param string|array $class One or more classes to add to the class list.
 
496
 */
 
497
function body_class( $class = '' ) {
 
498
        // Separates classes with a single space, collates classes for body element
 
499
        echo 'class="' . join( ' ', get_body_class( $class ) ) . '"';
 
500
}
 
501
 
 
502
/**
 
503
 * Retrieve the classes for the body element as an array.
 
504
 *
 
505
 * @since 2.8.0
 
506
 *
 
507
 * @param string|array $class One or more classes to add to the class list.
 
508
 * @return array Array of classes.
 
509
 */
 
510
function get_body_class( $class = '' ) {
 
511
        global $wp_query, $wpdb;
 
512
 
 
513
        $classes = array();
 
514
 
 
515
        if ( is_rtl() )
 
516
                $classes[] = 'rtl';
 
517
 
 
518
        if ( is_front_page() )
 
519
                $classes[] = 'home';
 
520
        if ( is_home() )
 
521
                $classes[] = 'blog';
 
522
        if ( is_archive() )
 
523
                $classes[] = 'archive';
 
524
        if ( is_date() )
 
525
                $classes[] = 'date';
 
526
        if ( is_search() ) {
 
527
                $classes[] = 'search';
 
528
                $classes[] = $wp_query->posts ? 'search-results' : 'search-no-results';
 
529
        }
 
530
        if ( is_paged() )
 
531
                $classes[] = 'paged';
 
532
        if ( is_attachment() )
 
533
                $classes[] = 'attachment';
 
534
        if ( is_404() )
 
535
                $classes[] = 'error404';
 
536
 
 
537
        if ( is_single() ) {
 
538
                $post_id = $wp_query->get_queried_object_id();
 
539
                $post = $wp_query->get_queried_object();
 
540
 
 
541
                $classes[] = 'single';
 
542
                if ( isset( $post->post_type ) ) {
 
543
                        $classes[] = 'single-' . sanitize_html_class($post->post_type, $post_id);
 
544
                        $classes[] = 'postid-' . $post_id;
 
545
 
 
546
                        // Post Format
 
547
                        if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
 
548
                                $post_format = get_post_format( $post->ID );
 
549
 
 
550
                                if ( $post_format && !is_wp_error($post_format) )
 
551
                                        $classes[] = 'single-format-' . sanitize_html_class( $post_format );
 
552
                                else
 
553
                                        $classes[] = 'single-format-standard';
 
554
                        }
 
555
                }
 
556
 
 
557
                if ( is_attachment() ) {
 
558
                        $mime_type = get_post_mime_type($post_id);
 
559
                        $mime_prefix = array( 'application/', 'image/', 'text/', 'audio/', 'video/', 'music/' );
 
560
                        $classes[] = 'attachmentid-' . $post_id;
 
561
                        $classes[] = 'attachment-' . str_replace( $mime_prefix, '', $mime_type );
 
562
                }
 
563
        } elseif ( is_archive() ) {
 
564
                if ( is_post_type_archive() ) {
 
565
                        $classes[] = 'post-type-archive';
 
566
                        $post_type = get_query_var( 'post_type' );
 
567
                        if ( is_array( $post_type ) )
 
568
                                $post_type = reset( $post_type );
 
569
                        $classes[] = 'post-type-archive-' . sanitize_html_class( $post_type );
 
570
                } else if ( is_author() ) {
 
571
                        $author = $wp_query->get_queried_object();
 
572
                        $classes[] = 'author';
 
573
                        if ( isset( $author->user_nicename ) ) {
 
574
                                $classes[] = 'author-' . sanitize_html_class( $author->user_nicename, $author->ID );
 
575
                                $classes[] = 'author-' . $author->ID;
 
576
                        }
 
577
                } elseif ( is_category() ) {
 
578
                        $cat = $wp_query->get_queried_object();
 
579
                        $classes[] = 'category';
 
580
                        if ( isset( $cat->term_id ) ) {
 
581
                                $classes[] = 'category-' . sanitize_html_class( $cat->slug, $cat->term_id );
 
582
                                $classes[] = 'category-' . $cat->term_id;
 
583
                        }
 
584
                } elseif ( is_tag() ) {
 
585
                        $tags = $wp_query->get_queried_object();
 
586
                        $classes[] = 'tag';
 
587
                        if ( isset( $tags->term_id ) ) {
 
588
                                $classes[] = 'tag-' . sanitize_html_class( $tags->slug, $tags->term_id );
 
589
                                $classes[] = 'tag-' . $tags->term_id;
 
590
                        }
 
591
                } elseif ( is_tax() ) {
 
592
                        $term = $wp_query->get_queried_object();
 
593
                        if ( isset( $term->term_id ) ) {
 
594
                                $classes[] = 'tax-' . sanitize_html_class( $term->taxonomy );
 
595
                                $classes[] = 'term-' . sanitize_html_class( $term->slug, $term->term_id );
 
596
                                $classes[] = 'term-' . $term->term_id;
 
597
                        }
 
598
                }
 
599
        } elseif ( is_page() ) {
 
600
                $classes[] = 'page';
 
601
 
 
602
                $page_id = $wp_query->get_queried_object_id();
 
603
 
 
604
                $post = get_post($page_id);
 
605
 
 
606
                $classes[] = 'page-id-' . $page_id;
 
607
 
 
608
                if ( get_pages( array( 'parent' => $page_id, 'number' => 1 ) ) ) {
 
609
                        $classes[] = 'page-parent';
 
610
                }
 
611
 
 
612
                if ( $post->post_parent ) {
 
613
                        $classes[] = 'page-child';
 
614
                        $classes[] = 'parent-pageid-' . $post->post_parent;
 
615
                }
 
616
                if ( is_page_template() ) {
 
617
                        $classes[] = 'page-template';
 
618
                        $classes[] = 'page-template-' . sanitize_html_class( str_replace( '.', '-', get_page_template_slug( $page_id ) ) );
 
619
                } else {
 
620
                        $classes[] = 'page-template-default';
 
621
                }
 
622
        }
 
623
 
 
624
        if ( is_user_logged_in() )
 
625
                $classes[] = 'logged-in';
 
626
 
 
627
        if ( is_admin_bar_showing() ) {
 
628
                $classes[] = 'admin-bar';
 
629
                $classes[] = 'no-customize-support';
 
630
        }
 
631
 
 
632
        if ( get_theme_mod( 'background_color' ) || get_background_image() )
 
633
                $classes[] = 'custom-background';
 
634
 
 
635
        $page = $wp_query->get( 'page' );
 
636
 
 
637
        if ( ! $page || $page < 2 )
 
638
                $page = $wp_query->get( 'paged' );
 
639
 
 
640
        if ( $page && $page > 1 && ! is_404() ) {
 
641
                $classes[] = 'paged-' . $page;
 
642
 
 
643
                if ( is_single() )
 
644
                        $classes[] = 'single-paged-' . $page;
 
645
                elseif ( is_page() )
 
646
                        $classes[] = 'page-paged-' . $page;
 
647
                elseif ( is_category() )
 
648
                        $classes[] = 'category-paged-' . $page;
 
649
                elseif ( is_tag() )
 
650
                        $classes[] = 'tag-paged-' . $page;
 
651
                elseif ( is_date() )
 
652
                        $classes[] = 'date-paged-' . $page;
 
653
                elseif ( is_author() )
 
654
                        $classes[] = 'author-paged-' . $page;
 
655
                elseif ( is_search() )
 
656
                        $classes[] = 'search-paged-' . $page;
 
657
                elseif ( is_post_type_archive() )
 
658
                        $classes[] = 'post-type-paged-' . $page;
 
659
        }
 
660
 
 
661
        if ( ! empty( $class ) ) {
 
662
                if ( !is_array( $class ) )
 
663
                        $class = preg_split( '#\s+#', $class );
 
664
                $classes = array_merge( $classes, $class );
 
665
        } else {
 
666
                // Ensure that we always coerce class to being an array.
 
667
                $class = array();
 
668
        }
 
669
 
 
670
        $classes = array_map( 'esc_attr', $classes );
 
671
 
 
672
        /**
 
673
         * Filter the list of CSS body classes for the current post or page.
 
674
         *
 
675
         * @since 2.8.0
 
676
         *
 
677
         * @param array  $classes An array of body classes.
 
678
         * @param string $class   A comma-separated list of additional classes added to the body.
 
679
         */
 
680
        $classes = apply_filters( 'body_class', $classes, $class );
 
681
 
 
682
        return array_unique( $classes );
 
683
}
 
684
 
 
685
/**
 
686
 * Whether post requires password and correct password has been provided.
 
687
 *
 
688
 * @since 2.7.0
 
689
 *
 
690
 * @param int|WP_Post $post An optional post. Global $post used if not provided.
 
691
 * @return bool false if a password is not required or the correct password cookie is present, true otherwise.
 
692
 */
 
693
function post_password_required( $post = null ) {
 
694
        $post = get_post($post);
 
695
 
 
696
        if ( empty( $post->post_password ) )
 
697
                return false;
 
698
 
 
699
        if ( ! isset( $_COOKIE['wp-postpass_' . COOKIEHASH] ) )
 
700
                return true;
 
701
 
 
702
        require_once ABSPATH . WPINC . '/class-phpass.php';
 
703
        $hasher = new PasswordHash( 8, true );
 
704
 
 
705
        $hash = wp_unslash( $_COOKIE[ 'wp-postpass_' . COOKIEHASH ] );
 
706
        if ( 0 !== strpos( $hash, '$P$B' ) )
 
707
                return true;
 
708
 
 
709
        return ! $hasher->CheckPassword( $post->post_password, $hash );
 
710
}
 
711
 
 
712
//
 
713
// Page Template Functions for usage in Themes
 
714
//
 
715
 
 
716
/**
 
717
 * The formatted output of a list of pages.
 
718
 *
 
719
 * Displays page links for paginated posts (i.e. includes the <!--nextpage-->.
 
720
 * Quicktag one or more times). This tag must be within The Loop.
 
721
 *
 
722
 * @since 1.2.0
 
723
 *
 
724
 * @param string|array $args {
 
725
 *     Optional. Array or string of default arguments.
 
726
 *
 
727
 *     @type string       $before           HTML or text to prepend to each link. Default is '<p> Pages:'.
 
728
 *     @type string       $after            HTML or text to append to each link. Default is '</p>'.
 
729
 *     @type string       $link_before      HTML or text to prepend to each link, inside the <a> tag.
 
730
 *                                          Also prepended to the current item, which is not linked. Default empty.
 
731
 *     @type string       $link_after       HTML or text to append to each Pages link inside the <a> tag.
 
732
 *                                          Also appended to the current item, which is not linked. Default empty.
 
733
 *     @type string       $next_or_number   Indicates whether page numbers should be used. Valid values are number
 
734
 *                                          and next. Default is 'number'.
 
735
 *     @type string       $separator        Text between pagination links. Default is ' '.
 
736
 *     @type string       $nextpagelink     Link text for the next page link, if available. Default is 'Next Page'.
 
737
 *     @type string       $previouspagelink Link text for the previous page link, if available. Default is 'Previous Page'.
 
738
 *     @type string       $pagelink         Format string for page numbers. The % in the parameter string will be
 
739
 *                                          replaced with the page number, so 'Page %' generates "Page 1", "Page 2", etc.
 
740
 *                                          Defaults to '%', just the page number.
 
741
 *     @type int|bool     $echo             Whether to echo or not. Accepts 1|true or 0|false. Default 1|true.
 
742
 * }
 
743
 * @return string Formatted output in HTML.
 
744
 */
 
745
function wp_link_pages( $args = '' ) {
 
746
        $defaults = array(
 
747
                'before'           => '<p>' . __( 'Pages:' ),
 
748
                'after'            => '</p>',
 
749
                'link_before'      => '',
 
750
                'link_after'       => '',
 
751
                'next_or_number'   => 'number',
 
752
                'separator'        => ' ',
 
753
                'nextpagelink'     => __( 'Next page' ),
 
754
                'previouspagelink' => __( 'Previous page' ),
 
755
                'pagelink'         => '%',
 
756
                'echo'             => 1
 
757
        );
 
758
 
 
759
        $params = wp_parse_args( $args, $defaults );
 
760
 
 
761
        /**
 
762
         * Filter the arguments used in retrieving page links for paginated posts.
 
763
         *
 
764
         * @since 3.0.0
 
765
         *
 
766
         * @param array $params An array of arguments for page links for paginated posts.
 
767
         */
 
768
        $r = apply_filters( 'wp_link_pages_args', $params );
 
769
 
 
770
        global $page, $numpages, $multipage, $more;
 
771
 
 
772
        $output = '';
 
773
        if ( $multipage ) {
 
774
                if ( 'number' == $r['next_or_number'] ) {
 
775
                        $output .= $r['before'];
 
776
                        for ( $i = 1; $i <= $numpages; $i++ ) {
 
777
                                $link = $r['link_before'] . str_replace( '%', $i, $r['pagelink'] ) . $r['link_after'];
 
778
                                if ( $i != $page || ! $more && 1 == $page ) {
 
779
                                        $link = _wp_link_page( $i ) . $link . '</a>';
 
780
                                }
 
781
                                /**
 
782
                                 * Filter the HTML output of individual page number links.
 
783
                                 *
 
784
                                 * @since 3.6.0
 
785
                                 *
 
786
                                 * @param string $link The page number HTML output.
 
787
                                 * @param int    $i    Page number for paginated posts' page links.
 
788
                                 */
 
789
                                $link = apply_filters( 'wp_link_pages_link', $link, $i );
 
790
                                $output .= $r['separator'] . $link;
 
791
                        }
 
792
                        $output .= $r['after'];
 
793
                } elseif ( $more ) {
 
794
                        $output .= $r['before'];
 
795
                        $prev = $page - 1;
 
796
                        if ( $prev ) {
 
797
                                $link = _wp_link_page( $prev ) . $r['link_before'] . $r['previouspagelink'] . $r['link_after'] . '</a>';
 
798
 
 
799
                                /** This filter is documented in wp-includes/post-template.php */
 
800
                                $link = apply_filters( 'wp_link_pages_link', $link, $prev );
 
801
                                $output .= $r['separator'] . $link;
 
802
                        }
 
803
                        $next = $page + 1;
 
804
                        if ( $next <= $numpages ) {
 
805
                                $link = _wp_link_page( $next ) . $r['link_before'] . $r['nextpagelink'] . $r['link_after'] . '</a>';
 
806
 
 
807
                                /** This filter is documented in wp-includes/post-template.php */
 
808
                                $link = apply_filters( 'wp_link_pages_link', $link, $next );
 
809
                                $output .= $r['separator'] . $link;
 
810
                        }
 
811
                        $output .= $r['after'];
 
812
                }
 
813
        }
 
814
 
 
815
        /**
 
816
         * Filter the HTML output of page links for paginated posts.
 
817
         *
 
818
         * @since 3.6.0
 
819
         *
 
820
         * @param string $output HTML output of paginated posts' page links.
 
821
         * @param array  $args   An array of arguments.
 
822
         */
 
823
        $html = apply_filters( 'wp_link_pages', $output, $args );
 
824
 
 
825
        if ( $r['echo'] ) {
 
826
                echo $html;
 
827
        }
 
828
        return $html;
 
829
}
 
830
 
 
831
/**
 
832
 * Helper function for wp_link_pages().
 
833
 *
 
834
 * @since 3.1.0
 
835
 * @access private
 
836
 *
 
837
 * @param int $i Page number.
 
838
 * @return string Link.
 
839
 */
 
840
function _wp_link_page( $i ) {
 
841
        global $wp_rewrite;
 
842
        $post = get_post();
 
843
 
 
844
        if ( 1 == $i ) {
 
845
                $url = get_permalink();
 
846
        } else {
 
847
                if ( '' == get_option('permalink_structure') || in_array($post->post_status, array('draft', 'pending')) )
 
848
                        $url = add_query_arg( 'page', $i, get_permalink() );
 
849
                elseif ( 'page' == get_option('show_on_front') && get_option('page_on_front') == $post->ID )
 
850
                        $url = trailingslashit(get_permalink()) . user_trailingslashit("$wp_rewrite->pagination_base/" . $i, 'single_paged');
 
851
                else
 
852
                        $url = trailingslashit(get_permalink()) . user_trailingslashit($i, 'single_paged');
 
853
        }
 
854
 
 
855
        if ( is_preview() ) {
 
856
                $url = add_query_arg( array(
 
857
                        'preview' => 'true'
 
858
                ), $url );
 
859
 
 
860
                if ( ( 'draft' !== $post->post_status ) && isset( $_GET['preview_id'], $_GET['preview_nonce'] ) ) {
 
861
                        $url = add_query_arg( array(
 
862
                                'preview_id'    => wp_unslash( $_GET['preview_id'] ),
 
863
                                'preview_nonce' => wp_unslash( $_GET['preview_nonce'] )
 
864
                        ), $url );
 
865
                }
 
866
        }
 
867
 
 
868
        return '<a href="' . esc_url( $url ) . '">';
 
869
}
 
870
 
 
871
//
 
872
// Post-meta: Custom per-post fields.
 
873
//
 
874
 
 
875
/**
 
876
 * Retrieve post custom meta data field.
 
877
 *
 
878
 * @since 1.5.0
 
879
 *
 
880
 * @param string $key Meta data key name.
 
881
 * @return bool|string|array Array of values or single value, if only one element exists. False will be returned if key does not exist.
 
882
 */
 
883
function post_custom( $key = '' ) {
 
884
        $custom = get_post_custom();
 
885
 
 
886
        if ( !isset( $custom[$key] ) )
 
887
                return false;
 
888
        elseif ( 1 == count($custom[$key]) )
 
889
                return $custom[$key][0];
 
890
        else
 
891
                return $custom[$key];
 
892
}
 
893
 
 
894
/**
 
895
 * Display list of post custom fields.
 
896
 *
 
897
 * @internal This will probably change at some point...
 
898
 * @since 1.2.0
 
899
 * @uses apply_filters() Calls 'the_meta_key' on list item HTML content, with key and value as separate parameters.
 
900
 */
 
901
function the_meta() {
 
902
        if ( $keys = get_post_custom_keys() ) {
 
903
                echo "<ul class='post-meta'>\n";
 
904
                foreach ( (array) $keys as $key ) {
 
905
                        $keyt = trim($key);
 
906
                        if ( is_protected_meta( $keyt, 'post' ) )
 
907
                                continue;
 
908
                        $values = array_map('trim', get_post_custom_values($key));
 
909
                        $value = implode($values,', ');
 
910
 
 
911
                        /**
 
912
                         * Filter the HTML output of the li element in the post custom fields list.
 
913
                         *
 
914
                         * @since 2.2.0
 
915
                         *
 
916
                         * @param string $html  The HTML output for the li element.
 
917
                         * @param string $key   Meta key.
 
918
                         * @param string $value Meta value.
 
919
                         */
 
920
                        echo apply_filters( 'the_meta_key', "<li><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value );
 
921
                }
 
922
                echo "</ul>\n";
 
923
        }
 
924
}
 
925
 
 
926
//
 
927
// Pages
 
928
//
 
929
 
 
930
/**
 
931
 * Retrieve or display list of pages as a dropdown (select list).
 
932
 *
 
933
 * @since 2.1.0
 
934
 *
 
935
 * @param array|string $args Optional. Override default arguments.
 
936
 * @return string HTML content, if not displaying.
 
937
 */
 
938
function wp_dropdown_pages( $args = '' ) {
 
939
        $defaults = array(
 
940
                'depth' => 0, 'child_of' => 0,
 
941
                'selected' => 0, 'echo' => 1,
 
942
                'name' => 'page_id', 'id' => '',
 
943
                'show_option_none' => '', 'show_option_no_change' => '',
 
944
                'option_none_value' => ''
 
945
        );
 
946
 
 
947
        $r = wp_parse_args( $args, $defaults );
 
948
 
 
949
        $pages = get_pages( $r );
 
950
        $output = '';
 
951
        // Back-compat with old system where both id and name were based on $name argument
 
952
        if ( empty( $r['id'] ) ) {
 
953
                $r['id'] = $r['name'];
 
954
        }
 
955
 
 
956
        if ( ! empty( $pages ) ) {
 
957
                $output = "<select name='" . esc_attr( $r['name'] ) . "' id='" . esc_attr( $r['id'] ) . "'>\n";
 
958
                if ( $r['show_option_no_change'] ) {
 
959
                        $output .= "\t<option value=\"-1\">" . $r['show_option_no_change'] . "</option>\n";
 
960
                }
 
961
                if ( $r['show_option_none'] ) {
 
962
                        $output .= "\t<option value=\"" . esc_attr( $r['option_none_value'] ) . '">' . $r['show_option_none'] . "</option>\n";
 
963
                }
 
964
                $output .= walk_page_dropdown_tree( $pages, $r['depth'], $r );
 
965
                $output .= "</select>\n";
 
966
        }
 
967
 
 
968
        /**
 
969
         * Filter the HTML output of a list of pages as a drop down.
 
970
         *
 
971
         * @since 2.1.0
 
972
         *
 
973
         * @param string $output HTML output for drop down list of pages.
 
974
         */
 
975
        $html = apply_filters( 'wp_dropdown_pages', $output );
 
976
 
 
977
        if ( $r['echo'] ) {
 
978
                echo $html;
 
979
        }
 
980
        return $html;
 
981
}
 
982
 
 
983
/**
 
984
 * Retrieve or display list of pages in list (li) format.
 
985
 *
 
986
 * @since 1.5.0
 
987
 *
 
988
 * @see get_pages()
 
989
 *
 
990
 * @param array|string $args {
 
991
 *     Array or string of arguments. Optional.
 
992
 *
 
993
 *     @type int    $child_of     Display only the sub-pages of a single page by ID. Default 0 (all pages).
 
994
 *     @type string $authors      Comma-separated list of author IDs. Default empty (all authors).
 
995
 *     @type string $date_format  PHP date format to use for the listed pages. Relies on the 'show_date' parameter.
 
996
 *                                Default is the value of 'date_format' option.
 
997
 *     @type int    $depth        Number of levels in the hierarchy of pages to include in the generated list.
 
998
 *                                Accepts -1 (any depth), 0 (all pages), 1 (top-level pages only), and n (pages to
 
999
 *                                the given n depth). Default 0.
 
1000
 *     @type bool   $echo         Whether or not to echo the list of pages. Default true.
 
1001
 *     @type string $exclude      Comma-separated list of page IDs to exclude. Default empty.
 
1002
 *     @type array  $include      Comma-separated list of page IDs to include. Default empty.
 
1003
 *     @type string $link_after   Text or HTML to follow the page link label. Default null.
 
1004
 *     @type string $link_before  Text or HTML to precede the page link label. Default null.
 
1005
 *     @type string $post_type    Post type to query for. Default 'page'.
 
1006
 *     @type string $post_status  Comma-separated list of post statuses to include. Default 'publish'.
 
1007
 *     @type string $show_date    Whether to display the page publish or modified date for each page. Accepts
 
1008
 *                                'modified' or any other value. An empty value hides the date. Default empty.
 
1009
 *     @type string $sort_column  Comma-separated list of column names to sort the pages by. Accepts 'post_author',
 
1010
 *                                'post_date', 'post_title', 'post_name', 'post_modified', 'post_modified_gmt',
 
1011
 *                                'menu_order', 'post_parent', 'ID', 'rand', or 'comment_count'. Default 'post_title'.
 
1012
 *     @type string $title_li     List heading. Passing a null or empty value will result in no heading, and the list
 
1013
 *                                will not be wrapped with unordered list `<ul>` tags. Default 'Pages'.
 
1014
 *     @type Walker $walker       Walker instance to use for listing pages. Default empty (Walker_Page).
 
1015
 * }
 
1016
 * @return string HTML list of pages.
 
1017
 */
 
1018
function wp_list_pages( $args = '' ) {
 
1019
        $defaults = array(
 
1020
                'depth' => 0, 'show_date' => '',
 
1021
                'date_format' => get_option( 'date_format' ),
 
1022
                'child_of' => 0, 'exclude' => '',
 
1023
                'title_li' => __( 'Pages' ), 'echo' => 1,
 
1024
                'authors' => '', 'sort_column' => 'menu_order, post_title',
 
1025
                'link_before' => '', 'link_after' => '', 'walker' => '',
 
1026
        );
 
1027
 
 
1028
        $r = wp_parse_args( $args, $defaults );
 
1029
 
 
1030
        $output = '';
 
1031
        $current_page = 0;
 
1032
 
 
1033
        // sanitize, mostly to keep spaces out
 
1034
        $r['exclude'] = preg_replace( '/[^0-9,]/', '', $r['exclude'] );
 
1035
 
 
1036
        // Allow plugins to filter an array of excluded pages (but don't put a nullstring into the array)
 
1037
        $exclude_array = ( $r['exclude'] ) ? explode( ',', $r['exclude'] ) : array();
 
1038
 
 
1039
        /**
 
1040
         * Filter the array of pages to exclude from the pages list.
 
1041
         *
 
1042
         * @since 2.1.0
 
1043
         *
 
1044
         * @param array $exclude_array An array of page IDs to exclude.
 
1045
         */
 
1046
        $r['exclude'] = implode( ',', apply_filters( 'wp_list_pages_excludes', $exclude_array ) );
 
1047
 
 
1048
        // Query pages.
 
1049
        $r['hierarchical'] = 0;
 
1050
        $pages = get_pages( $r );
 
1051
 
 
1052
        if ( ! empty( $pages ) ) {
 
1053
                if ( $r['title_li'] ) {
 
1054
                        $output .= '<li class="pagenav">' . $r['title_li'] . '<ul>';
 
1055
                }
 
1056
                global $wp_query;
 
1057
                if ( is_page() || is_attachment() || $wp_query->is_posts_page ) {
 
1058
                        $current_page = get_queried_object_id();
 
1059
                } elseif ( is_singular() ) {
 
1060
                        $queried_object = get_queried_object();
 
1061
                        if ( is_post_type_hierarchical( $queried_object->post_type ) ) {
 
1062
                                $current_page = $queried_object->ID;
 
1063
                        }
 
1064
                }
 
1065
 
 
1066
                $output .= walk_page_tree( $pages, $r['depth'], $current_page, $r );
 
1067
 
 
1068
                if ( $r['title_li'] ) {
 
1069
                        $output .= '</ul></li>';
 
1070
                }
 
1071
        }
 
1072
 
 
1073
        /**
 
1074
         * Filter the HTML output of the pages to list.
 
1075
         *
 
1076
         * @since 1.5.1
 
1077
         *
 
1078
         * @see wp_list_pages()
 
1079
         *
 
1080
         * @param string $output HTML output of the pages list.
 
1081
         * @param array  $r      An array of page-listing arguments.
 
1082
         */
 
1083
        $html = apply_filters( 'wp_list_pages', $output, $r );
 
1084
 
 
1085
        if ( $r['echo'] ) {
 
1086
                echo $html;
 
1087
        } else {
 
1088
                return $html;
 
1089
        }
 
1090
}
 
1091
 
 
1092
/**
 
1093
 * Display or retrieve list of pages with optional home link.
 
1094
 *
 
1095
 * The arguments are listed below and part of the arguments are for {@link
 
1096
 * wp_list_pages()} function. Check that function for more info on those
 
1097
 * arguments.
 
1098
 *
 
1099
 * @since 2.7.0
 
1100
 *
 
1101
 * @param array|string $args {
 
1102
 *     Optional. Arguments to generate a page menu. {@see wp_list_pages()}
 
1103
 *     for additional arguments.
 
1104
 *
 
1105
 * @type string     $sort_column How to short the list of pages. Accepts post column names.
 
1106
 *                               Default 'menu_order, post_title'.
 
1107
 * @type string     $menu_class  Class to use for the div ID containing the page list. Default 'menu'.
 
1108
 * @type bool       $echo        Whether to echo the list or return it. Accepts true (echo) or false (return).
 
1109
 *                               Default true.
 
1110
 * @type string     $link_before The HTML or text to prepend to $show_home text. Default empty.
 
1111
 * @type string     $link_after  The HTML or text to append to $show_home text. Default empty.
 
1112
 * @type int|string $show_home   Whether to display the link to the home page. Can just enter the text
 
1113
 *                               you'd like shown for the home link. 1|true defaults to 'Home'.
 
1114
 * }
 
1115
 * @return string html menu
 
1116
 */
 
1117
function wp_page_menu( $args = array() ) {
 
1118
        $defaults = array('sort_column' => 'menu_order, post_title', 'menu_class' => 'menu', 'echo' => true, 'link_before' => '', 'link_after' => '');
 
1119
        $args = wp_parse_args( $args, $defaults );
 
1120
 
 
1121
        /**
 
1122
         * Filter the arguments used to generate a page-based menu.
 
1123
         *
 
1124
         * @since 2.7.0
 
1125
         *
 
1126
         * @see wp_page_menu()
 
1127
         *
 
1128
         * @param array $args An array of page menu arguments.
 
1129
         */
 
1130
        $args = apply_filters( 'wp_page_menu_args', $args );
 
1131
 
 
1132
        $menu = '';
 
1133
 
 
1134
        $list_args = $args;
 
1135
 
 
1136
        // Show Home in the menu
 
1137
        if ( ! empty($args['show_home']) ) {
 
1138
                if ( true === $args['show_home'] || '1' === $args['show_home'] || 1 === $args['show_home'] )
 
1139
                        $text = __('Home');
 
1140
                else
 
1141
                        $text = $args['show_home'];
 
1142
                $class = '';
 
1143
                if ( is_front_page() && !is_paged() )
 
1144
                        $class = 'class="current_page_item"';
 
1145
                $menu .= '<li ' . $class . '><a href="' . home_url( '/' ) . '">' . $args['link_before'] . $text . $args['link_after'] . '</a></li>';
 
1146
                // If the front page is a page, add it to the exclude list
 
1147
                if (get_option('show_on_front') == 'page') {
 
1148
                        if ( !empty( $list_args['exclude'] ) ) {
 
1149
                                $list_args['exclude'] .= ',';
 
1150
                        } else {
 
1151
                                $list_args['exclude'] = '';
 
1152
                        }
 
1153
                        $list_args['exclude'] .= get_option('page_on_front');
 
1154
                }
 
1155
        }
 
1156
 
 
1157
        $list_args['echo'] = false;
 
1158
        $list_args['title_li'] = '';
 
1159
        $menu .= str_replace( array( "\r", "\n", "\t" ), '', wp_list_pages($list_args) );
 
1160
 
 
1161
        if ( $menu )
 
1162
                $menu = '<ul>' . $menu . '</ul>';
 
1163
 
 
1164
        $menu = '<div class="' . esc_attr($args['menu_class']) . '">' . $menu . "</div>\n";
 
1165
 
 
1166
        /**
 
1167
         * Filter the HTML output of a page-based menu.
 
1168
         *
 
1169
         * @since 2.7.0
 
1170
         *
 
1171
         * @see wp_page_menu()
 
1172
         *
 
1173
         * @param string $menu The HTML output.
 
1174
         * @param array  $args An array of arguments.
 
1175
         */
 
1176
        $menu = apply_filters( 'wp_page_menu', $menu, $args );
 
1177
        if ( $args['echo'] )
 
1178
                echo $menu;
 
1179
        else
 
1180
                return $menu;
 
1181
}
 
1182
 
 
1183
//
 
1184
// Page helpers
 
1185
//
 
1186
 
 
1187
/**
 
1188
 * Retrieve HTML list content for page list.
 
1189
 *
 
1190
 * @uses Walker_Page to create HTML list content.
 
1191
 * @since 2.1.0
 
1192
 * @see Walker_Page::walk() for parameters and return description.
 
1193
 */
 
1194
function walk_page_tree($pages, $depth, $current_page, $r) {
 
1195
        if ( empty($r['walker']) )
 
1196
                $walker = new Walker_Page;
 
1197
        else
 
1198
                $walker = $r['walker'];
 
1199
 
 
1200
        foreach ( (array) $pages as $page ) {
 
1201
                if ( $page->post_parent )
 
1202
                        $r['pages_with_children'][ $page->post_parent ] = true;
 
1203
        }
 
1204
 
 
1205
        $args = array($pages, $depth, $r, $current_page);
 
1206
        return call_user_func_array(array($walker, 'walk'), $args);
 
1207
}
 
1208
 
 
1209
/**
 
1210
 * Retrieve HTML dropdown (select) content for page list.
 
1211
 *
 
1212
 * @uses Walker_PageDropdown to create HTML dropdown content.
 
1213
 * @since 2.1.0
 
1214
 * @see Walker_PageDropdown::walk() for parameters and return description.
 
1215
 */
 
1216
function walk_page_dropdown_tree() {
 
1217
        $args = func_get_args();
 
1218
        if ( empty($args[2]['walker']) ) // the user's options are the third parameter
 
1219
                $walker = new Walker_PageDropdown;
 
1220
        else
 
1221
                $walker = $args[2]['walker'];
 
1222
 
 
1223
        return call_user_func_array(array($walker, 'walk'), $args);
 
1224
}
 
1225
 
 
1226
/**
 
1227
 * Create HTML list of pages.
 
1228
 *
 
1229
 * @since 2.1.0
 
1230
 * @uses Walker
 
1231
 */
 
1232
class Walker_Page extends Walker {
 
1233
        /**
 
1234
         * @see Walker::$tree_type
 
1235
         * @since 2.1.0
 
1236
         * @var string
 
1237
         */
 
1238
        public $tree_type = 'page';
 
1239
 
 
1240
        /**
 
1241
         * @see Walker::$db_fields
 
1242
         * @since 2.1.0
 
1243
         * @todo Decouple this.
 
1244
         * @var array
 
1245
         */
 
1246
        public $db_fields = array ('parent' => 'post_parent', 'id' => 'ID');
 
1247
 
 
1248
        /**
 
1249
         * @see Walker::start_lvl()
 
1250
         * @since 2.1.0
 
1251
         *
 
1252
         * @param string $output Passed by reference. Used to append additional content.
 
1253
         * @param int $depth Depth of page. Used for padding.
 
1254
         * @param array $args
 
1255
         */
 
1256
        public function start_lvl( &$output, $depth = 0, $args = array() ) {
 
1257
                $indent = str_repeat("\t", $depth);
 
1258
                $output .= "\n$indent<ul class='children'>\n";
 
1259
        }
 
1260
 
 
1261
        /**
 
1262
         * @see Walker::end_lvl()
 
1263
         * @since 2.1.0
 
1264
         *
 
1265
         * @param string $output Passed by reference. Used to append additional content.
 
1266
         * @param int $depth Depth of page. Used for padding.
 
1267
         * @param array $args
 
1268
         */
 
1269
        public function end_lvl( &$output, $depth = 0, $args = array() ) {
 
1270
                $indent = str_repeat("\t", $depth);
 
1271
                $output .= "$indent</ul>\n";
 
1272
        }
 
1273
 
 
1274
        /**
 
1275
         * @see Walker::start_el()
 
1276
         * @since 2.1.0
 
1277
         *
 
1278
         * @param string $output Passed by reference. Used to append additional content.
 
1279
         * @param object $page Page data object.
 
1280
         * @param int $depth Depth of page. Used for padding.
 
1281
         * @param int $current_page Page ID.
 
1282
         * @param array $args
 
1283
         */
 
1284
        public function start_el( &$output, $page, $depth = 0, $args = array(), $current_page = 0 ) {
 
1285
                if ( $depth ) {
 
1286
                        $indent = str_repeat( "\t", $depth );
 
1287
                } else {
 
1288
                        $indent = '';
 
1289
                }
 
1290
 
 
1291
                $css_class = array( 'page_item', 'page-item-' . $page->ID );
 
1292
 
 
1293
                if ( isset( $args['pages_with_children'][ $page->ID ] ) ) {
 
1294
                        $css_class[] = 'page_item_has_children';
 
1295
                }
 
1296
 
 
1297
                if ( ! empty( $current_page ) ) {
 
1298
                        $_current_page = get_post( $current_page );
 
1299
                        if ( in_array( $page->ID, $_current_page->ancestors ) ) {
 
1300
                                $css_class[] = 'current_page_ancestor';
 
1301
                        }
 
1302
                        if ( $page->ID == $current_page ) {
 
1303
                                $css_class[] = 'current_page_item';
 
1304
                        } elseif ( $_current_page && $page->ID == $_current_page->post_parent ) {
 
1305
                                $css_class[] = 'current_page_parent';
 
1306
                        }
 
1307
                } elseif ( $page->ID == get_option('page_for_posts') ) {
 
1308
                        $css_class[] = 'current_page_parent';
 
1309
                }
 
1310
 
 
1311
                /**
 
1312
                 * Filter the list of CSS classes to include with each page item in the list.
 
1313
                 *
 
1314
                 * @since 2.8.0
 
1315
                 *
 
1316
                 * @see wp_list_pages()
 
1317
                 *
 
1318
                 * @param array   $css_class    An array of CSS classes to be applied
 
1319
                 *                             to each list item.
 
1320
                 * @param WP_Post $page         Page data object.
 
1321
                 * @param int     $depth        Depth of page, used for padding.
 
1322
                 * @param array   $args         An array of arguments.
 
1323
                 * @param int     $current_page ID of the current page.
 
1324
                 */
 
1325
                $css_classes = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page ) );
 
1326
 
 
1327
                if ( '' === $page->post_title ) {
 
1328
                        $page->post_title = sprintf( __( '#%d (no title)' ), $page->ID );
 
1329
                }
 
1330
 
 
1331
                $args['link_before'] = empty( $args['link_before'] ) ? '' : $args['link_before'];
 
1332
                $args['link_after'] = empty( $args['link_after'] ) ? '' : $args['link_after'];
 
1333
 
 
1334
                /** This filter is documented in wp-includes/post-template.php */
 
1335
                $output .= $indent . sprintf(
 
1336
                        '<li class="%s"><a href="%s">%s%s%s</a>',
 
1337
                        $css_classes,
 
1338
                        get_permalink( $page->ID ),
 
1339
                        $args['link_before'],
 
1340
                        apply_filters( 'the_title', $page->post_title, $page->ID ),
 
1341
                        $args['link_after']
 
1342
                );
 
1343
 
 
1344
                if ( ! empty( $args['show_date'] ) ) {
 
1345
                        if ( 'modified' == $args['show_date'] ) {
 
1346
                                $time = $page->post_modified;
 
1347
                        } else {
 
1348
                                $time = $page->post_date;
 
1349
                        }
 
1350
 
 
1351
                        $date_format = empty( $args['date_format'] ) ? '' : $args['date_format'];
 
1352
                        $output .= " " . mysql2date( $date_format, $time );
 
1353
                }
 
1354
        }
 
1355
 
 
1356
        /**
 
1357
         * @see Walker::end_el()
 
1358
         * @since 2.1.0
 
1359
         *
 
1360
         * @param string $output Passed by reference. Used to append additional content.
 
1361
         * @param object $page Page data object. Not used.
 
1362
         * @param int $depth Depth of page. Not Used.
 
1363
         * @param array $args
 
1364
         */
 
1365
        public function end_el( &$output, $page, $depth = 0, $args = array() ) {
 
1366
                $output .= "</li>\n";
 
1367
        }
 
1368
 
 
1369
}
 
1370
 
 
1371
/**
 
1372
 * Create HTML dropdown list of pages.
 
1373
 *
 
1374
 * @since 2.1.0
 
1375
 * @uses Walker
 
1376
 */
 
1377
class Walker_PageDropdown extends Walker {
 
1378
        /**
 
1379
         * @see Walker::$tree_type
 
1380
         * @since 2.1.0
 
1381
         * @var string
 
1382
         */
 
1383
        public $tree_type = 'page';
 
1384
 
 
1385
        /**
 
1386
         * @see Walker::$db_fields
 
1387
         * @since 2.1.0
 
1388
         * @todo Decouple this
 
1389
         * @var array
 
1390
         */
 
1391
        public $db_fields = array ('parent' => 'post_parent', 'id' => 'ID');
 
1392
 
 
1393
        /**
 
1394
         * @see Walker::start_el()
 
1395
         * @since 2.1.0
 
1396
         *
 
1397
         * @param string $output Passed by reference. Used to append additional content.
 
1398
         * @param object $page Page data object.
 
1399
         * @param int $depth Depth of page in reference to parent pages. Used for padding.
 
1400
         * @param array $args Uses 'selected' argument for selected page to set selected HTML attribute for option element.
 
1401
         * @param int $id
 
1402
         */
 
1403
        public function start_el( &$output, $page, $depth = 0, $args = array(), $id = 0 ) {
 
1404
                $pad = str_repeat('&nbsp;', $depth * 3);
 
1405
 
 
1406
                $output .= "\t<option class=\"level-$depth\" value=\"$page->ID\"";
 
1407
                if ( $page->ID == $args['selected'] )
 
1408
                        $output .= ' selected="selected"';
 
1409
                $output .= '>';
 
1410
 
 
1411
                $title = $page->post_title;
 
1412
                if ( '' === $title ) {
 
1413
                        $title = sprintf( __( '#%d (no title)' ), $page->ID );
 
1414
                }
 
1415
 
 
1416
                /**
 
1417
                 * Filter the page title when creating an HTML drop-down list of pages.
 
1418
                 *
 
1419
                 * @since 3.1.0
 
1420
                 *
 
1421
                 * @param string $title Page title.
 
1422
                 * @param object $page  Page data object.
 
1423
                 */
 
1424
                $title = apply_filters( 'list_pages', $title, $page );
 
1425
                $output .= $pad . esc_html( $title );
 
1426
                $output .= "</option>\n";
 
1427
        }
 
1428
}
 
1429
 
 
1430
//
 
1431
// Attachments
 
1432
//
 
1433
 
 
1434
/**
 
1435
 * Display an attachment page link using an image or icon.
 
1436
 *
 
1437
 * @since 2.0.0
 
1438
 *
 
1439
 * @param int|WP_Post $id Optional. Post ID or post object.
 
1440
 * @param bool $fullsize Optional, default is false. Whether to use full size.
 
1441
 * @param bool $deprecated Deprecated. Not used.
 
1442
 * @param bool $permalink Optional, default is false. Whether to include permalink.
 
1443
 */
 
1444
function the_attachment_link( $id = 0, $fullsize = false, $deprecated = false, $permalink = false ) {
 
1445
        if ( !empty( $deprecated ) )
 
1446
                _deprecated_argument( __FUNCTION__, '2.5' );
 
1447
 
 
1448
        if ( $fullsize )
 
1449
                echo wp_get_attachment_link($id, 'full', $permalink);
 
1450
        else
 
1451
                echo wp_get_attachment_link($id, 'thumbnail', $permalink);
 
1452
}
 
1453
 
 
1454
/**
 
1455
 * Retrieve an attachment page link using an image or icon, if possible.
 
1456
 *
 
1457
 * @since 2.5.0
 
1458
 * @uses apply_filters() Calls 'wp_get_attachment_link' filter on HTML content with same parameters as function.
 
1459
 *
 
1460
 * @param int|WP_Post $id Optional. Post ID or post object.
 
1461
 * @param string $size Optional, default is 'thumbnail'. Size of image, either array or string.
 
1462
 * @param bool $permalink Optional, default is false. Whether to add permalink to image.
 
1463
 * @param bool $icon Optional, default is false. Whether to include icon.
 
1464
 * @param string|bool $text Optional, default is false. If string, then will be link text.
 
1465
 * @return string HTML content.
 
1466
 */
 
1467
function wp_get_attachment_link( $id = 0, $size = 'thumbnail', $permalink = false, $icon = false, $text = false ) {
 
1468
        $id = intval( $id );
 
1469
        $_post = get_post( $id );
 
1470
 
 
1471
        if ( empty( $_post ) || ( 'attachment' != $_post->post_type ) || ! $url = wp_get_attachment_url( $_post->ID ) )
 
1472
                return __( 'Missing Attachment' );
 
1473
 
 
1474
        if ( $permalink )
 
1475
                $url = get_attachment_link( $_post->ID );
 
1476
 
 
1477
        if ( $text )
 
1478
                $link_text = $text;
 
1479
        elseif ( $size && 'none' != $size )
 
1480
                $link_text = wp_get_attachment_image( $id, $size, $icon );
 
1481
        else
 
1482
                $link_text = '';
 
1483
 
 
1484
        if ( trim( $link_text ) == '' )
 
1485
                $link_text = $_post->post_title;
 
1486
 
 
1487
        /**
 
1488
         * Filter a retrieved attachment page link.
 
1489
         *
 
1490
         * @since 2.7.0
 
1491
         *
 
1492
         * @param string      $link_html The page link HTML output.
 
1493
         * @param int         $id        Post ID.
 
1494
         * @param string      $size      Image size. Default 'thumbnail'.
 
1495
         * @param bool        $permalink Whether to add permalink to image. Default false.
 
1496
         * @param bool        $icon      Whether to include an icon. Default false.
 
1497
         * @param string|bool $text      If string, will be link text. Default false.
 
1498
         */
 
1499
        return apply_filters( 'wp_get_attachment_link', "<a href='$url'>$link_text</a>", $id, $size, $permalink, $icon, $text );
 
1500
}
 
1501
 
 
1502
/**
 
1503
 * Wrap attachment in <<p>> element before content.
 
1504
 *
 
1505
 * @since 2.0.0
 
1506
 *
 
1507
 * @param string $content
 
1508
 * @return string
 
1509
 */
 
1510
function prepend_attachment($content) {
 
1511
        $post = get_post();
 
1512
 
 
1513
        if ( empty($post->post_type) || $post->post_type != 'attachment' )
 
1514
                return $content;
 
1515
 
 
1516
        if ( 0 === strpos( $post->post_mime_type, 'video' ) ) {
 
1517
                $meta = wp_get_attachment_metadata( get_the_ID() );
 
1518
                $atts = array( 'src' => wp_get_attachment_url() );
 
1519
                if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
 
1520
                        $atts['width'] = (int) $meta['width'];
 
1521
                        $atts['height'] = (int) $meta['height'];
 
1522
                }
 
1523
                if ( has_post_thumbnail() ) {
 
1524
                        $atts['poster'] = wp_get_attachment_url( get_post_thumbnail_id() );
 
1525
                }
 
1526
                $p = wp_video_shortcode( $atts );
 
1527
        } elseif ( 0 === strpos( $post->post_mime_type, 'audio' ) ) {
 
1528
                $p = wp_audio_shortcode( array( 'src' => wp_get_attachment_url() ) );
 
1529
        } else {
 
1530
                $p = '<p class="attachment">';
 
1531
                // show the medium sized image representation of the attachment if available, and link to the raw file
 
1532
                $p .= wp_get_attachment_link(0, 'medium', false);
 
1533
                $p .= '</p>';
 
1534
        }
 
1535
 
 
1536
        /**
 
1537
         * Filter the attachment markup to be prepended to the post content.
 
1538
         *
 
1539
         * @since 2.0.0
 
1540
         *
 
1541
         * @see prepend_attachment()
 
1542
         *
 
1543
         * @param string $p The attachment HTML output.
 
1544
         */
 
1545
        $p = apply_filters( 'prepend_attachment', $p );
 
1546
 
 
1547
        return "$p\n$content";
 
1548
}
 
1549
 
 
1550
//
 
1551
// Misc
 
1552
//
 
1553
 
 
1554
/**
 
1555
 * Retrieve protected post password form content.
 
1556
 *
 
1557
 * @since 1.0.0
 
1558
 *
 
1559
 * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
 
1560
 * @return string HTML content for password form for password protected post.
 
1561
 */
 
1562
function get_the_password_form( $post = 0 ) {
 
1563
        $post = get_post( $post );
 
1564
        $label = 'pwbox-' . ( empty($post->ID) ? rand() : $post->ID );
 
1565
        $output = '<form action="' . esc_url( site_url( 'wp-login.php?action=postpass', 'login_post' ) ) . '" class="post-password-form" method="post">
 
1566
        <p>' . __( 'This content is password protected. To view it please enter your password below:' ) . '</p>
 
1567
        <p><label for="' . $label . '">' . __( 'Password:' ) . ' <input name="post_password" id="' . $label . '" type="password" size="20" /></label> <input type="submit" name="Submit" value="' . esc_attr__( 'Submit' ) . '" /></p></form>
 
1568
        ';
 
1569
 
 
1570
        /**
 
1571
         * Filter the HTML output for the protected post password form.
 
1572
         *
 
1573
         * If modifying the password field, please note that the core database schema
 
1574
         * limits the password field to 20 characters regardless of the value of the
 
1575
         * size attribute in the form input.
 
1576
         *
 
1577
         * @since 2.7.0
 
1578
         *
 
1579
         * @param string $output The password form HTML output.
 
1580
         */
 
1581
        return apply_filters( 'the_password_form', $output );
 
1582
}
 
1583
 
 
1584
/**
 
1585
 * Whether currently in a page template.
 
1586
 *
 
1587
 * This template tag allows you to determine if you are in a page template.
 
1588
 * You can optionally provide a template name and then the check will be
 
1589
 * specific to that template.
 
1590
 *
 
1591
 * @since 2.5.0
 
1592
 * @uses $wp_query
 
1593
 *
 
1594
 * @param string $template The specific template name if specific matching is required.
 
1595
 * @return bool True on success, false on failure.
 
1596
 */
 
1597
function is_page_template( $template = '' ) {
 
1598
        if ( ! is_page() )
 
1599
                return false;
 
1600
 
 
1601
        $page_template = get_page_template_slug( get_queried_object_id() );
 
1602
 
 
1603
        if ( empty( $template ) )
 
1604
                return (bool) $page_template;
 
1605
 
 
1606
        if ( $template == $page_template )
 
1607
                return true;
 
1608
 
 
1609
        if ( 'default' == $template && ! $page_template )
 
1610
                return true;
 
1611
 
 
1612
        return false;
 
1613
}
 
1614
 
 
1615
/**
 
1616
 * Get the specific template name for a page.
 
1617
 *
 
1618
 * @since 3.4.0
 
1619
 *
 
1620
 * @param int $post_id Optional. The page ID to check. Defaults to the current post, when used in the loop.
 
1621
 * @return string|bool Page template filename. Returns an empty string when the default page template
 
1622
 *      is in use. Returns false if the post is not a page.
 
1623
 */
 
1624
function get_page_template_slug( $post_id = null ) {
 
1625
        $post = get_post( $post_id );
 
1626
        if ( ! $post || 'page' != $post->post_type )
 
1627
                return false;
 
1628
        $template = get_post_meta( $post->ID, '_wp_page_template', true );
 
1629
        if ( ! $template || 'default' == $template )
 
1630
                return '';
 
1631
        return $template;
 
1632
}
 
1633
 
 
1634
/**
 
1635
 * Retrieve formatted date timestamp of a revision (linked to that revisions's page).
 
1636
 *
 
1637
 * @since 2.6.0
 
1638
 *
 
1639
 * @uses date_i18n()
 
1640
 *
 
1641
 * @param int|object $revision Revision ID or revision object.
 
1642
 * @param bool $link Optional, default is true. Link to revisions's page?
 
1643
 * @return string i18n formatted datetimestamp or localized 'Current Revision'.
 
1644
 */
 
1645
function wp_post_revision_title( $revision, $link = true ) {
 
1646
        if ( !$revision = get_post( $revision ) )
 
1647
                return $revision;
 
1648
 
 
1649
        if ( !in_array( $revision->post_type, array( 'post', 'page', 'revision' ) ) )
 
1650
                return false;
 
1651
 
 
1652
        /* translators: revision date format, see http://php.net/date */
 
1653
        $datef = _x( 'j F, Y @ G:i', 'revision date format');
 
1654
        /* translators: 1: date */
 
1655
        $autosavef = _x( '%1$s [Autosave]', 'post revision title extra' );
 
1656
        /* translators: 1: date */
 
1657
        $currentf  = _x( '%1$s [Current Revision]', 'post revision title extra' );
 
1658
 
 
1659
        $date = date_i18n( $datef, strtotime( $revision->post_modified ) );
 
1660
        if ( $link && current_user_can( 'edit_post', $revision->ID ) && $link = get_edit_post_link( $revision->ID ) )
 
1661
                $date = "<a href='$link'>$date</a>";
 
1662
 
 
1663
        if ( !wp_is_post_revision( $revision ) )
 
1664
                $date = sprintf( $currentf, $date );
 
1665
        elseif ( wp_is_post_autosave( $revision ) )
 
1666
                $date = sprintf( $autosavef, $date );
 
1667
 
 
1668
        return $date;
 
1669
}
 
1670
 
 
1671
/**
 
1672
 * Retrieve formatted date timestamp of a revision (linked to that revisions's page).
 
1673
 *
 
1674
 * @since 3.6.0
 
1675
 *
 
1676
 * @uses date_i18n()
 
1677
 *
 
1678
 * @param int|object $revision Revision ID or revision object.
 
1679
 * @param bool $link Optional, default is true. Link to revisions's page?
 
1680
 * @return string gravatar, user, i18n formatted datetimestamp or localized 'Current Revision'.
 
1681
 */
 
1682
function wp_post_revision_title_expanded( $revision, $link = true ) {
 
1683
        if ( !$revision = get_post( $revision ) )
 
1684
                return $revision;
 
1685
 
 
1686
        if ( !in_array( $revision->post_type, array( 'post', 'page', 'revision' ) ) )
 
1687
                return false;
 
1688
 
 
1689
        $author = get_the_author_meta( 'display_name', $revision->post_author );
 
1690
        /* translators: revision date format, see http://php.net/date */
 
1691
        $datef = _x( 'j F, Y @ G:i:s', 'revision date format');
 
1692
 
 
1693
        $gravatar = get_avatar( $revision->post_author, 24 );
 
1694
 
 
1695
        $date = date_i18n( $datef, strtotime( $revision->post_modified ) );
 
1696
        if ( $link && current_user_can( 'edit_post', $revision->ID ) && $link = get_edit_post_link( $revision->ID ) )
 
1697
                $date = "<a href='$link'>$date</a>";
 
1698
 
 
1699
        $revision_date_author = sprintf(
 
1700
                /* translators: post revision title: 1: author avatar, 2: author name, 3: time ago, 4: date */
 
1701
                _x( '%1$s %2$s, %3$s ago (%4$s)', 'post revision title' ),
 
1702
                $gravatar,
 
1703
                $author,
 
1704
                human_time_diff( strtotime( $revision->post_modified ), current_time( 'timestamp' ) ),
 
1705
                $date
 
1706
        );
 
1707
 
 
1708
        $autosavef = __( '%1$s [Autosave]' );
 
1709
        $currentf  = __( '%1$s [Current Revision]' );
 
1710
 
 
1711
        if ( !wp_is_post_revision( $revision ) )
 
1712
                $revision_date_author = sprintf( $currentf, $revision_date_author );
 
1713
        elseif ( wp_is_post_autosave( $revision ) )
 
1714
                $revision_date_author = sprintf( $autosavef, $revision_date_author );
 
1715
 
 
1716
        return $revision_date_author;
 
1717
}
 
1718
 
 
1719
/**
 
1720
 * Display list of a post's revisions.
 
1721
 *
 
1722
 * Can output either a UL with edit links or a TABLE with diff interface, and
 
1723
 * restore action links.
 
1724
 *
 
1725
 * @since 2.6.0
 
1726
 *
 
1727
 * @uses wp_get_post_revisions()
 
1728
 * @uses wp_post_revision_title_expanded()
 
1729
 * @uses get_edit_post_link()
 
1730
 * @uses get_the_author_meta()
 
1731
 *
 
1732
 * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default is global $post.
 
1733
 * @param string $type 'all' (default), 'revision' or 'autosave'
 
1734
 * @return null
 
1735
 */
 
1736
function wp_list_post_revisions( $post_id = 0, $type = 'all' ) {
 
1737
        if ( ! $post = get_post( $post_id ) )
 
1738
                return;
 
1739
 
 
1740
        // $args array with (parent, format, right, left, type) deprecated since 3.6
 
1741
        if ( is_array( $type ) ) {
 
1742
                $type = ! empty( $type['type'] ) ? $type['type']  : $type;
 
1743
                _deprecated_argument( __FUNCTION__, '3.6' );
 
1744
        }
 
1745
 
 
1746
        if ( ! $revisions = wp_get_post_revisions( $post->ID ) )
 
1747
                return;
 
1748
 
 
1749
        $rows = '';
 
1750
        foreach ( $revisions as $revision ) {
 
1751
                if ( ! current_user_can( 'read_post', $revision->ID ) )
 
1752
                        continue;
 
1753
 
 
1754
                $is_autosave = wp_is_post_autosave( $revision );
 
1755
                if ( ( 'revision' === $type && $is_autosave ) || ( 'autosave' === $type && ! $is_autosave ) )
 
1756
                        continue;
 
1757
 
 
1758
                $rows .= "\t<li>" . wp_post_revision_title_expanded( $revision ) . "</li>\n";
 
1759
        }
 
1760
 
 
1761
        echo "<div class='hide-if-js'><p>" . __( 'JavaScript must be enabled to use this feature.' ) . "</p></div>\n";
 
1762
 
 
1763
        echo "<ul class='post-revisions hide-if-no-js'>\n";
 
1764
        echo $rows;
 
1765
        echo "</ul>";
 
1766
}