tected_title_format, $post_title );
} elseif ( isset( $post->post_status ) && 'private' === $post->post_status ) {
/* translators: %s: Private post title. */
$prepend = __( 'Private: %s' );
/**
* Filters the text prepended to the post title of private posts.
*
* The filter is only applied on the front end.
*
* @since 2.8.0
*
* @param string $prepend Text displayed before the post title.
* Default 'Private: %s'.
* @param WP_Post $post Current post object.
*/
$private_title_format = apply_filters( 'private_title_format', $prepend, $post );
$post_title = sprintf( $private_title_format, $post_title );
}
}
/**
* Filters the post title.
*
* @since 0.71
*
* @param string $post_title The post title.
* @param int $post_id The post ID.
*/
return apply_filters( 'the_title', $post_title, $post_id );
}
/**
* Displays the Post Global Unique Identifier (guid).
*
* The guid will appear to be a link, but should not be used as a link to the
* post. The reason you should not use it as a link, is because of moving the
* blog across domains.
*
* URL is escaped to make it XML-safe.
*
* @since 1.5.0
*
* @param int|WP_Post $post Optional. Post ID or post object. Default is global $post.
*/
function the_guid( $post = 0 ) {
$post = get_post( $post );
$post_guid = isset( $post->guid ) ? get_the_guid( $post ) : '';
$post_id = isset( $post->ID ) ? $post->ID : 0;
/**
* Filters the escaped Global Unique Identifier (guid) of the post.
*
* @since 4.2.0
*
* @see get_the_guid()
*
* @param string $post_guid Escaped Global Unique Identifier (guid) of the post.
* @param int $post_id The post ID.
*/
echo apply_filters( 'the_guid', $post_guid, $post_id );
}
/**
* Retrieves the Post Global Unique Identifier (guid).
*
* The guid will appear to be a link, but should not be used as an link to the
* post. The reason you should not use it as a link, is because of moving the
* blog across domains.
*
* @since 1.5.0
*
* @param int|WP_Post $post Optional. Post ID or post object. Default is global $post.
* @return string
*/
function get_the_guid( $post = 0 ) {
$post = get_post( $post );
$post_guid = isset( $post->guid ) ? $post->guid : '';
$post_id = isset( $post->ID ) ? $post->ID : 0;
/**
* Filters the Global Unique Identifier (guid) of the post.
*
* @since 1.5.0
*
* @param string $post_guid Global Unique Identifier (guid) of the post.
* @param int $post_id The post ID.
*/
return apply_filters( 'get_the_guid', $post_guid, $post_id );
}
/**
* Displays the post content.
*
* @since 0.71
*
* @param string $more_link_text Optional. Content for when there is more text.
* @param bool $strip_teaser Optional. Strip teaser content before the more text. Default false.
*/
function the_content( $more_link_text = null, $strip_teaser = false ) {
$content = get_the_content( $more_link_text, $strip_teaser );
/**
* Filters the post content.
*
* @since 0.71
*
* @param string $content Content of the current post.
*/
$content = apply_filters( 'the_content', $content );
$content = str_replace( ']]>', ']]>', $content );
echo $content;
}
/**
* Retrieves the post content.
*
* @since 0.71
* @since 5.2.0 Added the `$post` parameter.
*
* @global int $page Page number of a single post/page.
* @global int $more Boolean indicator for whether single post/page is being viewed.
* @global bool $preview Whether post/page is in preview mode.
* @global array $pages Array of all pages in post/page. Each array element contains
* part of the content separated by the `` tag.
* @global int $multipage Boolean indicator for whether multiple pages are in play.
*
* @param string $more_link_text Optional. Content for when there is more text.
* @param bool $strip_teaser Optional. Strip teaser content before the more text. Default false.
* @param WP_Post|object|int $post Optional. WP_Post instance or Post ID/object. Default null.
* @return string
*/
function get_the_content( $more_link_text = null, $strip_teaser = false, $post = null ) {
global $page, $more, $preview, $pages, $multipage;
$_post = get_post( $post );
if ( ! ( $_post instanceof WP_Post ) ) {
return '';
}
/*
* Use the globals if the $post parameter was not specified,
* but only after they have been set up in setup_postdata().
*/
if ( null === $post && did_action( 'the_post' ) ) {
$elements = compact( 'page', 'more', 'preview', 'pages', 'multipage' );
} else {
$elements = generate_postdata( $_post );
}
if ( null === $more_link_text ) {
$more_link_text = sprintf(
'%2$s',
sprintf(
/* translators: %s: Post title. */
__( 'Continue reading %s' ),
the_title_attribute(
array(
'echo' => false,
'post' => $_post,
)
)
),
__( '(more…)' )
);
}
$output = '';
$has_teaser = false;
// If post password required and it doesn't match the cookie.
if ( post_password_required( $_post ) ) {
return get_the_password_form( $_post );
}
// If the requested page doesn't exist.
if ( $elements['page'] > count( $elements['pages'] ) ) {
// Give them the highest numbered page that DOES exist.
$elements['page'] = count( $elements['pages'] );
}
$page_no = $elements['page'];
$content = $elements['pages'][ $page_no - 1 ];
if ( preg_match( '//', $content, $matches ) ) {
if ( has_block( 'more', $content ) ) {
// Remove the core/more block delimiters. They will be left over after $content is split up.
$content = preg_replace( '//', '', $content );
}
$content = explode( $matches[0], $content, 2 );
if ( ! empty( $matches[1] ) && ! empty( $more_link_text ) ) {
$more_link_text = strip_tags( wp_kses_no_null( trim( $matches[1] ) ) );
}
$has_teaser = true;
} else {
$content = array( $content );
}
if ( str_contains( $_post->post_content, '' )
&& ( ! $elements['multipage'] || 1 === $elements['page'] )
) {
$strip_teaser = true;
}
$teaser = $content[0];
if ( $elements['more'] && $strip_teaser && $has_teaser ) {
$teaser = '';
}
$output .= $teaser;
if ( count( $content ) > 1 ) {
if ( $elements['more'] ) {
$output .= '' . $content[1];
} else {
if ( ! empty( $more_link_text ) ) {
/**
* Filters the Read More link text.
*
* @since 2.8.0
*
* @param string $more_link_element Read More link element.
* @param string $more_link_text Read More text.
*/
$output .= apply_filters( 'the_content_more_link', ' ID}\" class=\"more-link\">$more_link_text", $more_link_text );
}
$output = force_balance_tags( $output );
}
}
return $output;
}
/**
* Displays the post excerpt.
*
* @since 0.71
*/
function the_excerpt() {
/**
* Filters the displayed post excerpt.
*
* @since 0.71
*
* @see get_the_excerpt()
*
* @param string $post_excerpt The post excerpt.
*/
echo apply_filters( 'the_excerpt', get_the_excerpt() );
}
/**
* Retrieves the post excerpt.
*
* @since 0.71
* @since 4.5.0 Introduced the `$post` parameter.
*
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
* @return string Post excerpt.
*/
function get_the_excerpt( $post = null ) {
if ( is_bool( $post ) ) {
_deprecated_argument( __FUNCTION__, '2.3.0' );
}
$post = get_post( $post );
if ( empty( $post ) ) {
return '';
}
if ( post_password_required( $post ) ) {
return __( 'There is no excerpt because this is a protected post.' );
}
/**
* Filters the retrieved post excerpt.
*
* @since 1.2.0
* @since 4.5.0 Introduced the `$post` parameter.
*
* @param string $post_excerpt The post excerpt.
* @param WP_Post $post Post object.
*/
return apply_filters( 'get_the_excerpt', $post->post_excerpt, $post );
}
/**
* Determines whether the post has a custom excerpt.
*
* For more information on this and similar theme functions, check out
* the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
* Conditional Tags} article in the Theme Developer Handbook.
*
* @since 2.3.0
*
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
* @return bool True if the post has a custom excerpt, false otherwise.
*/
function has_excerpt( $post = 0 ) {
$post = get_post( $post );
return ( ! empty( $post->post_excerpt ) );
}
/**
* Displays the classes for the post container element.
*
* @since 2.7.0
*
* @param string|string[] $css_class Optional. One or more classes to add to the class list.
* Default empty.
* @param int|WP_Post $post Optional. Post ID or post object. Defaults to the global `$post`.
*/
function post_class( $css_class = '', $post = null ) {
// Separates classes with a single space, collates classes for post DIV.
echo 'class="' . esc_attr( implode( ' ', get_post_class( $css_class, $post ) ) ) . '"';
}
/**
* Retrieves an array of the class names for the post container element.
*
* The class names are many:
*
* - If the post has a post thumbnail, `has-post-thumbnail` is added as a class.
* - If the post is sticky, then the `sticky` class name is added.
* - The class `hentry` is always added to each post.
* - For each taxonomy that the post belongs to, a class will be added of the format
* `{$taxonomy}-{$slug}`, e.g. `category-foo` or `my_custom_taxonomy-bar`.
* The `post_tag` taxonomy is a special case; the class has the `tag-` prefix
* instead of `post_tag-`.
*
* All class names are passed through the filter, {@see 'post_class'}, followed by
* `$css_class` parameter value, with the post ID as the last parameter.
*
* @since 2.7.0
* @since 4.2.0 Custom taxonomy class names were added.
*
* @param string|string[] $css_class Optional. Space-separated string or array of class names
* to add to the class list. Default empty.
* @param int|WP_Post $post Optional. Post ID or post object.
* @return string[] Array of class names.
*/
function get_post_class( $css_class = '', $post = null ) {
$post = get_post( $post );
$classes = array();
if ( $css_class ) {
if ( ! is_array( $css_class ) ) {
$css_class = preg_split( '#\s+#', $css_class );
}
$classes = array_map( 'esc_attr', $css_class );
} else {
// Ensure that we always coerce class to being an array.
$css_class = array();
}
if ( ! $post ) {
return $classes;
}
$classes[] = 'post-' . $post->ID;
if ( ! is_admin() ) {
$classes[] = $post->post_type;
}
$classes[] = 'type-' . $post->post_type;
$classes[] = 'status-' . $post->post_status;
// Post Format.
if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
$post_format = get_post_format( $post->ID );
if ( $post_format && ! is_wp_error( $post_format ) ) {
$classes[] = 'format-' . sanitize_html_class( $post_format );
} else {
$classes[] = 'format-standard';
}
}
$post_password_required = post_password_required( $post->ID );
// Post requires password.
if ( $post_password_required ) {
$classes[] = 'post-password-required';
} elseif ( ! empty( $post->post_password ) ) {
$classes[] = 'post-password-protected';
}
// Post thumbnails.
if ( current_theme_supports( 'post-thumbnails' ) && has_post_thumbnail( $post->ID ) && ! is_attachment( $post ) && ! $post_password_required ) {
$classes[] = 'has-post-thumbnail';
}
// Sticky for Sticky Posts.
if ( is_sticky( $post->ID ) ) {
if ( is_home() && ! is_paged() ) {
$classes[] = 'sticky';
} elseif ( is_admin() ) {
$classes[] = 'status-sticky';
}
}
// hentry for hAtom compliance.
$classes[] = 'hentry';
// All public taxonomies.
$taxonomies = get_taxonomies( array( 'public' => true ) );
/**
* Filters the taxonomies to generate classes for each individual term.
*
* Default is all public taxonomies registered to the post type.
*
* @since 6.1.0
*
* @param string[] $taxonomies List of all taxonomy names to generate classes for.
* @param int $post_id The post ID.
* @param string[] $classes An array of post class names.
* @param string[] $css_class An array of additional class names added to the post.
*/
$taxonomies = apply_filters( 'post_class_taxonomies', $taxonomies, $post->ID, $classes, $css_class );
foreach ( (array) $taxonomies as $taxonomy ) {
if ( is_object_in_taxonomy( $post->post_type, $taxonomy ) ) {
foreach ( (array) get_the_terms( $post->ID, $taxonomy ) as $term ) {
if ( empty( $term->slug ) ) {
continue;
}
$term_class = sanitize_html_class( $term->slug, $term->term_id );
if ( is_numeric( $term_class ) || ! trim( $term_class, '-' ) ) {
$term_class = $term->term_id;
}
// 'post_tag' uses the 'tag' prefix for backward compatibility.
if ( 'post_tag' === $taxonomy ) {
$classes[] = 'tag-' . $term_class;
} else {
$classes[] = sanitize_html_class( $taxonomy . '-' . $term_class, $taxonomy . '-' . $term->term_id );
}
}
}
}
$classes = array_map( 'esc_attr', $classes );
/**
* Filters the list of CSS class names for the current post.
*
* @since 2.7.0
*
* @param string[] $classes An array of post class names.
* @param string[] $css_class An array of additional class names added to the post.
* @param int $post_id The post ID.
*/
$classes = apply_filters( 'post_class', $classes, $css_class, $post->ID );
return array_unique( $classes );
}
/**
* Displays the class names for the body element.
*
* @since 2.8.0
*
* @param string|string[] $css_class Optional. Space-separated string or array of class names
* to add to the class list. Default empty.
*/
function body_class( $css_class = '' ) {
// Separates class names with a single space, collates class names for body element.
echo 'class="' . esc_attr( implode( ' ', get_body_class( $css_class ) ) ) . '"';
}
/**
* Retrieves an array of the class names for the body element.
*
* @since 2.8.0
*
* @global WP_Query $wp_query WordPress Query object.
*
* @param string|string[] $css_class Optional. Space-separated string or array of class names
* to add to the class list. Default empty.
* @return string[] Array of class names.
*/
function get_body_class( $css_class = '' ) {
global $wp_query;
$classes = array();
if ( is_rtl() ) {
$classes[] = 'rtl';
}
if ( is_front_page() ) {
$classes[] = 'home';
}
if ( is_home() ) {
$classes[] = 'blog';
}
if ( is_privacy_policy() ) {
$classes[] = 'privacy-policy';
}
if ( is_archive() ) {
$classes[] = 'archive';
}
if ( is_date() ) {
$classes[] = 'date';
}
if ( is_search() ) {
$classes[] = 'search';
$classes[] = $wp_query->posts ? 'search-results' : 'search-no-results';
}
if ( is_paged() ) {
$classes[] = 'paged';
}
if ( is_attachment() ) {
$classes[] = 'attachment';
}
if ( is_404() ) {
$classes[] = 'error404';
}
if ( is_singular() ) {
$post = $wp_query->get_queried_object();
$post_id = $post->ID;
$post_type = $post->post_type;
if ( is_page_template() ) {
$classes[] = "{$post_type}-template";
$template_slug = get_page_template_slug( $post_id );
$template_parts = explode( '/', $template_slug );
foreach ( $template_parts as $part ) {
$classes[] = "{$post_type}-template-" . sanitize_html_class( str_replace( array( '.', '/' ), '-', basename( $part, '.php' ) ) );
}
$classes[] = "{$post_type}-template-" . sanitize_html_class( str_replace( '.', '-', $template_slug ) );
} else {
$classes[] = "{$post_type}-template-default";
}
if ( is_single() ) {
$classes[] = 'single';
if ( isset( $post->post_type ) ) {
$classes[] = 'single-' . sanitize_html_class( $post->post_type, $post_id );
$classes[] = 'postid-' . $post_id;
// Post Format.
if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
$post_format = get_post_format( $post->ID );
if ( $post_format && ! is_wp_error( $post_format ) ) {
$classes[] = 'single-format-' . sanitize_html_class( $post_format );
} else {
$classes[] = 'single-format-standard';
}
}
}
}
if ( is_attachment() ) {
$mime_type = get_post_mime_type( $post_id );
$mime_prefix = array( 'application/', 'image/', 'text/', 'audio/', 'video/', 'music/' );
$classes[] = 'attachmentid-' . $post_id;
$classes[] = 'attachment-' . str_replace( $mime_prefix, '', $mime_type );
} elseif ( is_page() ) {
$classes[] = 'page';
$classes[] = 'page-id-' . $post_id;
if ( get_pages(
array(
'parent' => $post_id,
'number' => 1,
)
) ) {
$classes[] = 'page-parent';
}
if ( $post->post_parent ) {
$classes[] = 'page-child';
$classes[] = 'parent-pageid-' . $post->post_parent;
}
}
} elseif ( is_archive() ) {
if ( is_post_type_archive() ) {
$classes[] = 'post-type-archive';
$post_type = get_query_var( 'post_type' );
if ( is_array( $post_type ) ) {
$post_type = reset( $post_type );
}
$classes[] = 'post-type-archive-' . sanitize_html_class( $post_type );
} elseif ( is_author() ) {
$author = $wp_query->get_queried_object();
$classes[] = 'author';
if ( isset( $author->user_nicename ) ) {
$classes[] = 'author-' . sanitize_html_class( $author->user_nicename, $author->ID );
$classes[] = 'author-' . $author->ID;
}
} elseif ( is_category() ) {
$cat = $wp_query->get_queried_object();
$classes[] = 'category';
if ( isset( $cat->term_id ) ) {
$cat_class = sanitize_html_class( $cat->slug, $cat->term_id );
if ( is_numeric( $cat_class ) || ! trim( $cat_class, '-' ) ) {
$cat_class = $cat->term_id;
}
$classes[] = 'category-' . $cat_class;
$classes[] = 'category-' . $cat->term_id;
}
} elseif ( is_tag() ) {
$tag = $wp_query->get_queried_object();
$classes[] = 'tag';
if ( isset( $tag->term_id ) ) {
$tag_class = sanitize_html_class( $tag->slug, $tag->term_id );
if ( is_numeric( $tag_class ) || ! trim( $tag_class, '-' ) ) {
$tag_class = $tag->term_id;
}
$classes[] = 'tag-' . $tag_class;
$classes[] = 'tag-' . $tag->term_id;
}
} elseif ( is_tax() ) {
$term = $wp_query->get_queried_object();
if ( isset( $term->term_id ) ) {
$term_class = sanitize_html_class( $term->slug, $term->term_id );
if ( is_numeric( $term_class ) || ! trim( $term_class, '-' ) ) {
$term_class = $term->term_id;
}
$classes[] = 'tax-' . sanitize_html_class( $term->taxonomy );
$classes[] = 'term-' . $term_class;
$classes[] = 'term-' . $term->term_id;
}
}
}
if ( is_user_logged_in() ) {
$classes[] = 'logged-in';
}
if ( is_admin_bar_showing() ) {
$classes[] = 'admin-bar';
$classes[] = 'no-customize-support';
}
if ( current_theme_supports( 'custom-background' )
&& ( get_background_color() !== get_theme_support( 'custom-background', 'default-color' ) || get_background_image() ) ) {
$classes[] = 'custom-background';
}
if ( has_custom_logo() ) {
$classes[] = 'wp-custom-logo';
}
if ( current_theme_supports( 'responsive-embeds' ) ) {
$classes[] = 'wp-embed-responsive';
}
$page = $wp_query->get( 'page' );
if ( ! $page || $page < 2 ) {
$page = $wp_query->get( 'paged' );
}
if ( $page && $page > 1 && ! is_404() ) {
$classes[] = 'paged-' . $page;
if ( is_single() ) {
$classes[] = 'single-paged-' . $page;
} elseif ( is_page() ) {
$classes[] = 'page-paged-' . $page;
} elseif ( is_category() ) {
$classes[] = 'category-paged-' . $page;
} elseif ( is_tag() ) {
$classes[] = 'tag-paged-' . $page;
} elseif ( is_date() ) {
$classes[] = 'date-paged-' . $page;
} elseif ( is_author() ) {
$classes[] = 'author-paged-' . $page;
} elseif ( is_search() ) {
$classes[] = 'search-paged-' . $page;
} elseif ( is_post_type_archive() ) {
$classes[] = 'post-type-paged-' . $page;
}
}
if ( ! empty( $css_class ) ) {
if ( ! is_array( $css_class ) ) {
$css_class = preg_split( '#\s+#', $css_class );
}
$classes = array_merge( $classes, $css_class );
} else {
// Ensure that we always coerce class to being an array.
$css_class = array();
}
$classes = array_map( 'esc_attr', $classes );
/**
* Filters the list of CSS body class names for the current post or page.
*
* @since 2.8.0
*
* @param string[] $classes An array of body class names.
* @param string[] $css_class An array of additional class names added to the body.
*/
$classes = apply_filters( 'body_class', $classes, $css_class );
return array_unique( $classes );
}
/**
* Determines whether the post requires password and whether a correct password has been provided.
*
* @since 2.7.0
*
* @param int|WP_Post|null $post An optional post. Global $post used if not provided.
* @return bool false if a password is not required or the correct password cookie is present, true otherwise.
*/
function post_password_required( $post = null ) {
$post = get_post( $post );
if ( empty( $post->post_password ) ) {
/** This filter is documented in wp-includes/post-template.php */
return apply_filters( 'post_password_required', false, $post );
}
if ( ! isset( $_COOKIE[ 'wp-postpass_' . COOKIEHASH ] ) ) {
/** This filter is documented in wp-includes/post-template.php */
return apply_filters( 'post_password_required', true, $post );
}
require_once ABSPATH . WPINC . '/class-phpass.php';
$hasher = new PasswordHash( 8, true );
$hash = wp_unslash( $_COOKIE[ 'wp-postpass_' . COOKIEHASH ] );
if ( ! str_starts_with( $hash, '$P$B' ) ) {
$required = true;
} else {
$required = ! $hasher->CheckPassword( $post->post_password, $hash );
}
/**
* Filters whether a post requires the user to supply a password.
*
* @since 4.7.0
*
* @param bool $required Whether the user needs to supply a password. True if password has not been
* provided or is incorrect, false if password has been supplied or is not required.
* @param WP_Post $post Post object.
*/
return apply_filters( 'post_password_required', $required, $post );
}
//
// Page Template Functions for usage in Themes.
//
/**
* The formatted output of a list of pages.
*
* Displays page links for paginated posts (i.e. including the ``
* Quicktag one or more times). This tag must be within The Loop.
*
* @since 1.2.0
* @since 5.1.0 Added the `aria_current` argument.
*
* @global int $page
* @global int $numpages
* @global int $multipage
* @global int $more
*
* @param string|array $args {
* Optional. Array or string of default arguments.
*
* @type string $before HTML or text to prepend to each link. Default is `
Pages:`.
* @type string $after HTML or text to append to each link. Default is `
';
// If the front page is a page, add it to the exclude list.
if ( 'page' === get_option( 'show_on_front' ) ) {
if ( ! empty( $list_args['exclude'] ) ) {
$list_args['exclude'] .= ',';
} else {
$list_args['exclude'] = '';
}
$list_args['exclude'] .= get_option( 'page_on_front' );
}
}
$list_args['echo'] = false;
$list_args['title_li'] = '';
$menu .= wp_list_pages( $list_args );
$container = sanitize_text_field( $args['container'] );
// Fallback in case `wp_nav_menu()` was called without a container.
if ( empty( $container ) ) {
$container = 'div';
}
if ( $menu ) {
// wp_nav_menu() doesn't set before and after.
if ( isset( $args['fallback_cb'] ) &&
'wp_page_menu' === $args['fallback_cb'] &&
'ul' !== $container ) {
$args['before'] = "
{$n}";
$args['after'] = '
';
}
$menu = $args['before'] . $menu . $args['after'];
}
$attrs = '';
if ( ! empty( $args['menu_id'] ) ) {
$attrs .= ' id="' . esc_attr( $args['menu_id'] ) . '"';
}
if ( ! empty( $args['menu_class'] ) ) {
$attrs .= ' class="' . esc_attr( $args['menu_class'] ) . '"';
}
$menu = "<{$container}{$attrs}>" . $menu . "{$container}>{$n}";
/**
* Filters the HTML output of a page-based menu.
*
* @since 2.7.0
*
* @see wp_page_menu()
*
* @param string $menu The HTML output.
* @param array $args An array of arguments. See wp_page_menu()
* for information on accepted arguments.
*/
$menu = apply_filters( 'wp_page_menu', $menu, $args );
if ( $args['echo'] ) {
echo $menu;
} else {
return $menu;
}
}
//
// Page helpers.
//
/**
* Retrieves HTML list content for page list.
*
* @uses Walker_Page to create HTML list content.
* @since 2.1.0
*
* @param array $pages
* @param int $depth
* @param int $current_page
* @param array $args
* @return string
*/
function walk_page_tree( $pages, $depth, $current_page, $args ) {
if ( empty( $args['walker'] ) ) {
$walker = new Walker_Page();
} else {
/**
* @var Walker $walker
*/
$walker = $args['walker'];
}
foreach ( (array) $pages as $page ) {
if ( $page->post_parent ) {
$args['pages_with_children'][ $page->post_parent ] = true;
}
}
return $walker->walk( $pages, $depth, $args, $current_page );
}
/**
* Retrieves HTML dropdown (select) content for page list.
*
* @since 2.1.0
* @since 5.3.0 Formalized the existing `...$args` parameter by adding it
* to the function signature.
*
* @uses Walker_PageDropdown to create HTML dropdown content.
* @see Walker_PageDropdown::walk() for parameters and return description.
*
* @param mixed ...$args Elements array, maximum hierarchical depth and optional additional arguments.
* @return string
*/
function walk_page_dropdown_tree( ...$args ) {
if ( empty( $args[2]['walker'] ) ) { // The user's options are the third parameter.
$walker = new Walker_PageDropdown();
} else {
/**
* @var Walker $walker
*/
$walker = $args[2]['walker'];
}
return $walker->walk( ...$args );
}
//
// Attachments.
//
/**
* Displays an attachment page link using an image or icon.
*
* @since 2.0.0
*
* @param int|WP_Post $post Optional. Post ID or post object.
* @param bool $fullsize Optional. Whether to use full size. Default false.
* @param bool $deprecated Deprecated. Not used.
* @param bool $permalink Optional. Whether to include permalink. Default false.
*/
function the_attachment_link( $post = 0, $fullsize = false, $deprecated = false, $permalink = false ) {
if ( ! empty( $deprecated ) ) {
_deprecated_argument( __FUNCTION__, '2.5.0' );
}
if ( $fullsize ) {
echo wp_get_attachment_link( $post, 'full', $permalink );
} else {
echo wp_get_attachment_link( $post, 'thumbnail', $permalink );
}
}
/**
* Retrieves an attachment page link using an image or icon, if possible.
*
* @since 2.5.0
* @since 4.4.0 The `$post` parameter can now accept either a post ID or `WP_Post` object.
*
* @param int|WP_Post $post Optional. Post ID or post object.
* @param string|int[] $size Optional. Image size. Accepts any registered image size name, or an array
* of width and height values in pixels (in that order). Default 'thumbnail'.
* @param bool $permalink Optional. Whether to add permalink to image. Default false.
* @param bool $icon Optional. Whether the attachment is an icon. Default false.
* @param string|false $text Optional. Link text to use. Activated by passing a string, false otherwise.
* Default false.
* @param array|string $attr Optional. Array or string of attributes. Default empty.
* @return string HTML content.
*/
function wp_get_attachment_link( $post = 0, $size = 'thumbnail', $permalink = false, $icon = false, $text = false, $attr = '' ) {
$_post = get_post( $post );
if ( empty( $_post ) || ( 'attachment' !== $_post->post_type ) || ! wp_get_attachment_url( $_post->ID ) ) {
return __( 'Missing Attachment' );
}
$url = wp_get_attachment_url( $_post->ID );
if ( $permalink ) {
$url = get_attachment_link( $_post->ID );
}
if ( $text ) {
$link_text = $text;
} elseif ( $size && 'none' !== $size ) {
$link_text = wp_get_attachment_image( $_post->ID, $size, $icon, $attr );
} else {
$link_text = '';
}
if ( '' === trim( $link_text ) ) {
$link_text = $_post->post_title;
}
if ( '' === trim( $link_text ) ) {
$link_text = esc_html( pathinfo( get_attached_file( $_post->ID ), PATHINFO_FILENAME ) );
}
/**
* Filters the list of attachment link attributes.
*
* @since 6.2.0
*
* @param array $attributes An array of attributes for the link markup,
* keyed on the attribute name.
* @param int $id Post ID.
*/
$attributes = apply_filters( 'wp_get_attachment_link_attributes', array( 'href' => $url ), $_post->ID );
$link_attributes = '';
foreach ( $attributes as $name => $value ) {
$value = 'href' === $name ? esc_url( $value ) : esc_attr( $value );
$link_attributes .= ' ' . esc_attr( $name ) . "='" . $value . "'";
}
$link_html = "$link_text";
/**
* Filters a retrieved attachment page link.
*
* @since 2.7.0
* @since 5.1.0 Added the `$attr` parameter.
*
* @param string $link_html The page link HTML output.
* @param int|WP_Post $post Post ID or object. Can be 0 for the current global post.
* @param string|int[] $size Requested image size. Can be any registered image size name, or
* an array of width and height values in pixels (in that order).
* @param bool $permalink Whether to add permalink to image. Default false.
* @param bool $icon Whether to include an icon.
* @param string|false $text If string, will be link text.
* @param array|string $attr Array or string of attributes.
*/
return apply_filters( 'wp_get_attachment_link', $link_html, $post, $size, $permalink, $icon, $text, $attr );
}
/**
* Wraps attachment in paragraph tag before content.
*
* @since 2.0.0
*
* @param string $content
* @return string
*/
function prepend_attachment( $content ) {
$post = get_post();
if ( empty( $post->post_type ) || 'attachment' !== $post->post_type ) {
return $content;
}
if ( wp_attachment_is( 'video', $post ) ) {
$meta = wp_get_attachment_metadata( get_the_ID() );
$atts = array( 'src' => wp_get_attachment_url() );
if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
$atts['width'] = (int) $meta['width'];
$atts['height'] = (int) $meta['height'];
}
if ( has_post_thumbnail() ) {
$atts['poster'] = wp_get_attachment_url( get_post_thumbnail_id() );
}
$p = wp_video_shortcode( $atts );
} elseif ( wp_attachment_is( 'audio', $post ) ) {
$p = wp_audio_shortcode( array( 'src' => wp_get_attachment_url() ) );
} else {
$p = '
';
// Show the medium sized image representation of the attachment if available, and link to the raw file.
$p .= wp_get_attachment_link( 0, 'medium', false );
$p .= '
';
}
/**
* Filters the attachment markup to be prepended to the post content.
*
* @since 2.0.0
*
* @see prepend_attachment()
*
* @param string $p The attachment HTML output.
*/
$p = apply_filters( 'prepend_attachment', $p );
return "$p\n$content";
}
//
// Misc.
//
/**
* Retrieves protected post password form content.
*
* @since 1.0.0
*
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
* @return string HTML content for password form for password protected post.
*/
function get_the_password_form( $post = 0 ) {
$post = get_post( $post );
$label = 'pwbox-' . ( empty( $post->ID ) ? rand() : $post->ID );
$output = '
';
/**
* Filters the HTML output for the protected post password form.
*
* If modifying the password field, please note that the core database schema
* limits the password field to 20 characters regardless of the value of the
* size attribute in the form input.
*
* @since 2.7.0
* @since 5.8.0 Added the `$post` parameter.
*
* @param string $output The password form HTML output.
* @param WP_Post $post Post object.
*/
return apply_filters( 'the_password_form', $output, $post );
}
/**
* Determines whether the current post uses a page template.
*
* This template tag allows you to determine if you are in a page template.
* You can optionally provide a template filename or array of template filenames
* and then the check will be specific to that template.
*
* For more information on this and similar theme functions, check out
* the {@link https://developer.wordpress.org/themes/basics/conditional-tags/
* Conditional Tags} article in the Theme Developer Handbook.
*
* @since 2.5.0
* @since 4.2.0 The `$template` parameter was changed to also accept an array of page templates.
* @since 4.7.0 Now works with any post type, not just pages.
*
* @param string|string[] $template The specific template filename or array of templates to match.
* @return bool True on success, false on failure.
*/
function is_page_template( $template = '' ) {
if ( ! is_singular() ) {
return false;
}
$page_template = get_page_template_slug( get_queried_object_id() );
if ( empty( $template ) ) {
return (bool) $page_template;
}
if ( $template === $page_template ) {
return true;
}
if ( is_array( $template ) ) {
if ( ( in_array( 'default', $template, true ) && ! $page_template )
|| in_array( $page_template, $template, true )
) {
return true;
}
}
return ( 'default' === $template && ! $page_template );
}
/**
* Gets the specific template filename for a given post.
*
* @since 3.4.0
* @since 4.7.0 Now works with any post type, not just pages.
*
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
* @return string|false Page template filename. Returns an empty string when the default page template
* is in use. Returns false if the post does not exist.
*/
function get_page_template_slug( $post = null ) {
$post = get_post( $post );
if ( ! $post ) {
return false;
}
$template = get_post_meta( $post->ID, '_wp_page_template', true );
if ( ! $template || 'default' === $template ) {
return '';
}
return $template;
}
/**
* Retrieves formatted date timestamp of a revision (linked to that revisions's page).
*
* @since 2.6.0
*
* @param int|WP_Post $revision Revision ID or revision object.
* @param bool $link Optional. Whether to link to revision's page. Default true.
* @return string|false i18n formatted datetimestamp or localized 'Current Revision'.
*/
function wp_post_revision_title( $revision, $link = true ) {
$revision = get_post( $revision );
if ( ! $revision ) {
return $revision;
}
if ( ! in_array( $revision->post_type, array( 'post', 'page', 'revision' ), true ) ) {
return false;
}
/* translators: Revision date format, see https://www.php.net/manual/datetime.format.php */
$datef = _x( 'F j, Y @ H:i:s', 'revision date format' );
/* translators: %s: Revision date. */
$autosavef = __( '%s [Autosave]' );
/* translators: %s: Revision date. */
$currentf = __( '%s [Current Revision]' );
$date = date_i18n( $datef, strtotime( $revision->post_modified ) );
$edit_link = get_edit_post_link( $revision->ID );
if ( $link && current_user_can( 'edit_post', $revision->ID ) && $edit_link ) {
$date = "$date";
}
if ( ! wp_is_post_revision( $revision ) ) {
$date = sprintf( $currentf, $date );
} elseif ( wp_is_post_autosave( $revision ) ) {
$date = sprintf( $autosavef, $date );
}
return $date;
}
/**
* Retrieves formatted date timestamp of a revision (linked to that revisions's page).
*
* @since 3.6.0
*
* @param int|WP_Post $revision Revision ID or revision object.
* @param bool $link Optional. Whether to link to revision's page. Default true.
* @return string|false gravatar, user, i18n formatted datetimestamp or localized 'Current Revision'.
*/
function wp_post_revision_title_expanded( $revision, $link = true ) {
$revision = get_post( $revision );
if ( ! $revision ) {
return $revision;
}
if ( ! in_array( $revision->post_type, array( 'post', 'page', 'revision' ), true ) ) {
return false;
}
$author = get_the_author_meta( 'display_name', $revision->post_author );
/* translators: Revision date format, see https://www.php.net/manual/datetime.format.php */
$datef = _x( 'F j, Y @ H:i:s', 'revision date format' );
$gravatar = get_avatar( $revision->post_author, 24 );
$date = date_i18n( $datef, strtotime( $revision->post_modified ) );
$edit_link = get_edit_post_link( $revision->ID );
if ( $link && current_user_can( 'edit_post', $revision->ID ) && $edit_link ) {
$date = "$date";
}
$revision_date_author = sprintf(
/* translators: Post revision title. 1: Author avatar, 2: Author name, 3: Time ago, 4: Date. */
__( '%1$s %2$s, %3$s ago (%4$s)' ),
$gravatar,
$author,
human_time_diff( strtotime( $revision->post_modified_gmt ) ),
$date
);
/* translators: %s: Revision date with author avatar. */
$autosavef = __( '%s [Autosave]' );
/* translators: %s: Revision date with author avatar. */
$currentf = __( '%s [Current Revision]' );
if ( ! wp_is_post_revision( $revision ) ) {
$revision_date_author = sprintf( $currentf, $revision_date_author );
} elseif ( wp_is_post_autosave( $revision ) ) {
$revision_date_author = sprintf( $autosavef, $revision_date_author );
}
/**
* Filters the formatted author and date for a revision.
*
* @since 4.4.0
*
* @param string $revision_date_author The formatted string.
* @param WP_Post $revision The revision object.
* @param bool $link Whether to link to the revisions page, as passed into
* wp_post_revision_title_expanded().
*/
return apply_filters( 'wp_post_revision_title_expanded', $revision_date_author, $revision, $link );
}
/**
* Displays a list of a post's revisions.
*
* Can output either a UL with edit links or a TABLE with diff interface, and
* restore action links.
*
* @since 2.6.0
*
* @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post.
* @param string $type 'all' (default), 'revision' or 'autosave'
*/
function wp_list_post_revisions( $post = 0, $type = 'all' ) {
$post = get_post( $post );
if ( ! $post ) {
return;
}
// $args array with (parent, format, right, left, type) deprecated since 3.6.
if ( is_array( $type ) ) {
$type = ! empty( $type['type'] ) ? $type['type'] : $type;
_deprecated_argument( __FUNCTION__, '3.6.0' );
}
$revisions = wp_get_post_revisions( $post->ID );
if ( ! $revisions ) {
return;
}
$rows = '';
foreach ( $revisions as $revision ) {
if ( ! current_user_can( 'read_post', $revision->ID ) ) {
continue;
}
$is_autosave = wp_is_post_autosave( $revision );
if ( ( 'revision' === $type && $is_autosave ) || ( 'autosave' === $type && ! $is_autosave ) ) {
continue;
}
$rows .= "\t
" . __( 'JavaScript must be enabled to use this feature.' ) . "
\n";
echo "
\n";
echo $rows;
echo '
';
}
/**
* Retrieves the parent post object for the given post.
*
* @since 5.7.0
*
* @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global $post.
* @return WP_Post|null Parent post object, or null if there isn't one.
*/
function get_post_parent( $post = null ) {
$wp_post = get_post( $post );
return ! empty( $wp_post->post_parent ) ? get_post( $wp_post->post_parent ) : null;
}
/**
* Returns whether the given post has a parent post.
*
* @since 5.7.0
*
* @param int|WP_Post|null $post Optional. Post ID or WP_Post object. Default is global $post.
* @return bool Whether the post has a parent post.
*/
function has_post_parent( $post = null ) {
return (bool) get_post_parent( $post );
}
e data value.
* @return bool True on success, false on failure.
*/
public function add_data( $handle, $key, $value ) {
if ( ! isset( $this->registered[ $handle ] ) ) {
return false;
}
return $this->registered[ $handle ]->add_data( $key, $value );
}
/**
* Get extra item data.
*
* Gets data associated with a registered item.
*
* @since 3.3.0
*
* @param string $handle Name of the item. Should be unique.
* @param string $key The data key.
* @return mixed Extra item data (string), false otherwise.
*/
public function get_data( $handle, $key ) {
if ( ! isset( $this->registered[ $handle ] ) ) {
return false;
}
if ( ! isset( $this->registered[ $handle ]->extra[ $key ] ) ) {
return false;
}
return $this->registered[ $handle ]->extra[ $key ];
}
/**
* Un-register an item or items.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string|string[] $handles Item handle (string) or item handles (array of strings).
*/
public function remove( $handles ) {
foreach ( (array) $handles as $handle ) {
unset( $this->registered[ $handle ] );
}
}
/**
* Queue an item or items.
*
* Decodes handles and arguments, then queues handles and stores
* arguments in the class property $args. For example in extending
* classes, $args is appended to the item url as a query string.
* Note $args is NOT the $args property of items in the $registered array.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string|string[] $handles Item handle (string) or item handles (array of strings).
*/
public function enqueue( $handles ) {
foreach ( (array) $handles as $handle ) {
$handle = explode( '?', $handle );
if ( ! in_array( $handle[0], $this->queue, true ) && isset( $this->registered[ $handle[0] ] ) ) {
$this->queue[] = $handle[0];
// Reset all dependencies so they must be recalculated in recurse_deps().
$this->all_queued_deps = null;
if ( isset( $handle[1] ) ) {
$this->args[ $handle[0] ] = $handle[1];
}
} elseif ( ! isset( $this->registered[ $handle[0] ] ) ) {
$this->queued_before_register[ $handle[0] ] = null; // $args
if ( isset( $handle[1] ) ) {
$this->queued_before_register[ $handle[0] ] = $handle[1];
}
}
}
}
/**
* Dequeue an item or items.
*
* Decodes handles and arguments, then dequeues handles
* and removes arguments from the class property $args.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string|string[] $handles Item handle (string) or item handles (array of strings).
*/
public function dequeue( $handles ) {
foreach ( (array) $handles as $handle ) {
$handle = explode( '?', $handle );
$key = array_search( $handle[0], $this->queue, true );
if ( false !== $key ) {
// Reset all dependencies so they must be recalculated in recurse_deps().
$this->all_queued_deps = null;
unset( $this->queue[ $key ] );
unset( $this->args[ $handle[0] ] );
} elseif ( array_key_exists( $handle[0], $this->queued_before_register ) ) {
unset( $this->queued_before_register[ $handle[0] ] );
}
}
}
/**
* Recursively search the passed dependency tree for a handle.
*
* @since 4.0.0
*
* @param string[] $queue An array of queued _WP_Dependency handles.
* @param string $handle Name of the item. Should be unique.
* @return bool Whether the handle is found after recursively searching the dependency tree.
*/
protected function recurse_deps( $queue, $handle ) {
if ( isset( $this->all_queued_deps ) ) {
return isset( $this->all_queued_deps[ $handle ] );
}
$all_deps = array_fill_keys( $queue, true );
$queues = array();
$done = array();
while ( $queue ) {
foreach ( $queue as $queued ) {
if ( ! isset( $done[ $queued ] ) && isset( $this->registered[ $queued ] ) ) {
$deps = $this->registered[ $queued ]->deps;
if ( $deps ) {
$all_deps += array_fill_keys( $deps, true );
array_push( $queues, $deps );
}
$done[ $queued ] = true;
}
}
$queue = array_pop( $queues );
}
$this->all_queued_deps = $all_deps;
return isset( $this->all_queued_deps[ $handle ] );
}
/**
* Query the list for an item.
*
* @since 2.1.0
* @since 2.6.0 Moved from `WP_Scripts`.
*
* @param string $handle Name of the item. Should be unique.
* @param string $status Optional. Status of the item to query. Default 'registered'.
* @return bool|_WP_Dependency Found, or object Item data.
*/
public function query( $handle, $status = 'registered' ) {
switch ( $status ) {
case 'registered':
case 'scripts': // Back compat.
if ( isset( $this->registered[ $handle ] ) ) {
return $this->registered[ $handle ];
}
return false;
case 'enqueued':
case 'queue': // Back compat.
if ( in_array( $handle, $this->queue, true ) ) {
return true;
}
return $this->recurse_deps( $this->queue, $handle );
case 'to_do':
case 'to_print': // Back compat.
return in_array( $handle, $this->to_do, true );
case 'done':
case 'printed': // Back compat.
return in_array( $handle, $this->done, true );
}
return false;
}
/**
* Set item group, unless already in a lower group.
*
* @since 2.8.0
*
* @param string $handle Name of the item. Should be unique.
* @param bool $recursion Internal flag that calling function was called recursively.
* @param int|false $group Group level: level (int), no group (false).
* @return bool Not already in the group or a lower group.
*/
public function set_group( $handle, $recursion, $group ) {
$group = (int) $group;
if ( isset( $this->groups[ $handle ] ) && $this->groups[ $handle ] <= $group ) {
return false;
}
$this->groups[ $handle ] = $group;
return true;
}
}