f ( $this->frontend_page_type->is_home_static_page() ) {
$metadesc = $this->get_seo_meta_value( 'metadesc' );
if ( ( $metadesc === '' && $post_type !== '' ) && WPSEO_Options::get( 'metadesc-' . $post_type, '' ) !== '' ) {
$template = WPSEO_Options::get( 'metadesc-' . $post_type );
}
}
elseif ( is_category() || is_tag() || is_tax() ) {
$term = $wp_query->get_queried_object();
$metadesc_override = WPSEO_Taxonomy_Meta::get_term_meta( $term, $term->taxonomy, 'desc' );
if ( is_object( $term ) && isset( $term->taxonomy ) && WPSEO_Options::get( 'metadesc-tax-' . $term->taxonomy, '' ) !== '' ) {
$template = WPSEO_Options::get( 'metadesc-tax-' . $term->taxonomy );
}
}
elseif ( is_author() ) {
$author_id = get_query_var( 'author' );
$metadesc = get_the_author_meta( 'wpseo_metadesc', $author_id );
if ( ( ! is_string( $metadesc ) || $metadesc === '' ) && WPSEO_Options::get( 'metadesc-author-wpseo', '' ) !== '' ) {
$template = WPSEO_Options::get( 'metadesc-author-wpseo' );
}
}
elseif ( is_post_type_archive() ) {
$post_type = $this->get_queried_post_type();
if ( WPSEO_Options::get( 'metadesc-ptarchive-' . $post_type, '' ) !== '' ) {
$template = WPSEO_Options::get( 'metadesc-ptarchive-' . $post_type );
}
}
elseif ( is_archive() ) {
$template = WPSEO_Options::get( 'metadesc-archive-wpseo' );
}
// If we're on a paginated page, and the template doesn't change for paginated pages, bail.
if ( ( ! is_string( $metadesc ) || $metadesc === '' ) && get_query_var( 'paged' ) && get_query_var( 'paged' ) > 1 && $template !== '' ) {
if ( strpos( $template, '%%page' ) === false ) {
$metadesc = '';
}
}
}
$post_data = $post;
if ( is_string( $metadesc_override ) && '' !== $metadesc_override ) {
$metadesc = $metadesc_override;
if ( isset( $term ) ) {
$post_data = $term;
}
}
elseif ( ( ! is_string( $metadesc ) || '' === $metadesc ) && '' !== $template ) {
if ( ! isset( $term ) ) {
$term = $wp_query->get_queried_object();
}
$metadesc = $template;
$post_data = $term;
}
$metadesc = $this->replace_vars( $metadesc, $post_data );
/**
* Filter: 'wpseo_metadesc' - Allow changing the Yoast SEO meta description sentence.
*
* @api string $metadesc The description sentence.
*/
$this->metadesc = apply_filters( 'wpseo_metadesc', trim( $metadesc ) );
}
/**
* Based on the redirect meta value, this function determines whether it should redirect the current post / page.
*
* @return boolean
*/
public function page_redirect() {
if ( is_singular() ) {
global $post;
if ( ! isset( $post ) || ! is_object( $post ) ) {
return false;
}
$redir = $this->get_seo_meta_value( 'redirect', $post->ID );
if ( $redir !== '' ) {
header( 'X-Redirect-By: Yoast SEO' );
wp_redirect( $redir, 301, 'Yoast SEO' );
exit;
}
}
return false;
}
/**
* Outputs noindex values for the current page.
*/
public function noindex_page() {
remove_action( 'wpseo_head', array( $this, 'canonical' ), 20 );
echo '', "\n";
}
/**
* Send a Robots HTTP header preventing URL from being indexed in the search results while allowing search engines
* to follow the links in the object at the URL.
*
* @since 1.1.7
* @return boolean Boolean indicating whether the noindex header was sent.
*/
public function noindex_feed() {
if ( ( is_feed() || is_robots() ) && headers_sent() === false ) {
header( 'X-Robots-Tag: noindex, follow', true );
return true;
}
return false;
}
/**
* Adds rel="nofollow" to a link, only used for login / registration links.
*
* @param string $input The link element as a string.
*
* @return string
*/
public function nofollow_link( $input ) {
return str_replace( 'is_date ) ||
( WPSEO_Options::get( 'disable-author', false ) && $wp_query->is_author ) ||
( WPSEO_Options::get( 'disable-post_format', false ) && $wp_query->is_tax( 'post_format' ) )
) {
$this->redirect( get_bloginfo( 'url' ), 301 );
return true;
}
return false;
}
/**
* If the option to disable attachment URLs is checked, this performs the redirect to the attachment.
*
* @return bool Returns succes status.
*/
public function attachment_redirect() {
if ( WPSEO_Options::get( 'disable-attachment', false ) === false ) {
return false;
}
if ( ! is_attachment() ) {
return false;
}
/**
* Allow the developer to change the target redirection URL for attachments.
*
* @api string $attachment_url The attachment URL for the queried object.
* @api object $queried_object The queried object.
*
* @since 7.5.3
*/
$url = apply_filters( 'wpseo_attachment_redirect_url', wp_get_attachment_url( get_queried_object_id() ), get_queried_object() );
if ( ! empty( $url ) ) {
$this->do_attachment_redirect( $url );
return true;
}
return false;
}
/**
* Performs the redirect from the attachment page to the image file itself.
*
* @param string $attachment_url The attachment image url.
*
* @return void
*/
public function do_attachment_redirect( $attachment_url ) {
header( 'X-Redirect-By: Yoast SEO' );
wp_redirect( $attachment_url, 301, 'Yoast SEO' );
exit;
}
/**
* Replaces the possible RSS variables with their actual values.
*
* @param string $content The RSS content that should have the variables replaced.
*
* @return string
*/
public function rss_replace_vars( $content ) {
global $post;
/**
* Allow the developer to determine whether or not to follow the links in the bits Yoast SEO adds to the RSS feed, defaults to true.
*
* @api bool $unsigned Whether or not to follow the links in RSS feed, defaults to true.
*
* @since 1.4.20
*/
$no_follow = apply_filters( 'nofollow_rss_links', true );
$no_follow_attr = '';
if ( $no_follow === true ) {
$no_follow_attr = 'rel="nofollow" ';
}
$author_link = '';
if ( is_object( $post ) ) {
$author_link = 'post_author ) ) . '">' . esc_html( get_the_author() ) . '';
}
$post_link = '' . esc_html( get_the_title() ) . '';
$blog_link = '' . esc_html( get_bloginfo( 'name' ) ) . '';
$blog_desc_link = '' . esc_html( get_bloginfo( 'name' ) ) . ' - ' . esc_html( get_bloginfo( 'description' ) ) . '';
$content = stripslashes( trim( $content ) );
$content = str_replace( '%%AUTHORLINK%%', $author_link, $content );
$content = str_replace( '%%POSTLINK%%', $post_link, $content );
$content = str_replace( '%%BLOGLINK%%', $blog_link, $content );
$content = str_replace( '%%BLOGDESCLINK%%', $blog_desc_link, $content );
return $content;
}
/**
* Adds the RSS footer (or header) to the full RSS feed item.
*
* @param string $content Feed item content.
*
* @return string
*/
public function embed_rssfooter( $content ) {
return $this->embed_rss( $content, 'full' );
}
/**
* Adds the RSS footer (or header) to the excerpt RSS feed item.
*
* @param string $content Feed item excerpt.
*
* @return string
*/
public function embed_rssfooter_excerpt( $content ) {
return $this->embed_rss( $content, 'excerpt' );
}
/**
* Adds the RSS footer and/or header to an RSS feed item.
*
* @since 1.4.14
*
* @param string $content Feed item content.
* @param string $context Feed item context, either 'excerpt' or 'full'.
*
* @return string
*/
public function embed_rss( $content, $context = 'full' ) {
/**
* Filter: 'wpseo_include_rss_footer' - Allow the RSS footer to be dynamically shown/hidden.
*
* @api boolean $show_embed Indicates if the RSS footer should be shown or not.
*
* @param string $context The context of the RSS content - 'full' or 'excerpt'.
*/
if ( ! apply_filters( 'wpseo_include_rss_footer', true, $context ) ) {
return $content;
}
if ( is_feed() ) {
$before = '';
$after = '';
if ( WPSEO_Options::get( 'rssbefore', '' ) !== '' ) {
$before = wpautop( $this->rss_replace_vars( WPSEO_Options::get( 'rssbefore' ) ) );
}
if ( WPSEO_Options::get( 'rssafter', '' ) !== '' ) {
$after = wpautop( $this->rss_replace_vars( WPSEO_Options::get( 'rssafter' ) ) );
}
if ( $before !== '' || $after !== '' ) {
if ( ( isset( $context ) && $context === 'excerpt' ) && trim( $content ) !== '' ) {
$content = wpautop( $content );
}
$content = $before . $content . $after;
}
}
return $content;
}
/**
* Used in the force rewrite functionality this retrieves the output, replaces the title with the proper SEO
* title and then flushes the output.
*/
public function flush_cache() {
global $wp_query;
if ( $this->ob_started !== true ) {
return false;
}
$content = ob_get_clean();
$old_wp_query = $wp_query;
wp_reset_query();
// Only replace the debug marker when it is hooked.
if ( $this->show_debug_marker() ) {
$title = $this->title( '' );
$debug_mark = $this->get_debug_mark();
/*
* Find all titles, strip them out and add the new one in within the debug marker,
* so it's easily identified whether a site uses force rewrite.
*/
$content = preg_replace( '/
/i', '', $content );
$content = str_replace( $debug_mark, $debug_mark . "\n" . '' . esc_html( $title ) . '', $content );
}
$GLOBALS['wp_query'] = $old_wp_query;
echo $content;
return true;
}
/**
* Starts the output buffer so it can later be fixed by flush_cache().
*/
public function force_rewrite_output_buffer() {
$this->ob_started = true;
ob_start();
}
/**
* Get the product name in the head section.
*
* @return string
*/
private function head_product_name() {
if ( $this->is_premium() ) {
return 'Yoast SEO Premium plugin';
}
return 'Yoast SEO plugin';
}
/**
* Check if this plugin is the premium version of WPSEO.
*
* @return bool
*/
protected function is_premium() {
return WPSEO_Utils::is_yoast_seo_premium();
}
/**
* Check if term archive query is for multiple terms (/term-1,term2/ or /term-1+term-2/).
*
* @return bool
*/
protected function is_multiple_terms_query() {
global $wp_query;
if ( ! is_tax() && ! is_tag() && ! is_category() ) {
return false;
}
$term = get_queried_object();
$queried_terms = $wp_query->tax_query->queried_terms;
if ( empty( $queried_terms[ $term->taxonomy ]['terms'] ) ) {
return false;
}
return count( $queried_terms[ $term->taxonomy ]['terms'] ) > 1;
}
/**
* Wraps wp_safe_redirect to allow testing for redirects.
*
* @param string $location The path to redirect to.
* @param int $status Status code to use.
*/
public function redirect( $location, $status = 302 ) {
header( 'X-Redirect-By: Yoast SEO' );
wp_safe_redirect( $location, $status, 'Yoast SEO' );
exit;
}
/**
* Checks if the debug mark action has been added.
*
* @return bool True when the action exists.
*/
protected function show_debug_marker() {
return has_action( 'wpseo_head', array( $this, 'debug_mark' ) ) !== false;
}
/**
* Shows the closing debug mark.
*
* @return string The closing debug mark comment.
*/
protected function show_closing_debug_mark() {
if ( ! $this->show_debug_marker() ) {
return '';
}
return sprintf(
"\n\n",
esc_html( $this->head_product_name() )
);
}
/**
* Builds the title for a post type archive.
*
* @param string $separator The title separator.
* @param string $separator_location The location of the title separator.
*
* @return string The title to use on a post type archive.
*/
protected function get_post_type_archive_title( $separator, $separator_location ) {
$post_type = $this->get_queried_post_type();
$title = $this->get_title_from_options( 'title-ptarchive-' . $post_type );
if ( ! is_string( $title ) || '' === $title ) {
$post_type_obj = get_post_type_object( $post_type );
$title_part = '';
if ( isset( $post_type_obj->labels->menu_name ) ) {
$title_part = $post_type_obj->labels->menu_name;
}
elseif ( isset( $post_type_obj->name ) ) {
$title_part = $post_type_obj->name;
}
$title = $this->get_default_title( $separator, $separator_location, $title_part );
}
return $title;
}
/**
* Retrieves the WooCommerce title.
*
* @return string The WooCommerce title.
*/
protected function get_woocommerce_title() {
$shop_page_id = $this->woocommerce_shop_page->get_shop_page_id();
$post = get_post( $shop_page_id );
$title = $this->get_seo_title( $post );
if ( is_string( $title ) && $title !== '' ) {
return $title;
}
if ( $shop_page_id !== -1 && is_archive() ) {
$title = $this->get_template( 'title-' . $post->post_type );
$title = $this->replace_vars( $title, $post );
}
return $title;
}
/**
* Retrieves a template from the options.
*
* @param string $template The template to retrieve.
*
* @return string The set template.
*/
protected function get_template( $template ) {
return WPSEO_Options::get( $template );
}
/**
* Retrieves the queried post type.
*
* @return string The queried post type.
*/
protected function get_queried_post_type() {
$post_type = get_query_var( 'post_type' );
if ( is_array( $post_type ) ) {
$post_type = reset( $post_type );
}
return $post_type;
}
/**
* Retrieves the SEO Meta value for the supplied key and optional post.
*
* @param string $key The key to retrieve.
* @param int $post_id Optional. The post to retrieve the key for.
*
* @return string Meta value.
*/
protected function get_seo_meta_value( $key, $post_id = 0 ) {
return WPSEO_Meta::get_value( $key, $post_id );
}
/**
* Replaces the dynamic variables in a string.
*
* @param string $string The string to replace the variables in.
* @param array $args The object some of the replacement values might come from,
* could be a post, taxonomy or term.
* @param array $omit Variables that should not be replaced by this function.
*
* @return string The replaced string.
*/
protected function replace_vars( $string, $args, $omit = array() ) {
$replacer = new WPSEO_Replace_Vars();
return $replacer->replace( $string, $args, $omit );
}
/**
* Adds shortcode support to category descriptions.
*
* @param string $desc String to add shortcodes in.
*
* @return string Content with shortcodes filtered out.
*/
public function custom_category_descriptions_add_shortcode_support( $desc ) {
// Wrap in output buffering to prevent shortcodes that echo stuff instead of return from breaking things.
ob_start();
$desc = do_shortcode( $desc );
ob_end_clean();
return $desc;
}
/* ********************* DEPRECATED METHODS ********************* */
/**
* Outputs the meta keywords element.
*
* @deprecated 6.3
* @codeCoverageIgnore
*
* @return void
*/
public function metakeywords() {
if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) {
_deprecated_function( 'WPSEO_Frontend::metakeywords', '6.3' );
}
}
/**
* Removes unneeded query variables from the URL.
*
* @deprecated 7.0
* @codeCoverageIgnore
*
* @return void
*/
public function clean_permalink() {
// As this is a frontend method, we want to make sure it is not displayed for non-logged in users.
if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) {
_deprecated_function( 'WPSEO_Frontend::clean_permalink', '7.0' );
}
}
/**
* Trailing slashes for everything except is_single().
*
* @deprecated 7.0
* @codeCoverageIgnore
*/
public function add_trailingslash() {
// As this is a frontend method, we want to make sure it is not displayed for non-logged in users.
if ( function_exists( 'wp_get_current_user' ) && current_user_can( 'manage_options' ) ) {
_deprecated_function( 'WPSEO_Frontend::add_trailingslash', '7.0', null );
}
}
/**
* Removes the ?replytocom variable from the link, replacing it with a #comment- anchor.
*
* @deprecated 7.0
* @codeCoverageIgnore
*
* @param string $link The comment link as a string.
*
* @return string The modified link.
*/
public function remove_reply_to_com( $link ) {
_deprecated_function( 'WPSEO_Frontend::remove_reply_to_com', '7.0', 'WPSEO_Remove_Reply_To_Com::remove_reply_to_com' );
$remove_replytocom = new WPSEO_Remove_Reply_To_Com();
return $remove_replytocom->remove_reply_to_com( $link );
}
/**
* Redirects out the ?replytocom variables.
*
* @deprecated 7.0
* @codeCoverageIgnore
*
* @return boolean True when redirect has been done.
*/
public function replytocom_redirect() {
_deprecated_function( 'WPSEO_Frontend::replytocom_redirect', '7.0', 'WPSEO_Remove_Reply_To_Com::replytocom_redirect' );
$remove_replytocom = new WPSEO_Remove_Reply_To_Com();
return $remove_replytocom->replytocom_redirect();
}
/**
* Determine whether this is the homepage and shows posts.
*
* @deprecated 7.7
* @codeCoverageIgnore
*
* @return bool Whether or not the current page is the homepage that displays posts.
*/
public function is_home_posts_page() {
_deprecated_function( __FUNCTION__, '7.7', 'WPSEO_Frontend_Page_Type::is_home_posts_page' );
return $this->frontend_page_type->is_home_posts_page();
}
/**
* Determine whether the this is the static frontpage.
*
* @deprecated 7.7
* @codeCoverageIgnore
*
* @return bool Whether or not the current page is a static frontpage.
*/
public function is_home_static_page() {
_deprecated_function( __FUNCTION__, '7.7', 'WPSEO_Frontend_Page_Type::is_home_static_page' );
return $this->frontend_page_type->is_home_static_page();
}
/**
* Determine whether this is the posts page, when it's not the frontpage.
*
* @deprecated 7.7
* @codeCoverageIgnore
*
* @return bool Whether or not it's a non-frontpage, posts page.
*/
public function is_posts_page() {
_deprecated_function( __FUNCTION__, '7.7', 'WPSEO_Frontend_Page_Type::is_posts_page' );
return $this->frontend_page_type->is_posts_page();
}
/**
* Function used in testing whether the title should be force rewritten or not.
*
* @deprecated 9.6
* @codeCoverageIgnore
*
* @param string $title Title string.
*
* @return string
*/
public function title_test_helper( $title ) {
_deprecated_function( __METHOD__, 'WPSEO 9.6' );
return $title;
}
/**
* Output the rel=publisher code on every page of the site.
*
* @deprecated 10.1.3
*
* @return boolean Boolean indicating whether the publisher link was printed.
*/
public function publisher() {
_deprecated_function( __METHOD__, 'WPSEO 10.1.3' );
return false;
}
}