Themes: Improve document title output.

Introduces more flexibility in filtering all parts of the document title,the
separator, and a way to short-circuit title generation. Plugins can now also
check for theme support and reliably filter the entire output. See #18548.
Deprecates `wp_title()`.

Fixes #31078.


Built from https://develop.svn.wordpress.org/trunk@35294


git-svn-id: http://core.svn.wordpress.org/trunk@35260 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Konstantin Obenland 2015-10-20 16:21:25 +00:00
parent b8e250927f
commit c69e96422b
12 changed files with 316 additions and 230 deletions

View File

@ -3635,3 +3635,156 @@ function force_ssl_login( $force = null ) {
_deprecated_function( __FUNCTION__, '4.4', 'force_ssl_admin()' );
return force_ssl_admin( $force );
}
/**
* Formerly used to display or retrieve page title for all areas of blog.
*
* By default, the page title will display the separator before the page title,
* so that the blog title will be before the page title. This is not good for
* title display, since the blog title shows up on most tabs and not what is
* important, which is the page that the user is looking at.
*
* There are also SEO benefits to having the blog title after or to the 'right'
* or the page title. However, it is mostly common sense to have the blog title
* to the right with most browsers supporting tabs. You can achieve this by
* using the seplocation parameter and setting the value to 'right'. This change
* was introduced around 2.5.0, in case backwards compatibility of themes is
* important.
*
* @since 1.0.0
* @deprecated 4.4.0
* @deprecated Use add_theme_support( 'title-tag' );
*
* @param string $sep Optional, default is '»'. How to separate the various items within the page title.
* @param bool $display Optional, default is true. Whether to display or retrieve title.
* @param string $seplocation Optional. Direction to display title, 'right'.
* @return string|null String on retrieve, null when displaying.
*/
function wp_title( $sep = '»', $display = true, $seplocation = '' ) {
_deprecated_function( __FUNCTION__, '4.4', 'add_theme_support( \'title-tag\' )' );
global $wp_locale;
$m = get_query_var( 'm' );
$year = get_query_var( 'year' );
$monthnum = get_query_var( 'monthnum' );
$day = get_query_var( 'day' );
$search = get_query_var( 's' );
$title = '';
$t_sep = '%WP_TITILE_SEP%'; // Temporary separator, for accurate flipping, if necessary
// If there is a post
if ( is_single() || ( is_home() && ! is_front_page() ) || ( is_page() && ! is_front_page() ) ) {
$title = single_post_title( '', false );
}
// If there's a post type archive
if ( is_post_type_archive() ) {
$post_type = get_query_var( 'post_type' );
if ( is_array( $post_type ) ) {
$post_type = reset( $post_type );
}
$post_type_object = get_post_type_object( $post_type );
if ( ! $post_type_object->has_archive ) {
$title = post_type_archive_title( '', false );
}
}
// If there's a category or tag
if ( is_category() || is_tag() ) {
$title = single_term_title( '', false );
}
// If there's a taxonomy
if ( is_tax() ) {
$term = get_queried_object();
if ( $term ) {
$tax = get_taxonomy( $term->taxonomy );
$title = single_term_title( $tax->labels->name . $t_sep, false );
}
}
// If there's an author
if ( is_author() && ! is_post_type_archive() ) {
$author = get_queried_object();
if ( $author ) {
$title = $author->display_name;
}
}
// Post type archives with has_archive should override terms.
if ( is_post_type_archive() && $post_type_object->has_archive ) {
$title = post_type_archive_title( '', false );
}
// If there's a month
if ( is_archive() && ! empty( $m ) ) {
$my_year = substr( $m, 0, 4 );
$my_month = $wp_locale->get_month( substr( $m, 4, 2 ) );
$my_day = intval( substr( $m, 6, 2 ) );
$title = $my_year . ( $my_month ? $t_sep . $my_month : '' ) . ( $my_day ? $t_sep . $my_day : '' );
}
// If there's a year
if ( is_archive() && ! empty( $year ) ) {
$title = $year;
if ( ! empty( $monthnum ) ) {
$title .= $t_sep . $wp_locale->get_month( $monthnum );
}
if ( ! empty( $day ) ) {
$title .= $t_sep . zeroise( $day, 2 );
}
}
// If it's a search
if ( is_search() ) {
/* translators: 1: separator, 2: search phrase */
$title = sprintf( __( 'Search Results %1$s %2$s' ), $t_sep, strip_tags( $search ) );
}
// If it's a 404 page
if ( is_404() ) {
$title = __( 'Page not found' );
}
$prefix = '';
if ( ! empty( $title ) ) {
$prefix = " $sep ";
}
/**
* Filter the parts of the page title.
*
* @since 4.0.0
*
* @param array $title_array Parts of the page title.
*/
$title_array = apply_filters( 'wp_title_parts', explode( $t_sep, $title ) );
// Determines position of the separator and direction of the breadcrumb
if ( 'right' == $seplocation ) { // sep on right, so reverse the order
$title_array = array_reverse( $title_array );
$title = implode( " $sep ", $title_array ) . $prefix;
} else {
$title = $prefix . implode( " $sep ", $title_array );
}
/**
* Filter the text of the page title.
*
* @since 2.0.0
*
* @param string $title Page title.
* @param string $sep Title separator.
* @param string $seplocation Location of the separator (left or right).
*/
$title = apply_filters( 'wp_title', $title, $sep, $seplocation );
// Send it out
if ( $display ) {
echo $title;
} else {
return $title;
}
}

