PageRenderTime 321ms CodeModel.GetById 91ms app.highlight 113ms RepoModel.GetById 68ms app.codeStats 1ms

/wp-includes/post-template.php

https://github.com/dedavidd/piratenpartij.nl
PHP | 1780 lines | 1262 code | 120 blank | 398 comment | 131 complexity | 19e9ef17148f38d5ea2ace8995297f2a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file