$post_type ) ) {
$post_type = reset( $post_type );
}
if ( isset( $this->options[ 'metadesc-ptarchive-' . $post_type ] ) ) {
$template = $this->options[ 'metadesc-ptarchive-' . $post_type ];
}
}
elseif ( is_archive() ) {
$template = $this->options['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 = wpseo_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
*/
function page_redirect() {
if ( is_singular() ) {
global $post;
if ( ! isset( $post ) || ! is_object( $post ) ) {
return false;
}
$redir = WPSEO_Meta::get_value( 'redirect', $post->ID );
if ( $redir !== '' ) {
wp_redirect( $redir, 301 );
exit;
}
}
return false;
}
/**
* Outputs noindex values for the current page.
*/
public function noindex_page() {
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( 'options['disable-date'] === true && $wp_query->is_date ) ||
( $this->options['disable-author'] === true && $wp_query->is_author ) ||
( $this->options['disable-post_format'] === true && $wp_query->is_tax( 'post_format' ) )
) {
wp_safe_redirect( get_bloginfo( 'url' ), 301 );
exit;
}
return false;
}
/**
* If the option to redirect attachments to their parent is checked, this performs the redirect.
*
* An extra check is done for when the attachment has no parent.
*
* @return boolean False when no redirect was triggered
*/
function attachment_redirect() {
global $post;
if ( is_attachment() && ( ( is_object( $post ) && isset( $post->post_parent ) ) && ( is_numeric( $post->post_parent ) && $post->post_parent != 0 ) ) ) {
wp_safe_redirect( get_permalink( $post->post_parent ), 301 );
exit;
}
return false;
}
/**
* Trailing slashes for everything except is_single().
*
* Thanks to Mark Jaquith for this code.
*
* @param string $url URL string.
* @param string $type Context (such as single).
*
* @return string
*/
function add_trailingslash( $url, $type ) {
if ( 'single' === $type || 'single_paged' === $type ) {
return $url;
}
else {
return trailingslashit( $url );
}
}
/**
* Removes the ?replytocom variable from the link, replacing it with a #comment- anchor.
*
* @todo Should this function also allow for relative urls ?
*
* @param string $link The comment link as a string.
*
* @return string
*/
public function remove_reply_to_com( $link ) {
return preg_replace( '`href=(["\'])(?:.*(?:\?|&|&)replytocom=(\d+)#respond)`', 'href=$1#comment-$2', $link );
}
/**
* Redirect out the ?replytocom variables when cleanreplytocom is enabled
*
* @since 1.4.13
* @return boolean
*/
function replytocom_redirect() {
if ( isset( $_GET['replytocom'] ) && is_singular() ) {
$url = get_permalink( $GLOBALS['post']->ID );
$hash = sanitize_text_field( $_GET['replytocom'] );
$query_string = remove_query_arg( 'replytocom', sanitize_text_field( $_SERVER['QUERY_STRING'] ) );
if ( ! empty( $query_string ) ) {
$url .= '?' . $query_string;
}
$url .= '#comment-' . $hash;
wp_safe_redirect( $url, 301 );
exit;
}
return false;
}
/**
* Removes unneeded query variables from the URL.
*
* @return boolean
*/
public function clean_permalink() {
if ( is_robots() || get_query_var( 'sitemap' ) || empty( $_GET ) ) {
return false;
}
global $wp_query;
// Recreate current URL.
$cururl = 'http';
if ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) {
$cururl .= 's';
}
$cururl .= '://';
if ( $_SERVER['SERVER_PORT'] != '80' && $_SERVER['SERVER_PORT'] != '443' ) {
$cururl .= $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI'];
}
else {
$cururl .= $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
}
$properurl = '';
if ( is_singular() ) {
global $post;
if ( empty( $post ) ) {
$post = $wp_query->get_queried_object();
}
$properurl = get_permalink( $post->ID );
$page = get_query_var( 'page' );
if ( $page && $page != 1 ) {
$post = get_post( $post->ID );
$page_count = substr_count( $post->post_content, '' );
if ( $page > ( $page_count + 1 ) ) {
$properurl = user_trailingslashit( trailingslashit( $properurl ) . ( $page_count + 1 ) );
}
else {
$properurl = user_trailingslashit( trailingslashit( $properurl ) . $page );
}
}
// Fix reply to comment links, whoever decided this should be a GET variable?
if ( preg_match( '`(\?replytocom=[^&]+)`', sanitize_text_field( $_SERVER['REQUEST_URI'] ), $matches ) ) {
$properurl .= str_replace( '?replytocom=', '#comment-', $matches[0] );
}
unset( $matches );
// Prevent cleaning out posts & page previews for people capable of viewing them.
if ( isset( $_GET['preview'], $_GET['preview_nonce'] ) && current_user_can( 'edit_post' ) ) {
$properurl = '';
}
}
elseif ( is_front_page() ) {
if ( $this->is_home_posts_page() ) {
$properurl = get_bloginfo( 'url' ) . '/';
}
elseif ( $this->is_home_static_page() ) {
$properurl = get_permalink( $GLOBALS['post']->ID );
}
}
elseif ( is_category() || is_tag() || is_tax() ) {
$term = $wp_query->get_queried_object();
if ( is_feed() ) {
$properurl = get_term_feed_link( $term->term_id, $term->taxonomy );
}
else {
$properurl = get_term_link( $term, $term->taxonomy );
}
}
elseif ( is_search() ) {
$s = urlencode( preg_replace( '`(%20|\+)`', ' ', get_search_query() ) );
$properurl = get_bloginfo( 'url' ) . '/?s=' . $s;
}
elseif ( is_404() ) {
if ( is_multisite() && ! is_subdomain_install() && is_main_site() ) {
if ( $cururl == get_bloginfo( 'url' ) . '/blog/' || $cururl == get_bloginfo( 'url' ) . '/blog' ) {
if ( $this->is_home_static_page() ) {
$properurl = get_permalink( get_option( 'page_for_posts' ) );
}
else {
$properurl = get_bloginfo( 'url' ) . '/';
}
}
}
}
if ( ! empty( $properurl ) && $wp_query->query_vars['paged'] != 0 && $wp_query->post_count != 0 ) {
if ( is_search() && ! empty( $s ) ) {
$properurl = get_bloginfo( 'url' ) . '/page/' . $wp_query->query_vars['paged'] . '/?s=' . $s;
}
else {
$properurl = user_trailingslashit( trailingslashit( $properurl ) . 'page/' . $wp_query->query_vars['paged'] );
}
}
// Prevent cleaning out the WP Subscription managers interface for everyone.
if ( isset( $_GET['wp-subscription-manager'] ) ) {
$properurl = '';
}
/**
* Filter: 'wpseo_whitelist_permalink_vars' - Allow plugins to register their own variables not to clean
*
* @api array $unsigned Array of permalink variables _not_ to clean. Empty by default.
*/
$whitelisted_extravars = apply_filters( 'wpseo_whitelist_permalink_vars', array() );
if ( $this->options['cleanpermalink-googlesitesearch'] === true ) {
// Prevent cleaning out Google Site searches.
$whitelisted_extravars = array_merge( $whitelisted_extravars, array(
'q',
'cx',
'debug',
'cof',
'ie',
'sa',
) );
}
if ( $this->options['cleanpermalink-googlecampaign'] === true ) {
// Prevent cleaning out Google Analytics campaign variables.
$whitelisted_extravars = array_merge( $whitelisted_extravars, array(
'utm_campaign',
'utm_medium',
'utm_source',
'utm_content',
'utm_term',
'utm_id',
'gclid',
) );
}
if ( $this->options['cleanpermalink-extravars'] !== '' ) {
$extravars = explode( ',', $this->options['cleanpermalink-extravars'] );
$extravars = array_map( 'trim', $extravars );
$whitelisted_extravars = array_merge( $whitelisted_extravars, $extravars );
unset( $extravars );
}
foreach ( $whitelisted_extravars as $get ) {
if ( isset( $_GET[ trim( $get ) ] ) ) {
$properurl = '';
}
}
unset( $get );
if ( ! empty( $properurl ) && $cururl != $properurl ) {
wp_safe_redirect( $properurl, 301 );
exit;
}
}
/**
* Replaces the possible RSS variables with their actual values.
*
* @param string $content The RSS content that should have the variables replaced.
*
* @return string
*/
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
*/
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
*/
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
*/
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 ( $this->options['rssbefore'] !== '' ) {
$before = wpautop( $this->rss_replace_vars( $this->options['rssbefore'] ) );
}
if ( $this->options['rssafter'] !== '' ) {
$after = wpautop( $this->rss_replace_vars( $this->options['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.
*/
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();
$title = $this->title( '' );
// 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( $this->debug_mark( false ), $this->debug_mark( false ) . "\n" . '' . $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()
*/
function force_rewrite_output_buffer() {
$this->ob_started = true;
ob_start();
}
/**
* Function used in testing whether the title should be force rewritten or not.
*
* @param string $title Title string.
*
* @return string
*/
function title_test_helper( $title ) {
$wpseo_titles = get_option( 'wpseo_titles' );
$wpseo_titles['title_test'] ++;
update_option( 'wpseo_titles', $wpseo_titles );
// Prevent this setting from being on forever when something breaks, as it breaks caching.
if ( $wpseo_titles['title_test'] > 5 ) {
$wpseo_titles['title_test'] = 0;
update_option( 'wpseo_titles', $wpseo_titles );
remove_filter( 'wpseo_title', array( $this, 'title_test_helper' ) );
return $title;
}
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
define( 'DONOTCACHEPAGE', true );
}
if ( ! defined( 'DONOTCACHCEOBJECT' ) ) {
define( 'DONOTCACHCEOBJECT', true );
}
if ( ! defined( 'DONOTMINIFY' ) ) {
define( 'DONOTMINIFY', true );
}
if ( $_SERVER['HTTP_USER_AGENT'] === "WordPress/{$GLOBALS['wp_version']}; " . get_bloginfo( 'url' ) . ' - Yoast' ) {
return 'This is a Yoast Test Title';
}
return $title;
}
/**
* Get the product name in the head section
*
* @return string
*/
private function head_product_name() {
if ( $this->is_premium() ) {
return 'Yoast SEO Premium plugin';
}
else {
return 'Yoast SEO plugin';
}
}
/**
* Check if this plugin is the premium version of WPSEO
*
* @return bool
*/
private function is_premium() {
return file_exists( WPSEO_PATH . 'premium/' );
}
/**
* Getting the keywords
*
* @param WP_Post $post The post object with the values.
*
* @return string
*/
private function get_keywords( $post ) {
$keywords = WPSEO_Meta::get_value( 'metakeywords', $post->ID );
$option_meta_key = 'metakey-' . $post->post_type;
if ( $keywords === '' && ( is_object( $post ) && ( isset( $this->options[ $option_meta_key ] ) && $this->options[ $option_meta_key ] !== '' ) ) ) {
$keywords = wpseo_replace_vars( $this->options[ $option_meta_key ], $post );
}
return $keywords;
}
/**
* 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;
}
/** Deprecated functions */
// @codeCoverageIgnoreStart
/**
* Outputs or returns the debug marker, which is also used for title replacement when force rewrite is active.
*
* @deprecated 4.4
*
* @param bool $echo Whether or not to echo the debug marker.
* @return string
*/
public function debug_marker( $echo = false ) {
return $this->debug_mark( $echo );
}
// @codeCoverageIgnoreEnd
}