View File

@ -33,7 +33,7 @@ do_action( 'rss_tag_pre', 'atom-comments' );
elseif ( is_search() )
printf( ent2ncr( __( 'Comments for %1$s searching on %2$s' ) ), get_bloginfo_rss( 'name' ), get_search_query() );
else
printf( ent2ncr( __( 'Comments for %s' ) ), get_bloginfo_rss( 'name' ) . get_wp_title_rss() );
printf( ent2ncr( __( 'Comments for %s' ) ), get_wp_title_rss() );
?></title>
<subtitle type="text"><?php bloginfo_rss('description'); ?></subtitle>

View File

@ -27,7 +27,7 @@ do_action( 'rss_tag_pre', 'atom' );
do_action( 'atom_ns' );
?>
>
<title type="text"><?php bloginfo_rss('name'); wp_title_rss(); ?></title>
<title type="text"><?php wp_title_rss(); ?></title>
<subtitle type="text"><?php bloginfo_rss("description") ?></subtitle>
<updated><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></updated>

View File

@ -30,7 +30,7 @@ do_action( 'rss_tag_pre', 'rdf' );
?>
>
<channel rdf:about="<?php bloginfo_rss("url") ?>">
<title><?php bloginfo_rss('name'); wp_title_rss(); ?></title>
<title><?php wp_title_rss(); ?></title>
<link><?php bloginfo_rss('url') ?></link>
<description><?php bloginfo_rss('description') ?></description>
<dc:date><?php echo mysql2date('Y-m-d\TH:i:s\Z', get_lastpostmodified('GMT'), false); ?></dc:date>

View File

@ -11,7 +11,7 @@ $more = 1;
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>'; ?>
<rss version="0.92">
<channel>
<title><?php bloginfo_rss('name'); wp_title_rss(); ?></title>
<title><?php wp_title_rss(); ?></title>
<link><?php bloginfo_rss('url') ?></link>
<description><?php bloginfo_rss('description') ?></description>
<lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>

View File

@ -38,7 +38,7 @@ do_action( 'rss_tag_pre', 'rss2-comments' );
elseif ( is_search() )
printf( ent2ncr( __( 'Comments for %1$s searching on %2$s' ) ), get_bloginfo_rss( 'name' ), get_search_query() );
else
printf( ent2ncr( __( 'Comments for %s' ) ), get_bloginfo_rss( 'name' ) . get_wp_title_rss() );
printf( ent2ncr( __( 'Comments for %s' ) ), get_wp_title_rss() );
?></title>
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
<link><?php (is_single()) ? the_permalink_rss() : bloginfo_rss("url") ?></link>

