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