View File

@ -38,7 +38,7 @@ do_action( 'rss_tag_pre', 'rss2' );
>
<channel>
<title><?php bloginfo_rss('name'); wp_title_rss(); ?></title>
<title><?php wp_title_rss(); ?></title>
<atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
<link><?php bloginfo_rss('url') ?></link>
<description><?php bloginfo_rss("description") ?></description>

View File

@ -91,53 +91,53 @@ function get_default_feed() {
* Retrieve the blog title for the feed title.
*
* @since 2.2.0
* @since 4.4.0 Deprecated argument.
*
* @param string $sep Optional. How to separate the title. See wp_title() for more info.
* @return string Error message on failure or blog title on success.
* @param string $deprecated Deprecated.
* @return string The document title.
*/
function get_wp_title_rss( $sep = '&#187;' ) {
$title = wp_title( $sep, false );
if ( is_wp_error( $title ) ) {
return $title->get_error_message();
}
if ( $title && $sep && ' ' !== substr( $title, 0, 1 ) ) {
$title = " $sep " . $title;
function get_wp_title_rss( $deprecated = '&#8211;' ) {
if ( '&#8211;' !== $deprecated ) {
_deprecated_argument( __FUNCTION__, '4.4.0', sprintf( __( 'Use the %s filter instead.' ), '<code>document_title_separator</code>' ) );
}
/**
* Filter the blog title for use as the feed title.
*
* @since 2.2.0
* @since 4.4.0 Deprecated argument.
*
* @param string $title The current blog title.
* @param string $sep Separator used by wp_title().
* @param string $deprecated Deprecated.
*/
$title = apply_filters( 'get_wp_title_rss', $title, $sep );
return $title;
return apply_filters( 'get_wp_title_rss', wp_get_document_title(), $deprecated );
}
/**
* Display the blog title for display of the feed title.
*
* @since 2.2.0
* @see wp_title() $sep parameter usage.
* @since 4.4.0 Deprecated argument.
*
* @param string $sep Optional.
* @param string $deprecated Optional.
*/
function wp_title_rss( $sep = '&#187;' ) {
function wp_title_rss( $deprecated = '&#8211;' ) {
if ( '&#8211;' !== $deprecated ) {
_deprecated_argument( __FUNCTION__, '4.4.0', sprintf( __( 'Use the %s filter instead.' ), '<code>document_title_separator</code>' ) );
}
/**
* Filter the blog title for display of the feed title.
*
* @since 2.2.0
* @since 4.4.0 Deprecated argument.
*
* @see get_wp_title_rss()
*
* @param string $wp_title The current blog title.
* @param string $sep Separator used by wp_title().
* @param string $wp_title_rss The current blog title.
* @param string $deprecated Deprecated.
*/
echo apply_filters( 'wp_title_rss', get_wp_title_rss( $sep ), $sep );
echo apply_filters( 'wp_title_rss', get_wp_title_rss(), $deprecated );
}
/**

View File

@ -781,184 +781,141 @@ function has_site_icon( $blog_id = 0 ) {
}
/**
* Display title tag with contents.
* Returns document title for the current page.
*
* @since 4.4.0
*
* @global int $page Page number of a single post.
* @global int $paged Page number of a list of posts.
*
* @return string Tag with the document title.
*/
function wp_get_document_title() {
/**
* Allows to short-circuit the title generation.
*
* @since 4.4.0
*
* @param string $title The document title. Default empty string.
*/
$title = apply_filters( 'pre_get_document_title', '' );
if ( ! empty( $title ) ) {
return $title;
}
global $page, $paged;
$title = array(
'title' => '',
);
if ( is_home() && is_front_page() ) {
$title['title'] = get_bloginfo( 'name', 'display' );
/*
* If we're on the blog page and that page is not the homepage or a single page that is designated as
* the homepage, use the container page's title.
*/
} elseif ( ( is_home() && ! is_front_page() ) || ( ! is_home() && is_front_page() ) ) {
$title['title'] = single_post_title( '', false );
// If we're on a post / page.
} elseif ( is_singular() ) {
$title['title'] = single_post_title( '', false );
// If we're on a category or tag or taxonomy archive.
} elseif ( is_category() || is_tag() || is_tax() ) {
$title['title'] = single_term_title( '', false );
// If it's a search.
} elseif ( is_search() ) {
/* translators: %s: search phrase */
$title['title'] = sprintf( __( 'Search Results for &#8220;%s&#8221;' ), get_search_query() );
// If we're on an author archive.
} elseif ( is_author() && $author = get_queried_object() ) {
$title['title'] = $author->display_name;
// If we're on a post type archive.
} elseif ( is_post_type_archive() ) {
$title['title'] = post_type_archive_title( '', false );
// If it's a date archive.
} elseif ( is_year() ) {
$title['title'] = get_the_date( _x( 'Y', 'yearly archives date format' ) );
} elseif ( is_month() ) {
$title['title'] = get_the_date( _x( 'F Y', 'monthly archives date format' ) );
} elseif ( is_day() ) {
$title['title'] = get_the_date();
// If it's a 404 page.
} elseif ( is_404() ) {
$title['title'] = __( 'Page not found' );
}
// Add a page number if necessary.
if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() ) {
$title['page'] = sprintf( __( 'Page %s' ), max( $paged, $page ) );
}
// Append the description or site title to give context.
if ( is_home() && is_front_page() ) {
$title['tagline'] = get_bloginfo( 'description', 'display' );
} else {
$title['site'] = get_bloginfo( 'name', 'display' );
}
/**
* Filters the separator for the document title.
*
* @since 4.4.0
*
* @param string $sep The separator. Default '-'.
*/
$sep = apply_filters( 'document_title_separator', '-' );
/**
* Filters the parts of the document title.
*
* @since 4.4.0
*
* @param array $title {
* The document title parts.
*
* @type string $title Title of the viewed page.
* @type string $page Optional. Page number if paginated.
* @type string $tagline Optional. Site description when on home page.
* @type string $site Optional. Site title when not on home page.
* }
*/
$title = apply_filters( 'document_title_parts', $title );
$title = implode( " $sep ", array_filter( $title ) );
$title = wptexturize( $title );
$title = convert_chars( $title );
$title = esc_html( $title );
$title = capital_P_dangit( $title );
return $title;
}
/**
* Displays title tag with content.
*
* @ignore
* @since 4.1.0
* @since 4.4.0 Improved title output replaced `wp_title()`.
* @access private
*
* @see wp_title()
*/
function _wp_render_title_tag() {
if ( ! current_theme_supports( 'title-tag' ) ) {
return;
}
// This can only work internally on wp_head.
if ( ! did_action( 'wp_head' ) && ! doing_action( 'wp_head' ) ) {
return;
}
echo '<title>' . wp_title( '|', false, 'right' ) . "</title>\n";
}
/**
* Display or retrieve page title for all areas of blog.
*
* By default, the page title will display the separator before the page title,
* so that the blog title will be before the page title. This is not good for
* title display, since the blog title shows up on most tabs and not what is
* important, which is the page that the user is looking at.
*
* There are also SEO benefits to having the blog title after or to the 'right'
* or the page title. However, it is mostly common sense to have the blog title
* to the right with most browsers supporting tabs. You can achieve this by
* using the seplocation parameter and setting the value to 'right'. This change
* was introduced around 2.5.0, in case backwards compatibility of themes is
* important.
*
* @since 1.0.0
*
* @global WP_Locale $wp_locale
* @global int $page
* @global int $paged
*
* @param string $sep Optional, default is '&raquo;'. How to separate the various items within the page title.
* @param bool $display Optional, default is true. Whether to display or retrieve title.
* @param string $seplocation Optional. Direction to display title, 'right'.
* @return string|void String on retrieve.
*/
function wp_title( $sep = '&raquo;', $display = true, $seplocation = '' ) {
global $wp_locale, $page, $paged;
$m = get_query_var('m');
$year = get_query_var('year');
$monthnum = get_query_var('monthnum');
$day = get_query_var('day');
$search = get_query_var('s');
$title = '';
$t_sep = '%WP_TITILE_SEP%'; // Temporary separator, for accurate flipping, if necessary
// If there is a post
if ( is_single() || ( is_home() && !is_front_page() ) || ( is_page() && !is_front_page() ) ) {
$title = single_post_title( '', false );
}
// If there's a post type archive
if ( is_post_type_archive() ) {
$post_type = get_query_var( 'post_type' );
if ( is_array( $post_type ) )
$post_type = reset( $post_type );
$post_type_object = get_post_type_object( $post_type );
if ( ! $post_type_object->has_archive )
$title = post_type_archive_title( '', false );
}
// If there's a category or tag
if ( is_category() || is_tag() ) {
$title = single_term_title( '', false );
}
// If there's a taxonomy
if ( is_tax() ) {
$term = get_queried_object();
if ( $term ) {
$tax = get_taxonomy( $term->taxonomy );
$title = single_term_title( $tax->labels->name . $t_sep, false );
}
}
// If there's an author
if ( is_author() && ! is_post_type_archive() ) {
$author = get_queried_object();
if ( $author )
$title = $author->display_name;
}
// Post type archives with has_archive should override terms.
if ( is_post_type_archive() && $post_type_object->has_archive )
$title = post_type_archive_title( '', false );
// If there's a month
if ( is_archive() && !empty($m) ) {
$my_year = substr($m, 0, 4);
$my_month = $wp_locale->get_month(substr($m, 4, 2));
$my_day = intval(substr($m, 6, 2));
$title = $my_year . ( $my_month ? $t_sep . $my_month : '' ) . ( $my_day ? $t_sep . $my_day : '' );
}
// If there's a year
if ( is_archive() && !empty($year) ) {
$title = $year;
if ( !empty($monthnum) )
$title .= $t_sep . $wp_locale->get_month($monthnum);
if ( !empty($day) )
$title .= $t_sep . zeroise($day, 2);
}
// If it's a search
if ( is_search() ) {
/* translators: 1: separator, 2: search phrase */
$title = sprintf(__('Search Results %1$s %2$s'), $t_sep, strip_tags($search));
}
// If it's a 404 page
if ( is_404() ) {
$title = __('Page not found');
}
$prefix = '';
if ( !empty($title) )
$prefix = " $sep ";
/**
* Filter the parts of the page title.
*
* @since 4.0.0
*
* @param array $title_array Parts of the page title.
*/
$title_array = apply_filters( 'wp_title_parts', explode( $t_sep, $title ) );
// Determines position of the separator and direction of the breadcrumb
if ( 'right' == $seplocation ) { // sep on right, so reverse the order
$title_array = array_reverse( $title_array );
$title = implode( " $sep ", $title_array ) . $prefix;
} else {
$title = $prefix . implode( " $sep ", $title_array );
}
if ( current_theme_supports( 'title-tag' ) && ! is_feed() ) {
$title .= get_bloginfo( 'name', 'display' );
$site_description = get_bloginfo( 'description', 'display' );
if ( $site_description && ( is_home() || is_front_page() ) ) {
$title .= " $sep $site_description";
}
if ( ( $paged >= 2 || $page >= 2 ) && ! is_404() ) {
$title .= " $sep " . sprintf( __( 'Page %s' ), max( $paged, $page ) );
}
}
/**
* Filter the text of the page title.
*
* @since 2.0.0
*
* @param string $title Page title.
* @param string $sep Title separator.
* @param string $seplocation Location of the separator (left or right).
*/
$title = apply_filters( 'wp_title', $title, $sep, $seplocation );
// Send it out
if ( $display )
echo $title;
else
return $title;
echo '<title>' . wp_get_document_title() . '</title>' . "\n";
}
/**
@ -1039,13 +996,9 @@ function post_type_archive_title( $prefix = '', $display = true ) {
/**
* Display or retrieve page title for category archive.
*
* This is useful for category template file or files, because it is optimized
* for category page title and with less overhead than {@link wp_title()}.
*
* It does not support placing the separator after the title, but by leaving the
* prefix parameter empty, you can set the title separator manually. The prefix
* does not automatically place a space between the prefix, so if there should
* be a space, the parameter value will need to have it at the end.
* Useful for category template files for displaying the category page title.
* The prefix does not automatically place a space between the prefix, so if
* there should be a space, the parameter value will need to have it at the end.
*
* @since 0.71
*
@ -1060,11 +1013,7 @@ function single_cat_title( $prefix = '', $display = true ) {
/**
* Display or retrieve page title for tag post archive.
*
* Useful for tag template files for displaying the tag page title. It has less
* overhead than {@link wp_title()}, because of its limited implementation.
*
* It does not support placing the separator after the title, but by leaving the
* prefix parameter empty, you can set the title separator manually. The prefix
* Useful for tag template files for displaying the tag page title. The prefix
* does not automatically place a space between the prefix, so if there should
* be a space, the parameter value will need to have it at the end.
*
@ -1082,11 +1031,7 @@ function single_tag_title( $prefix = '', $display = true ) {
* Display or retrieve page title for taxonomy term archive.
*
* Useful for taxonomy term template files for displaying the taxonomy term page title.
* It has less overhead than {@link wp_title()}, because of its limited implementation.
*
* It does not support placing the separator after the title, but by leaving the
* prefix parameter empty, you can set the title separator manually. The prefix
* does not automatically place a space between the prefix, so if there should
* The prefix does not automatically place a space between the prefix, so if there should
* be a space, the parameter value will need to have it at the end.
*
* @since 3.1.0
@ -1144,14 +1089,10 @@ function single_term_title( $prefix = '', $display = true ) {
/**
* Display or retrieve page title for post archive based on date.
*
* Useful for when the template only needs to display the month and year, if
* either are available. Optimized for just this purpose, so if it is all that
* is needed, should be better than {@link wp_title()}.
*
* It does not support placing the separator after the title, but by leaving the
* prefix parameter empty, you can set the title separator manually. The prefix
* does not automatically place a space between the prefix, so if there should
* be a space, the parameter value will need to have it at the end.
* Useful for when the template only needs to display the month and year,
* if either are available. The prefix does not automatically place a space
* between the prefix, so if there should be a space, the parameter value
* will need to have it at the end.
*
* @since 0.71
*

View File

@ -15,7 +15,7 @@ _deprecated_file( sprintf( __( 'Theme without %1$s' ), basename(__FILE__) ), '3.
<link rel="profile" href="http://gmpg.org/xfn/11" />
<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php bloginfo('charset'); ?>" />
<title><?php wp_title('&laquo;', true, 'right'); ?> <?php bloginfo('name'); ?></title>
<title><?php echo wp_get_document_title(); ?></title>
<link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>" type="text/css" media="screen" />
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>" />

View File

@ -1752,14 +1752,6 @@ function current_theme_supports( $feature ) {
if ( !isset( $_wp_theme_features[$feature] ) )
return false;
if ( 'title-tag' == $feature ) {
// Don't confirm support unless called internally.
$trace = debug_backtrace();
if ( ! in_array( $trace[1]['function'], array( '_wp_render_title_tag', 'wp_title' ) ) ) {
return false;
}
}
// If no args passed then no extra checks need be performed
if ( func_num_args() <= 1 )
return true;

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.4-alpha-35293';
$wp_version = '4.4-alpha-35294';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.