Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1,646 @@
<?php
/**
* The Breadcrumbs.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\Frontend
* @author Rank Math <support@rankmath.com>
*
* @copyright Copyright (C) 2015, WooCommerce
* The following code is a derivative work of the code from the WooCommerce(https://github.com/woocommerce/woocommerce/), which is licensed under GPL v3.
*/
namespace RankMath\Frontend;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Security;
defined( 'ABSPATH' ) || exit;
/**
* Breadcrumbs class.
*/
class Breadcrumbs {
use Hooker;
/**
* Breadcrumb trail.
*
* @var array
*/
private $crumbs = [];
/**
* Breadcrumb settings.
*
* @var array
*/
private $settings = [];
/**
* String.
*
* @var array
*/
private $strings = [];
/**
* Get an instance of the class.
*
* @return Breadcrumb The instancec.
*/
public static function get() {
static $instance;
$instance = false;
if ( Helper::is_breadcrumbs_enabled() && false === $instance ) {
$instance = new Breadcrumbs();
}
return $instance;
}
/**
* Convenience method to output as string.
*
* @return string
*/
public function __toString() {
return $this->get_breadcrumb();
}
/**
* The Constructor
*
* @codeCoverageIgnore
*/
public function __construct() {
$this->settings = wp_parse_args(
$this->do_filter( 'frontend/breadcrumb/settings', [] ),
[
'home' => Helper::get_settings( 'general.breadcrumbs_home' ),
'separator' => Helper::get_settings( 'general.breadcrumbs_separator' ),
'remove_title' => Helper::get_settings( 'general.breadcrumbs_remove_post_title' ),
'hide_tax_name' => Helper::get_settings( 'general.breadcrumbs_hide_taxonomy_name' ),
'show_ancestors' => Helper::get_settings( 'general.breadcrumbs_ancestor_categories' ),
'show_blog' => Helper::get_settings( 'general.breadcrumbs_blog_page' ),
'show_pagination' => true,
]
);
$this->strings = wp_parse_args(
$this->do_filter( 'frontend/breadcrumb/strings', [] ),
[
'prefix' => Helper::get_settings( 'general.breadcrumbs_prefix' ),
'home' => Helper::get_settings( 'general.breadcrumbs_home_label' ),
'home_link' => Helper::get_settings( 'general.breadcrumbs_home_link', home_url() ),
'error404' => Helper::get_settings( 'general.breadcrumbs_404_label' ),
/* translators: search query */
'search_format' => Helper::get_settings( 'general.breadcrumbs_search_format' ),
/* translators: archive title */
'archive_format' => Helper::get_settings( 'general.breadcrumbs_archive_format' ),
]
);
}
/**
* Get the breadcrumbs.
*
* @param array $args Arguments.
* @return string
*/
public function get_breadcrumb( $args = [] ) {
$args = $this->do_filter(
'frontend/breadcrumb/args',
wp_parse_args(
$args,
[
'delimiter' => '&nbsp;&#47;&nbsp;',
'wrap_before' => '<nav aria-label="breadcrumbs" class="rank-math-breadcrumb"><p>',
'wrap_after' => '</p></nav>',
'before' => '',
'after' => '',
]
)
);
$html = '';
$crumbs = $this->get_crumbs();
$remove_title = ( is_single() || is_page() ) && $this->settings['remove_title'];
if ( $remove_title ) {
array_pop( $crumbs );
}
$size = count( $crumbs );
if ( ! empty( $this->strings['prefix'] ) ) {
$html .= \sprintf( '<span class="label">%s</span> ', $this->strings['prefix'] );
}
foreach ( $crumbs as $key => $crumb ) {
$link = ! empty( $crumb[1] ) && ( $remove_title || $size !== $key + 1 );
$link = $link ? '<a href="' . esc_url( $crumb[1] ) . '">' . esc_html( $crumb[0] ) . '</a>' :
'<span class="last">' . esc_html( $crumb[0] ) . '</span>';
$html .= $args['before'] . $link . $args['after'];
if ( $size !== $key + 1 ) {
$html .= '<span class="separator"> ' . wp_kses_post( $this->settings['separator'] ) . ' </span>';
}
}
$html = $args['wrap_before'] . $html . $args['wrap_after'];
/**
* Change the breadcrumbs HTML output.
*
* @param string $html HTML output.
* @param array $crumbs The breadcrumbs array.
* @param Breadcrumbs $this Current breadcrumb.
*/
return $this->do_filter( 'frontend/breadcrumb/html', $html, $crumbs, $this );
}
/**
* Get the breadrumb trail.
*
* @return array
*/
public function get_crumbs() {
if ( empty( $this->crumbs ) ) {
$this->generate();
}
/**
* Change the breadcrumb items.
*
* @param array $crumbs The breadcrumbs array.
* @param Breadcrumbs $this Current breadcrumb.
*/
return $this->do_filter( 'frontend/breadcrumb/items', $this->crumbs, $this );
}
/**
* Add an item to the breadcrumbs.
*
* @param string $name Name.
* @param string $link Link.
* @param bool $hide_in_schema Don't include in JSON-LD.
*/
private function add_crumb( $name, $link = '', $hide_in_schema = false ) {
$this->crumbs[] = [
wp_strip_all_tags( $name ),
$link,
'hide_in_schema' => $hide_in_schema,
];
}
/**
* Generate the breadcrumb trail.
*/
private function generate() {
$conditionals = [
'is_home',
'is_404',
'is_search',
'is_attachment',
'is_shop',
'is_product',
'is_singular',
'is_product_category',
'is_product_tag',
'is_post_type_archive',
'is_category',
'is_tag',
'is_tax',
'is_date',
'is_author',
];
$this->maybe_add_home_crumb();
if ( ! $this->can_generate() ) {
return;
}
foreach ( $conditionals as $conditional ) {
if ( function_exists( $conditional ) && call_user_func( $conditional ) ) {
call_user_func( [ $this, 'add_crumbs_' . substr( $conditional, 3 ) ] );
break;
}
}
$this->maybe_add_page_crumb();
}
/**
* Can generate breadcrumb.
*
* @return bool
*/
private function can_generate() {
return (
! is_front_page() &&
! (
is_post_type_archive() &&
function_exists( 'wc_get_page_id' ) &&
intval( get_option( 'page_on_front' ) ) === wc_get_page_id( 'shop' ) )
) ||
is_paged();
}
/**
* Is home trail.
*/
private function add_crumbs_home() {
$this->add_crumb( single_post_title( '', false ) );
}
/**
* 404 trail.
*/
private function add_crumbs_404() {
$this->add_crumb( $this->strings['error404'] );
}
/**
* Search results trail.
*/
private function add_crumbs_search() {
$this->add_crumb( sprintf( $this->strings['search_format'], get_search_query() ), Security::remove_query_arg_raw( 'paged' ) );
}
/**
* Attachment trail.
*/
private function add_crumbs_attachment() {
global $post;
$this->add_crumbs_singular( $post->post_parent, get_permalink( $post->post_parent ) );
$this->add_crumb( $this->get_breadcrumb_title( 'post', get_the_ID(), get_the_title() ), get_permalink() );
}
/**
* Single product trail.
*/
private function add_crumbs_product() {
global $post;
$this->prepend_shop_page();
$main_tax = Helper::get_settings( 'titles.pt_product_primary_taxonomy' );
if ( $main_tax ) {
$this->maybe_add_primary_term( get_the_terms( $post->ID, $main_tax ) );
}
if ( isset( $post->ID ) ) {
$this->add_crumb( $this->get_breadcrumb_title( 'post', $post->ID, get_the_title( $post ) ), get_permalink( $post ) );
}
}
/**
* Single post trail.
*
* @param int $post_id Post ID.
* @param string $permalink Post permalink.
*/
private function add_crumbs_singular( $post_id = 0, $permalink = '' ) {
$post = ! $post_id ? $GLOBALS['post'] : get_post( $post_id );
$post_type = get_post_type( $post );
$permalink = $permalink ? $permalink : get_permalink( $post );
$this->add_crumbs_post_type_archive( $post_type );
if ( ! isset( $post->ID ) || empty( $post->ID ) ) {
return;
}
$this->maybe_add_blog();
$main_tax = Helper::get_settings( 'titles.pt_' . $post_type . '_primary_taxonomy' );
if ( isset( $post->post_parent ) && 0 === $post->post_parent && $main_tax ) {
$this->maybe_add_primary_term( get_the_terms( $post, $main_tax ) );
}
if ( isset( $post->post_parent ) && 0 !== $post->post_parent ) {
$this->add_post_ancestors( $post );
}
$this->add_crumb( $this->get_breadcrumb_title( 'post', $post->ID, get_the_title( $post ) ), $permalink );
}
/**
* Product category trail.
*/
private function add_crumbs_product_category() {
$term = $GLOBALS['wp_query']->get_queried_object();
$this->prepend_shop_page();
$this->maybe_add_term_ancestors( $term );
$this->add_crumb( $this->get_breadcrumb_title( 'term', $term, $term->name ), get_term_link( $term ) );
}
/**
* Product tag trail.
*/
private function add_crumbs_product_tag() {
$term = $GLOBALS['wp_query']->get_queried_object();
$this->prepend_shop_page();
/* translators: %s: product tag */
$this->add_crumb( sprintf( __( 'Products tagged &ldquo;%s&rdquo;', 'rank-math' ), $this->get_breadcrumb_title( 'term', $term, $term->name ) ), get_term_link( $term ) );
}
/**
* Shop trail.
*/
private function add_crumbs_shop() {
$shop_page_id = function_exists( 'wc_get_page_id' ) ? wc_get_page_id( 'shop' ) : false;
if ( intval( get_option( 'page_on_front' ) ) === $shop_page_id ) {
return;
}
$name = $shop_page_id ? $this->get_breadcrumb_title( 'post', $shop_page_id, get_the_title( $shop_page_id ) ) : '';
if ( ! $name ) {
$post_type = get_post_type_object( 'product' );
$name = $post_type->labels->singular_name;
}
$this->add_crumb( $name, get_post_type_archive_link( 'product' ) );
}
/**
* Post type archive trail.
*
* @param string $post_type Post type.
*/
private function add_crumbs_post_type_archive( $post_type = null ) {
if ( ! $post_type ) {
$post_type = $GLOBALS['wp_query']->get( 'post_type' );
}
if ( 'post' === $post_type ) {
return;
}
$type_object = get_post_type_object( $post_type );
if ( ! empty( $type_object->has_archive ) ) {
$this->add_crumb( $type_object->labels->name, get_post_type_archive_link( $post_type ) );
}
}
/**
* Category trail.
*/
private function add_crumbs_category() {
$this->maybe_add_blog();
$term = $GLOBALS['wp_query']->get_queried_object();
$this->maybe_add_term_ancestors( $term );
$this->add_crumb( $this->get_breadcrumb_title( 'term', $term, $term->name ), get_term_link( $term ) );
}
/**
* Tag trail.
*/
private function add_crumbs_tag() {
$this->maybe_add_blog();
$term = $GLOBALS['wp_query']->get_queried_object();
$this->add_crumb( $this->get_breadcrumb_title( 'term', $term, $term->name ), get_term_link( $term ) );
}
/**
* Taxonomies trail.
*/
private function add_crumbs_tax() {
$term = $GLOBALS['wp_query']->get_queried_object();
if ( ! $this->settings['hide_tax_name'] ) {
$taxonomy = get_taxonomy( $term->taxonomy );
$this->add_crumb( $taxonomy->labels->name );
}
$this->maybe_add_term_ancestors( $term );
$this->add_crumb( $this->get_breadcrumb_title( 'term', $term, $term->name ), get_term_link( $term ) );
}
/**
* Trail for date based archives.
*/
private function add_crumbs_date() {
if ( is_year() || is_month() || is_day() ) {
$this->add_crumb( sprintf( $this->strings['archive_format'], get_the_time( 'Y' ) ), get_year_link( get_the_time( 'Y' ) ) );
}
if ( is_month() || is_day() ) {
$this->add_crumb( sprintf( $this->strings['archive_format'], get_the_time( 'F' ) ), get_month_link( get_the_time( 'Y' ), get_the_time( 'm' ) ) );
}
if ( is_day() ) {
$this->add_crumb( sprintf( $this->strings['archive_format'], get_the_time( 'd' ) ) );
}
}
/**
* Trail for author archives.
*/
private function add_crumbs_author() {
global $author;
$userdata = get_userdata( $author );
$this->add_crumb( sprintf( $this->strings['archive_format'], $this->get_breadcrumb_title( 'user', $userdata->ID, $userdata->display_name ) ) );
}
/**
* Single post trail.
*
* @copyright Copyright (C) 2008-2019, Yoast BV
* The following code is a derivative work of the code from the Yoast (https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
*
* @param WP_Post $post Post object.
*/
private function add_post_ancestors( $post ) {
$ancestors = [];
if ( isset( $post->ancestors ) ) {
$ancestors = is_array( $post->ancestors ) ? array_values( $post->ancestors ) : [ $post->ancestors ];
} elseif ( isset( $post->post_parent ) ) {
$ancestors = [ $post->post_parent ];
}
if ( ! is_array( $ancestors ) ) {
return;
}
$ancestors = array_reverse( $ancestors );
foreach ( $ancestors as $ancestor ) {
$this->add_crumb( $this->get_breadcrumb_title( 'post', $ancestor, get_the_title( $ancestor ) ), get_permalink( $ancestor ) );
}
}
/**
* Prepend the shop page to the shop trail.
*/
private function prepend_shop_page() {
$shop_page_id = function_exists( 'wc_get_page_id' ) ? wc_get_page_id( 'shop' ) : false;
$shop_page = get_post( $shop_page_id );
// If permalinks contain the shop page in the URI prepend the breadcrumb with shop.
if ( $shop_page_id && $shop_page && $this->is_using_shop_base( $shop_page ) && intval( get_option( 'page_on_front' ) ) !== $shop_page_id ) {
$this->add_crumb( $this->get_breadcrumb_title( 'post', $shop_page_id, get_the_title( $shop_page ) ), get_permalink( $shop_page ) );
}
}
/**
* Checks if the permalinks product base is using the shop base.
*
* @param \WP_Post $shop_page The shop page.
*
* @return bool
*/
private function is_using_shop_base( $shop_page ) {
$permalinks = wc_get_permalink_structure();
$is_using_shop_base = isset( $permalinks['product_base'] ) && strstr( $permalinks['product_base'], '/' . $shop_page->post_name );
/**
* Allows to filter the "is using shop base" condition.
*
* @param bool True if using shop base or false otherwise.
*/
return $this->do_filter( 'frontend/breadcrumb/is_using_shop_base', $is_using_shop_base );
}
/**
* Get the primary term.
*
* @param array $terms Terms attached to the current post.
*/
private function maybe_add_primary_term( $terms ) {
// Early Bail!
if ( is_wp_error( $terms ) || empty( $terms ) ) {
return;
}
/**
* Allow changing the primary term output of the breadcrumbs class.
*
* @param WP_Term $term Primary term.
* @param array $terms Terms attached to the current post.
*/
$term = $this->do_filter( 'frontend/breadcrumb/main_term', $terms[0], $terms );
$this->maybe_add_term_ancestors( $term );
$this->add_crumb( $this->get_breadcrumb_title( 'term', $term, $term->name ), get_term_link( $term ) );
}
/**
* Add ancestor taxonomy crumbs to the hierachical taxonomy trails.
*
* @param object $term Term data object.
*/
private function maybe_add_term_ancestors( $term ) {
// Early Bail!
if ( ! $this->can_add_term_ancestors( $term ) ) {
return;
}
$ancestors = get_ancestors( $term->term_id, $term->taxonomy );
$ancestors = array_reverse( $ancestors );
foreach ( $ancestors as $ancestor ) {
$ancestor = get_term( $ancestor, $term->taxonomy );
if ( ! is_wp_error( $ancestor ) && $ancestor ) {
$this->add_crumb( $this->get_breadcrumb_title( 'term', $ancestor, $ancestor->name ), get_term_link( $ancestor ) );
}
}
}
/**
* Can add ancestor taxonomy crumbs to the hierachical taxonomy trails.
*
* @param object $term Term data object.
*
* @return bool
*/
private function can_add_term_ancestors( $term ) {
if ( 0 === $term->parent || false === $this->settings['show_ancestors'] || false === is_taxonomy_hierarchical( $term->taxonomy ) ) {
return false;
}
return true;
}
/**
* Add a page crumb to paginated trails.
*
* @since 1.0.8
*/
private function maybe_add_page_crumb() {
if ( empty( $this->settings['show_pagination'] ) || ! is_paged() ) {
return;
}
$current_page = get_query_var( 'paged', 1 );
if ( $current_page <= 1 ) {
return;
}
/* translators: %s expands to the current page number */
$this->add_crumb( sprintf( esc_html__( 'Page %s', 'rank-math' ), $current_page ), '', true );
}
/**
* Add home label.
*/
private function maybe_add_home_crumb() {
if ( ! empty( $this->settings['home'] ) ) {
$this->add_crumb( $this->strings['home'], $this->strings['home_link'] );
}
}
/**
* Get the Blog Page.
*
* @since 1.0.33
*/
private function maybe_add_blog() {
// Early Bail!
$blog_id = get_option( 'page_for_posts' );
if ( ! $blog_id || ! $this->can_add_blog() ) {
return;
}
$this->add_crumb( $this->get_breadcrumb_title( 'post', $blog_id, get_the_title( $blog_id ) ), get_permalink( $blog_id ) );
}
/**
* Can add Blog page crumb.
*
* @since 1.0.33
*
* @return bool
*/
private function can_add_blog() {
if ( empty( $this->settings['show_blog'] ) || 'page' !== get_option( 'show_on_front' ) ) {
return false;
}
if ( ! is_singular( 'post' ) && ! is_category() && ! is_tag() ) {
return false;
}
return true;
}
/**
* Get the breadcrumb title.
*
* @param string $object_type Object type.
* @param int $object_id Object ID to get the title for.
* @param string $default Default value to use for title.
* @return string
*/
private function get_breadcrumb_title( $object_type, $object_id, $default ) {
$title = '';
if ( 'post' === $object_type ) {
$title = Helper::get_post_meta( 'breadcrumb_title', $object_id );
} elseif ( 'term' === $object_type ) {
$title = Helper::get_term_meta( 'breadcrumb_title', $object_id );
} elseif ( 'user' === $object_type ) {
$title = Helper::get_user_meta( 'breadcrumb_title', $object_id );
}
return $title ? $title : $default;
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* The class handles the comments functionalities.
*
* @since 1.0.33
* @package RankMath
* @subpackage RankMath\Frontend
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Frontend;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Helpers\HTML;
use RankMath\Helpers\Str;
use RankMath\Helpers\Security;
defined( 'ABSPATH' ) || exit;
/**
* Comments class.
*
* @copyright Copyright (C) 2008-2019, Yoast BV
* The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
*/
class Comments {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'wp_head', 'add_attributes', 99 );
}
/**
* Add UGC attribute and remove ?replytocom parameters.
*/
public function add_attributes() {
/**
* Enable or disable the feature that adds ugc attribute.
*
* @param bool $remove Whether to remove the parameters.
*/
if ( $this->do_filter( 'frontend/add_ugc_attribute', true ) ) {
$this->filter( 'comment_text', 'add_ugc_attribute' );
$this->filter( 'get_comment_author_link', 'add_ugc_attribute' );
}
/**
* Enable or disable the feature that removes the ?replytocom parameters.
*
* @param bool $remove Whether to remove the parameters.
*/
if ( $this->do_filter( 'frontend/remove_reply_to_com', true ) ) {
$this->filter( 'comment_reply_link', 'remove_reply_to_com' );
$this->action( 'template_redirect', 'replytocom_redirect', 1 );
}
}
/**
* Replace the ?replytocom with #comment-[number] in a link.
*
* @param string $link The comment link as a string.
* @return string The new link.
*/
public function remove_reply_to_com( $link ) {
return preg_replace( '`href=(["\'])(?:.*(?:\?|&|&#038;)replytocom=(\d+)#respond)`', 'href=$1#comment-$2', $link );
}
/**
* Redirect the ?replytocom URLs.
*
* @return bool True when redirect has been done.
*/
public function replytocom_redirect() {
if ( isset( $_GET['replytocom'] ) && is_singular() ) {
$url = get_permalink( $GLOBALS['post']->ID );
$query_string = Security::remove_query_arg_raw( 'replytocom', sanitize_text_field( $_SERVER['QUERY_STRING'] ) );
if ( ! empty( $query_string ) ) {
$url .= '?' . $query_string;
}
$url .= '#comment-' . sanitize_text_field( $_GET['replytocom'] );
Helper::redirect( $url, 301 );
return true;
}
return false;
}
/**
* Add 'ugc' attribute to comment.
*
* @param string $text Comment or author link text to add ugc attribute.
* @return string
*/
public function add_ugc_attribute( $text ) {
preg_match_all( '/<(a\s[^>]+)>/', $text, $matches );
if ( empty( $matches ) || empty( $matches[0] ) ) {
return $text;
}
foreach ( $matches[0] as $link ) {
$attrs = HTML::extract_attributes( $link );
$attrs['rel'] = empty( $attrs['rel'] ) ? 'ugc' : ( Str::contains( 'ugc', $attrs['rel'] ) ? $attrs['rel'] : $attrs['rel'] . ' ugc' );
$new = '<a' . HTML::attributes_to_string( $attrs ) . '>';
$text = str_replace( $link, $new, $text );
}
return $text;
}
}

View File

@@ -0,0 +1,291 @@
<?php
/**
* The public-facing functionality of the plugin.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\Frontend
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Frontend;
use RankMath\Post;
use RankMath\Helper;
use RankMath\Paper\Paper;
use RankMath\Traits\Hooker;
use RankMath\OpenGraph\Twitter;
use RankMath\OpenGraph\Facebook;
use RankMath\OpenGraph\Slack;
use RankMath\Frontend\Shortcodes;
defined( 'ABSPATH' ) || exit;
/**
* Frontend class.
*
* @copyright Copyright (C) 2008-2019, Yoast BV
* The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
*/
class Frontend {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
if ( \RankMath\Helpers\Param::get( 'et_fb' ) ) {
return;
}
$this->includes();
$this->hooks();
/**
* Fires when frontend is included/loaded.
*/
$this->do_action( 'frontend/loaded' );
}
/**
* Include required files.
*/
private function includes() {
rank_math()->shortcodes = new Shortcodes();
if ( Helper::is_breadcrumbs_enabled() ) {
/**
* If RM's breadcrumbs are enabled then we can remove the bbPress breadcrumbs.
*/
add_filter( 'bbp_get_breadcrumb', '__return_false' );
}
new Redirection();
rank_math()->link_attributes = new Link_Attributes();
rank_math()->comments = new Comments();
}
/**
* Hook into actions and filters.
*/
private function hooks() {
$this->action( 'wp_enqueue_scripts', 'enqueue' );
$this->action( 'wp', 'integrations' );
$this->filter( 'the_content_feed', 'embed_rssfooter' );
$this->filter( 'the_excerpt_rss', 'embed_rssfooter_excerpt' );
// Add support for shortcode in the Category/Term description.
add_filter( 'category_description', 'do_shortcode' );
add_filter( 'term_description', 'do_shortcode' );
}
/**
* Initialize integrations.
*/
public function integrations() {
$type = get_query_var( 'sitemap' );
if ( $this->do_filter( 'frontend/disable_integration', ! empty( $type ) || is_customize_preview() ) ) {
return;
}
Paper::get();
new Facebook();
new Twitter();
new Slack();
// Leave this for backwards compatibility as AMP plugin uses head function. We can remove this in the future update.
rank_math()->head = new Head();
if ( function_exists( 'amp_is_dev_mode' ) && amp_is_dev_mode() ) {
$this->filter( 'script_loader_tag', 'add_amp_dev_mode_attributes', 10, 2 );
$this->filter( 'amp_dev_mode_element_xpaths', 'add_amp_dev_mode_xpaths' );
}
}
/**
* Enqueue Styles and Scripts
*/
public function enqueue() {
if ( ! is_admin_bar_showing() || ! Helper::has_cap( 'admin_bar' ) ) {
return;
}
wp_enqueue_style( 'rank-math', rank_math()->assets() . 'css/rank-math.css', null, rank_math()->version );
wp_enqueue_script( 'rank-math', rank_math()->assets() . 'js/rank-math.js', [ 'jquery' ], rank_math()->version, true );
if ( is_singular() ) {
Helper::add_json( 'objectID', Post::get_page_id() );
Helper::add_json( 'objectType', 'post' );
} elseif ( is_category() || is_tag() || is_tax() ) {
Helper::add_json( 'objectID', get_queried_object_id() );
Helper::add_json( 'objectType', 'term' );
} elseif ( is_author() ) {
Helper::add_json( 'objectID', get_queried_object_id() );
Helper::add_json( 'objectType', 'user' );
}
}
/**
* Adds the RSS header and footer messages to the RSS feed item content.
*
* @param string $content Feed item content.
*
* @return string
*/
public function embed_rssfooter( $content ) {
return $this->embed_rss( $content, 'full' );
}
/**
* Adds the RSS header and footer messages to the RSS feed item excerpt.
*
* @param string $content Feed item excerpt.
*
* @return string
*/
public function embed_rssfooter_excerpt( $content ) {
return $this->embed_rss( $content, 'excerpt' );
}
/**
* Add data-ampdevmode attribute to enqueued scripts.
*
* @since 1.0.45
*
* @param string $tag The script tag.
* @param string $handle The script handle.
*
* @return string Modified script tag.
*/
public function add_amp_dev_mode_attributes( $tag, $handle ) {
if ( ! in_array( $handle, [ 'rank-math', 'jquery-core', 'jquery-migrate' ], true ) ) {
return $tag;
}
return preg_replace( '/(?<=<script)(?=\s|>)/i', ' data-ampdevmode', $tag );
}
/**
* Add data-ampdevmode attributes to the elements that need it.
*
* @since 1.0.45
*
* @param string[] $xpaths XPath queries for elements that should get the data-ampdevmode attribute.
*
* @return string[] XPath queries.
*/
public function add_amp_dev_mode_xpaths( $xpaths ) {
$xpaths[] = '//script[ contains( text(), "var rankMath" ) ]';
$xpaths[] = '//*[ @id = "rank-math-css" ]';
$xpaths[] = '//a[starts-with(@href, "tel://")]';
return $xpaths;
}
/**
* Inserts the RSS header and footer messages in the RSS feed item.
*
* @param string $content Feed item content.
* @param string $context Feed item context, 'excerpt' or 'full'.
*
* @return string
*/
private function embed_rss( $content, $context = 'full' ) {
if ( false === $this->can_embed_footer( $content, $context ) ) {
return $content;
}
$before = $this->get_rss_content( 'before' );
$after = $this->get_rss_content( 'after' );
if ( '' === $before && '' === $after ) {
return $content;
}
if ( 'excerpt' === $context && '' !== trim( $content ) ) {
$content = wpautop( $content );
}
return $before . $content . $after;
}
/**
* Check if we can add the RSS footer and/or header to the RSS feed item.
*
* @copyright Copyright (C) 2008-2019, Yoast BV
* The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
*
* @param string $content Feed item content.
* @param string $context Feed item context, either 'excerpt' or 'full'.
*
* @return bool
*/
private function can_embed_footer( $content, $context ) {
/**
* Allow the RSS footer to be dynamically shown/hidden.
*
* @param bool $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 ( false === $this->do_filter( 'frontend/rss/include_footer', true, $context ) ) {
return false;
}
return is_feed();
}
/**
* Get RSS content for specified location.
*
* @param string $which Location ID.
*
* @return string
*/
private function get_rss_content( $which ) {
$content = $this->do_filter( 'frontend/rss/' . $which . '_content', Helper::get_settings( 'general.rss_' . $which . '_content' ) );
return '' !== $content ? wpautop( $this->rss_replace_vars( $content ) ) : $content;
}
/**
* Replace variables with the actual values in RSS header and footer messages.
*
* @param string $content The RSS content.
*
* @return string
*/
private function rss_replace_vars( $content ) {
global $post;
/**
* Add nofollow for the links in the RSS header and footer messages. Default: true.
*
* @param bool $unsigned Whether or not to follow the links in RSS feed, defaults to true.
*/
$no_follow = $this->do_filter( 'frontend/rss/nofollow_links', true );
$no_follow = true === $no_follow ? 'rel="nofollow" ' : '';
$author_link = '';
if ( is_object( $post ) ) {
$author_link = '<a ' . $no_follow . 'href="' . esc_url( get_author_posts_url( $post->post_author ) ) . '">' . esc_html( get_the_author() ) . '</a>';
}
$post_link = '<a ' . $no_follow . 'href="' . esc_url( get_permalink() ) . '">' . esc_html( get_the_title() ) . '</a>';
$blog_link = '<a ' . $no_follow . 'href="' . esc_url( get_bloginfo( 'url' ) ) . '">' . esc_html( get_bloginfo( 'name' ) ) . '</a>';
$blog_desc_link = '<a ' . $no_follow . 'href="' . esc_url( get_bloginfo( 'url' ) ) . '">' . esc_html( get_bloginfo( 'name' ) ) . ' - ' . esc_html( get_bloginfo( 'description' ) ) . '</a>';
// Featured image.
$image = Helper::get_thumbnail_with_fallback( $post->ID, 'full' );
$image = isset( $image[0] ) ? '<img src="' . $image[0] . '" style="display: block; margin: 1em auto">' : '';
$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 );
$content = str_replace( '%FEATUREDIMAGE%', $image, $content );
return $content;
}
}

View File

@@ -0,0 +1,447 @@
<?php
/**
* The <head> tag.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\Frontend
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Frontend;
use RankMath\Post;
use RankMath\Helper;
use RankMath\Paper\Paper;
use RankMath\Traits\Hooker;
use RankMath\Sitemap\Router;
use RankMath\Helpers\Str;
use RankMath\Helpers\Arr;
use RankMath\Helpers\Security;
defined( 'ABSPATH' ) || exit;
/**
* Head class.
*
* @copyright Copyright (C) 2008-2019, Yoast BV
* The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
*/
class Head {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'wp_head', 'head', 1 );
if ( Helper::is_amp_active() ) {
$this->action( 'amphtml_template_head', 'head', 1 );
$this->action( 'weeblramp_print_meta_data', 'head', 1 );
$this->action( 'better-amp/template/head', 'head', 99 );
$this->action( 'amp_post_template_head', 'head', 9 );
remove_action( 'better-amp/template/head', 'better_amp_print_rel_canonical' );
}
$this->action( 'wp_head', 'front_page_init', 0 );
$this->filter( 'language_attributes', 'search_results_schema' );
$this->action( 'rank_math/head', 'metadesc', 6 );
$this->action( 'rank_math/head', 'robots', 10 );
$this->action( 'rank_math/head', 'canonical', 20 );
$this->action( 'rank_math/head', 'adjacent_rel_links', 21 );
$this->action( 'rank_math/head', 'metakeywords', 22 );
$this->filter( 'wp_title', 'title', 15 );
$this->filter( 'thematic_doctitle', 'title', 15 );
$this->filter( 'pre_get_document_title', 'title', 15 );
// Code to move title inside the Rank Math's meta.
remove_action( 'wp_head', '_wp_render_title_tag', 1 );
add_action( 'rank_math/head', '_wp_render_title_tag', 1 );
// Force Rewrite title.
if ( Helper::get_settings( 'titles.rewrite_title' ) && ! current_theme_supports( 'title-tag' ) ) {
$this->action( 'get_header', 'start_ob', 0 );
$this->action( 'wp_head', 'rewrite_title', 9999 );
}
// Remove core robots data.
if ( ! is_embed() ) {
remove_all_filters( 'wp_robots' );
}
}
/**
* Initialize front page related stuff.
*/
public function front_page_init() {
if ( ! is_front_page() ) {
return;
}
$this->action( 'rank_math/head', 'webmaster_tools_authentication', 90 );
}
/**
* Output authentication codes for all the Webmaster Tools.
*/
public function webmaster_tools_authentication() {
$tools = [
'google_verify' => 'google-site-verification',
'bing_verify' => 'msvalidate.01',
'baidu_verify' => 'baidu-site-verification',
'yandex_verify' => 'yandex-verification',
'pinterest_verify' => 'p:domain_verify',
'norton_verify' => 'norton-safeweb-site-verification',
];
foreach ( $tools as $id => $name ) {
$content = trim( Helper::get_settings( "general.{$id}" ) );
$content = $this->do_filter( 'webmaster/' . $id, $content );
if ( empty( $content ) ) {
continue;
}
printf( '<meta name="%1$s" content="%2$s" />' . "\n", esc_attr( $name ), esc_attr( $content ) );
}
$custom_webmaster_tags = Helper::get_settings( 'general.custom_webmaster_tags' );
if ( empty( $custom_webmaster_tags ) ) {
return;
}
$custom_webmaster_tags = Arr::from_string( $custom_webmaster_tags );
foreach ( $custom_webmaster_tags as $custom_webmaster_tag ) {
$custom_webmaster_tag = trim( $custom_webmaster_tag );
if ( empty( $custom_webmaster_tag ) ) {
continue;
}
echo $custom_webmaster_tag . "\n";
}
}
/**
* Add Search Result Page schema as language attributes for the <html> tag.
*
* @param string $output A space-separated list of language attributes.
* @return string
*/
public function search_results_schema( $output ) {
if ( ! is_search() ) {
return $output;
}
return preg_replace( '/itemtype="([^"]+)"/', 'itemtype="https://schema.org/SearchResultsPage', $output );
}
/**
* Main function attached to the wp_head hook.
*/
public function head() {
global $wp_query;
$old_wp_query = null;
if ( ! $wp_query->is_main_query() ) {
$old_wp_query = $wp_query;
wp_reset_query();
}
$this->credits();
// Remove core actions, now handled by Rank Math.
remove_action( 'wp_head', 'rel_canonical' );
remove_action( 'wp_head', 'index_rel_link' );
remove_action( 'wp_head', 'start_post_rel_link' );
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' );
remove_action( 'wp_head', 'noindex', 1 );
if ( Helper::is_amp_active() ) {
remove_action( 'amp_post_template_head', 'amp_post_template_add_title' );
remove_action( 'amp_post_template_head', 'amp_post_template_add_canonical' );
remove_action( 'amp_post_template_head', 'amp_print_schemaorg_metadata' );
}
/**
* Add extra output in the head tag.
*/
$this->do_action( 'head' );
$this->credits( true );
if ( ! empty( $old_wp_query ) ) {
$GLOBALS['wp_query'] = $old_wp_query;
unset( $old_wp_query );
}
}
/**
* Main title function.
*
* @param string $title Already set title or empty string.
* @return string
*/
public function title( $title ) {
if ( is_feed() ) {
return $title;
}
$generated = Paper::get()->get_title();
return Str::is_non_empty( $generated ) ? $generated : $title;
}
/**
* Output the meta description tag with the generated description.
*/
public function metadesc() {
$generated = Paper::get()->get_description();
if ( Str::is_non_empty( $generated ) ) {
echo '<meta name="description" content="' . $generated . '"/>', "\n";
}
}
/**
* Output the meta robots tag.
*/
public function robots() {
$robots = Paper::get()->get_robots();
$robotsstr = join( ', ', $robots );
if ( Str::is_non_empty( $robotsstr ) ) {
echo '<meta name="robots" content="', esc_attr( $robotsstr ), '"/>', "\n";
}
// If a page is noindex, let's remove the canonical URL.
// https://www.seroundtable.com/google-noindex-rel-canonical-confusion-26079.html .
if ( isset( $robots['index'] ) && 'noindex' === $robots['index'] ) {
$this->remove_action( 'rank_math/head', 'canonical', 20 );
$this->remove_action( 'rank_math/head', 'adjacent_rel_links', 21 );
}
}
/**
* Output the canonical URL tag.
*/
public function canonical() {
$canonical = Paper::get()->get_canonical();
if ( Str::is_non_empty( $canonical ) ) {
echo '<link rel="canonical" href="' . esc_url( $canonical, null, 'other' ) . '" />' . "\n";
}
}
/**
* Add the rel 'prev' and 'next' links to archives or single posts.
*
* @link http://googlewebmastercentral.blogspot.com/2011/09/pagination-with-relnext-and-relprev.html
*/
public function adjacent_rel_links() {
/**
* Enable rel "next" & "prev" tags on sites running Genesis.
*
* @param bool $unsigned Whether or not to show rel next / prev .
*/
if ( is_home() && function_exists( 'genesis' ) && false === $this->do_filter( 'frontend/genesis/force_adjacent_rel_home', false ) ) {
return;
}
/**
* Disable rel 'prev' and 'next' links.
*
* @param bool $disable Rel 'prev' and 'next' links should be disabled or not.
*/
if ( true === $this->do_filter( 'frontend/disable_adjacent_rel_links', false ) ) {
return;
}
if ( is_singular() ) {
$this->adjacent_rel_links_single();
return;
}
$this->adjacent_rel_links_archive();
}
/**
* Output the meta keywords value.
*/
public function metakeywords() {
/**
* Passing a truthy value to the filter will effectively short-circuit the
* set keywords process.
*
* @param bool $return Short-circuit return value. Either false or true.
*/
if ( ! $this->do_filter( 'frontend/show_keywords', false ) ) {
return;
}
$keywords = Paper::get()->get_keywords();
if ( Str::is_non_empty( $keywords ) ) {
echo '<meta name="keywords" content="', esc_attr( $keywords ), '"/>', "\n";
}
}
/**
* Output the rel next/prev tags on a paginated single post.
*
* @return void
*/
private function adjacent_rel_links_single() {
$num_pages = 1;
$queried_object = get_queried_object();
if ( ! empty( $queried_object ) ) {
$num_pages = substr_count( $queried_object->post_content, '<!--nextpage-->' ) + 1;
}
if ( 1 === $num_pages ) {
return;
}
$page = max( 1, (int) get_query_var( 'page' ) );
$url = get_permalink( get_queried_object_id() );
if ( $page > 1 ) {
$this->adjacent_rel_link( 'prev', $url, $page - 1, 'page' );
}
if ( $page < $num_pages ) {
$this->adjacent_rel_link( 'next', $url, $page + 1, 'page' );
}
}
/**
* Output the rel next/prev tags on archives.
*/
private function adjacent_rel_links_archive() {
$url = Paper::get()->get_canonical( true, true );
if ( ! is_string( $url ) || '' === $url ) {
return;
}
$paged = max( 1, (int) get_query_var( 'paged' ) );
if ( 2 === $paged ) {
$this->adjacent_rel_link( 'prev', $url, $paged - 1 );
}
if ( is_front_page() ) {
$url = Router::get_base_url( '' );
}
if ( $paged > 2 ) {
$this->adjacent_rel_link( 'prev', $url, $paged - 1 );
}
if ( $paged < $GLOBALS['wp_query']->max_num_pages ) {
$this->adjacent_rel_link( 'next', $url, $paged + 1 );
}
}
/**
* Build adjacent page link for archives.
*
* @param string $rel Prev or next.
* @param string $url The current archive URL without page parameter.
* @param string $page The page number added to the $url in the link tag.
* @param string $query_arg The pagination query argument to use for the $url.
*/
private function adjacent_rel_link( $rel, $url, $page, $query_arg = 'paged' ) {
global $wp_rewrite;
if ( $page > 1 ) {
$url = ! $wp_rewrite->using_permalinks() ? Security::add_query_arg_raw( $query_arg, $page, $url ) : user_trailingslashit( trailingslashit( $url ) . $this->get_pagination_base() . $page );
}
/**
* Change the link rel HTML output.
*
* @param string $link The `<link rel=""` tag.
*/
$link = $this->do_filter( "frontend/{$rel}_rel_link", '<link rel="' . esc_attr( $rel ) . '" href="' . esc_url( $url ) . "\" />\n" );
if ( Str::is_non_empty( $link ) ) {
echo $link;
}
}
/**
* Get pagination base.
*
* @return string The pagination base.
*/
private function get_pagination_base() {
global $wp_rewrite;
return ( ! is_singular() || Post::is_home_static_page() ) ? trailingslashit( $wp_rewrite->pagination_base ) : '';
}
/**
* Credits.
*
* @param boolean $closing Is closing credits needed.
*/
private function credits( $closing = false ) {
/**
* Disable credit in the HTML source.
*
* @param bool $remove
*/
if ( $this->do_filter( 'frontend/remove_credit_notice', false ) ) {
return;
}
if ( false === $closing ) {
if ( ! Helper::is_whitelabel() && ! defined( 'RANK_MATH_PRO_FILE' ) ) {
echo "\n<!-- " . esc_html__( 'Search Engine Optimization by Rank Math - https://rankmath.com/', 'rank-math' ) . " -->\n";
} elseif ( defined( 'RANK_MATH_PRO_FILE' ) ) {
echo "\n<!-- " . esc_html__( 'Search Engine Optimization by Rank Math PRO - https://rankmath.com/', 'rank-math' ) . " -->\n";
}
return;
}
if ( ! Helper::is_whitelabel() ) {
echo '<!-- /' . esc_html__( 'Rank Math WordPress SEO plugin', 'rank-math' ) . " -->\n\n";
}
}
/**
* Start the Output Buffer.
*
* @since 1.0.29
*/
public function start_ob() {
ob_start();
}
/**
* Use output buffering to force rewrite the title tag.
*/
public function rewrite_title() {
global $wp_query;
// Check if we're in the main query.
$old_wp_query = null;
if ( ! $wp_query->is_main_query() ) {
$old_wp_query = $wp_query;
wp_reset_query();
}
$content = ob_get_clean();
$title = Paper::get()->get_title();
if ( empty( $title ) ) {
echo $content;
}
// Find all title tags, remove them, and add the new one.
$content = preg_replace( '/<title.*?\/title>/i', '', $content );
$content = str_replace( '<head>', '<head>' . "\n" . '<title>' . esc_html( $title ) . '</title>', $content );
if ( ! empty( $old_wp_query ) ) {
$GLOBALS['wp_query'] = $old_wp_query;
}
echo $content;
}
}

View File

@@ -0,0 +1,322 @@
<?php
/**
* The class handles adding of attributes to links to content.
*
* @since 1.0.43.2
* @package RankMath
* @subpackage RankMath\Frontend
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Frontend;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Str;
use RankMath\Helpers\Url;
use RankMath\Helpers\HTML;
defined( 'ABSPATH' ) || exit;
/**
* Add Link_Attributes class.
*/
class Link_Attributes {
use Hooker;
/**
* Add rel=noopener or not.
*
* @var bool
*/
public $add_noopener;
/**
* Add rel=nofollow to links or not.
*
* @var bool
*/
public $nofollow_link;
/**
* Add rel=nofollow to images or not.
*
* @var bool
*/
public $nofollow_image;
/**
* Open links in a new window or not.
*
* @var bool
*/
public $new_window_link;
/**
* Remove existing CSS class from links or not.
*
* @var bool
*/
public $remove_class;
/**
* Check if the link attributes have been modified or not.
*
* @var bool
*/
public $is_dirty;
/**
* Additional attributes to add to links.
*
* @var array
*/
public $add_attributes;
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'wp', 'add_attributes', 9999 );
$this->action( 'rest_api_init', 'add_attributes' );
}
/**
* Add nofollow, target, title and alt attributes to link and images.
*/
public function add_attributes() {
// Add rel="nofollow" & target="_blank" for external links.
$this->add_noopener = $this->do_filter( 'noopener', true );
$this->nofollow_link = Helper::get_settings( 'general.nofollow_external_links' );
$this->nofollow_image = Helper::get_settings( 'general.nofollow_image_links' );
$this->new_window_link = Helper::get_settings( 'general.new_window_external_links' );
$this->remove_class = $this->do_filter( 'link/remove_class', false );
$this->is_dirty = false;
// Filter to run the link attributes function even when Link options are disabled.
$this->add_attributes = $this->do_filter( 'link/add_attributes', $this->nofollow_link || $this->new_window_link || $this->nofollow_image || $this->add_noopener );
if ( $this->add_attributes || $this->remove_class ) {
$this->filter( 'the_content', 'add_link_attributes', 11 );
}
}
/**
* Add nofollow and target attributes to link.
*
* @param string $content Post content.
* @return string
*/
public function add_link_attributes( $content ) {
preg_match_all( '/<(a\s[^>]+)>/', $content, $matches );
if ( empty( $matches ) || empty( $matches[0] ) ) {
return $content;
}
foreach ( $matches[0] as $link ) {
$attrs = HTML::extract_attributes( $link );
if ( ! $this->can_add_attributes( $attrs ) ) {
continue;
}
$attrs = $this->remove_link_class( $attrs );
$attrs = $this->set_external_attrs( $attrs );
if ( $this->is_dirty ) {
$new = '<a' . HTML::attributes_to_string( $attrs ) . '>';
$content = str_replace( $link, $new, $content );
}
}
return $content;
}
/**
* Set rel attribute.
*
* @param array $attrs Array which hold rel attribute.
* @param string $property Property to add.
* @param boolean $append Append or not.
*/
private function set_rel_attribute( &$attrs, $property, $append ) {
if ( empty( $attrs['rel'] ) ) {
$attrs['rel'] = $property;
return;
}
if ( $append ) {
$attrs['rel'] .= ' ' . $property;
}
}
/**
* Check if we can do anything
*
* @param array $attrs Array of link attributes.
*
* @return boolean
*/
private function can_add_attributes( $attrs ) {
// If link has no href attribute or if the link is not valid then we don't need to do anything.
if (
empty( $attrs['href'] ) ||
( empty( wp_parse_url( $attrs['href'], PHP_URL_HOST ) ) && ! Url::is_affiliate( $attrs['href'] ) ) ||
( isset( $attrs['role'] ) && 'button' === $attrs['role'] )
) {
return false;
}
return true;
}
/**
* Remove rank-math-link class.
*
* @since 1.0.44.2
*
* @param array $attrs Array of link attributes.
*
* @return array $attrs
*/
private function remove_link_class( $attrs ) {
if ( ! $this->remove_class || empty( $attrs['class'] ) || strpos( $attrs['class'], 'rank-math-link' ) === false ) {
return $attrs;
}
$this->is_dirty = true;
$attrs['class'] = str_replace( 'rank-math-link', '', $attrs['class'] );
if ( ! trim( $attrs['class'] ) ) {
unset( $attrs['class'] );
}
return $attrs;
}
/**
* Set External attributs
*
* @since 1.0.44.2
*
* @param array $attrs Array of link attributes.
*
* @return array $attrs
*/
private function set_external_attrs( $attrs ) {
if ( ! $this->add_attributes ) {
return $attrs;
}
// Skip if there is no href or it's a hash link like "#id".
// Skip if relative link.
// Skip for same domain ignoring sub-domain if any.
if ( ! Url::is_external( $attrs['href'] ) ) {
return $attrs;
}
if ( $this->do_filter( 'nofollow/url', $this->should_add_nofollow( $attrs['href'] ), $attrs['href'] ) ) {
if ( $this->nofollow_link || ( $this->nofollow_image && $this->is_valid_image( $attrs['href'] ) ) ) {
$this->is_dirty = true;
$this->set_rel_attribute( $attrs, 'nofollow', ( isset( $attrs['rel'] ) && ! Str::contains( 'dofollow', $attrs['rel'] ) && ! Str::contains( 'nofollow', $attrs['rel'] ) ) );
}
}
if ( $this->new_window_link && ! isset( $attrs['target'] ) ) {
$this->is_dirty = true;
$attrs['target'] = '_blank';
}
if ( $this->add_noopener && $this->do_filter( 'noopener/domain', Url::get_domain( $attrs['href'] ) ) ) {
$this->is_dirty = true;
$this->set_rel_attribute( $attrs, 'noopener', ( isset( $attrs['rel'] ) && ! Str::contains( 'noopener', $attrs['rel'] ) ) );
}
if ( Url::is_affiliate( $attrs['href'] ) ) {
$this->is_dirty = true;
$this->set_rel_attribute( $attrs, 'sponsored', ( isset( $attrs['rel'] ) && ! Str::contains( 'sponsored', $attrs['rel'] ) ) );
}
return $attrs;
}
/**
* Check if we need to add nofollow for this link, based on "nofollow_domains" & "nofollow_exclude_domains"
*
* @param string $url Link URL.
* @return bool
*/
private function should_add_nofollow( $url ) {
if ( ! $this->nofollow_link && ! $this->nofollow_image ) {
return false;
}
$include_domains = $this->get_nofollow_domains( 'include' );
$exclude_domains = $this->get_nofollow_domains( 'exclude' );
$parent_domain = Url::get_domain( $url );
$parent_domain = preg_replace( '/^www\./', '', $parent_domain );
// Check if domain is in list.
if ( ! empty( $include_domains ) ) {
return in_array( $parent_domain, $include_domains, true );
}
// Check if domain is NOT in list.
if ( ! empty( $exclude_domains ) && in_array( $parent_domain, $exclude_domains, true ) ) {
return false;
}
return true;
}
/**
* Get domain for nofollow
*
* @param string $type Type either include or exclude.
* @return array
*/
private function get_nofollow_domains( $type ) {
static $rank_math_nofollow_domains;
if ( isset( $rank_math_nofollow_domains[ $type ] ) ) {
return $rank_math_nofollow_domains[ $type ];
}
$setting = 'include' === $type ? 'nofollow_domains' : 'nofollow_exclude_domains';
$domains = Helper::get_settings( "general.{$setting}" );
$domains = Str::to_arr_no_empty( $domains );
// Strip off www. prefixes.
$domains = array_map(
function( $domain ) {
$domain = preg_replace( '#^http(s)?://#', '', trim( $domain, '/' ) );
return preg_replace( '/^www\./', '', $domain );
},
$domains
);
$rank_math_nofollow_domains[ $type ] = $domains;
return $rank_math_nofollow_domains[ $type ];
}
/**
* Is a valid image url.
*
* @param string $url Image url.
*
* @return boolean
*/
private function is_valid_image( $url ) {
foreach ( [ '.jpg', '.jpeg', '.png', '.gif' ] as $ext ) {
if ( Str::contains( $ext, $url ) ) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* The class handles redirection of attachment & archive pages
*
* @since 1.0.216
* @package RankMath
* @subpackage RankMath\Frontend
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Frontend;
use RankMath\Helper;
use RankMath\Traits\Hooker;
defined( 'ABSPATH' ) || exit;
/**
* Add Link_Attributes class.
*/
class Redirection {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
if ( Helper::is_module_active( 'redirections' ) ) {
$this->filter( 'rank_math/redirection/pre_search', 'pre_redirection', 10, 3 );
return;
}
$this->action( 'wp', 'redirect' );
}
/**
* Pre-filter the redirection.
*
* @param string $check Check.
* @param string $uri Current URL.
* @param string $full_uri Full URL.
*
* @return string|array
*/
public function pre_redirection( $check, $uri, $full_uri ) {
if ( $new_link = $this->get_redirection_url() ) { // phpcs:ignore
return [
'url_to' => $new_link,
'header_code' => 301,
];
}
return $check;
}
/**
* Redirect product with base to the new link.
*/
public function redirect() {
if ( $link = $this->get_redirection_url() ) { // phpcs:ignore
Helper::redirect( $link, 301 );
exit;
}
}
/**
* Get Redirection URL.
*
* @return string Modified URL
*/
private function get_redirection_url() {
// Redirect attachment page to parent post.
if ( is_attachment() && Helper::get_settings( 'general.attachment_redirect_urls', true ) ) {
global $post;
$redirect = ! empty( $post->post_parent ) ? get_permalink( $post->post_parent ) : Helper::get_settings( 'general.attachment_redirect_default' );
if ( ! $redirect ) {
return;
}
/**
* Redirect attachment to its parent post.
*
* @param string $redirect URL as calculated for redirection.
* @param WP_Post $post Current post instance.
*/
return $this->do_filter( 'frontend/attachment/redirect_url', $redirect, $post );
}
// Redirect archives.
global $wp_query;
if (
( Helper::get_settings( 'titles.disable_date_archives' ) && $wp_query->is_date ) ||
( true === Helper::get_settings( 'titles.disable_author_archives' ) && $wp_query->is_author )
) {
return get_bloginfo( 'url' );
}
return false;
}
}

View File

@@ -0,0 +1,494 @@
<?php
/**
* The Shortcodes of the plugin.
*
* @since 0.9.0
* @package RankMath
* @subpackage RankMath\Frontend
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Frontend;
use RankMath\Helper;
use RankMath\Paper\Paper;
use RankMath\Traits\Hooker;
use RankMath\Traits\Shortcode;
use RankMath\Helpers\Arr;
defined( 'ABSPATH' ) || exit;
/**
* Shortcodes class.
*/
class Shortcodes {
use Hooker, Shortcode;
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'init', 'init' );
}
/**
* Initialize.
*/
public function init() {
// Remove Yoast shortcodes.
$this->remove_shortcode( 'wpseo_address' );
$this->remove_shortcode( 'wpseo_map' );
$this->remove_shortcode( 'wpseo_opening_hours' );
$this->remove_shortcode( 'wpseo_breadcrumb' );
$this->remove_shortcode( 'aioseo_breadcrumbs' );
// Add Yoast compatibility shortcodes.
$this->add_shortcode( 'wpseo_address', 'yoast_address' );
$this->add_shortcode( 'wpseo_map', 'yoast_map' );
$this->add_shortcode( 'wpseo_opening_hours', 'yoast_opening_hours' );
$this->add_shortcode( 'wpseo_breadcrumb', 'breadcrumb' );
$this->add_shortcode( 'aioseo_breadcrumbs', 'breadcrumb' );
// Add the Contact shortcode.
$this->add_shortcode( 'rank_math_contact_info', 'contact_info' );
// Add the Breadcrumbs shortcode.
$this->add_shortcode( 'rank_math_breadcrumb', 'breadcrumb' );
}
/**
* Get the breadcrumbs.
*
* @param array $args Arguments.
*
* @return string
*/
public function breadcrumb( $args ) {
if ( ! Helper::is_breadcrumbs_enabled() ) {
return;
}
return Breadcrumbs::get()->get_breadcrumb( $args );
}
/**
* Contact info shortcode, displays nicely formatted contact informations.
*
* @param array $args Optional. Shortcode arguments - currently only 'show'
* parameter, which is a comma-separated list of elements to show.
* @return string Shortcode output.
*/
public function contact_info( $args ) {
$args = shortcode_atts(
[
'show' => 'all',
'class' => '',
],
$args,
'contact-info'
);
$allowed = $this->get_allowed_info( $args );
wp_enqueue_style( 'rank-math-contact-info', rank_math()->assets() . 'css/rank-math-contact-info.css', null, rank_math()->version );
ob_start();
echo '<div class="' . esc_attr( $this->get_contact_classes( $allowed, $args['class'] ) ) . '">';
foreach ( $allowed as $element ) {
$method = 'display_' . $element;
if ( method_exists( $this, $method ) ) {
echo '<div class="rank-math-contact-section rank-math-contact-' . esc_attr( $element ) . '">';
$this->$method();
echo '</div>';
}
}
echo '</div>';
echo '<div class="clear"></div>';
/**
* Change the Contact Info HTML output.
*
* @param string $unsigned HTML output.
*/
return $this->do_filter( 'contact_info/html', ob_get_clean() );
}
/**
* Get allowed info array.
*
* @param array $args Shortcode arguments - currently only 'show'.
*
* @return array
*/
private function get_allowed_info( $args ) {
$type = Helper::get_settings( 'titles.knowledgegraph_type' );
$allowed = 'person' === $type
? [ 'name', 'email', 'person_phone', 'address' ]
: [ 'name', 'organization_description', 'email', 'address', 'hours', 'phone', 'additional_info', 'map' ];
if ( ! empty( $args['show'] ) && 'all' !== $args['show'] ) {
$allowed = array_intersect( Arr::from_string( $args['show'] ), $allowed );
}
return $allowed;
}
/**
* Get contact info container classes.
*
* @param array $allowed Allowed elements.
* @param array $extra_class Shortcode arguments.
* @return string
*/
private function get_contact_classes( $allowed, $extra_class ) {
$classes = [ 'rank-math-contact-info', $extra_class ];
foreach ( $allowed as $elem ) {
$classes[] = sanitize_html_class( 'show-' . $elem );
}
if ( count( $allowed ) === 1 ) {
$classes[] = sanitize_html_class( 'show-' . $elem . '-only' );
}
return join( ' ', array_filter( $classes ) );
}
/**
* Output address.
*/
private function display_address() {
$address = Helper::get_settings( 'titles.local_address' );
if ( false === $address ) {
return;
}
$format = nl2br( Helper::get_settings( 'titles.local_address_format' ) );
/**
* Allow developer to change the address part format.
*
* @param string $parts_format String format to output the address part.
*/
$parts_format = $this->do_filter( 'shortcode/contact/address_parts_format', '<span class="contact-address-%1$s">%2$s</span>' );
$hash = [
'streetAddress' => 'address',
'addressLocality' => 'locality',
'addressRegion' => 'region',
'postalCode' => 'postalcode',
'addressCountry' => 'country',
];
?>
<label><?php esc_html_e( 'Address:', 'rank-math' ); ?></label>
<address>
<?php
foreach ( $hash as $key => $tag ) {
$value = '';
if ( isset( $address[ $key ] ) && ! empty( $address[ $key ] ) ) {
$value = sprintf( $parts_format, $tag, $address[ $key ] );
}
$format = str_replace( "{{$tag}}", $value, $format );
}
echo $format;
?>
</address>
<?php
}
/**
* Output opening hours.
*/
private function display_hours() {
$hours = Helper::get_settings( 'titles.opening_hours' );
if ( ! isset( $hours[0]['time'] ) ) {
return;
}
$combined = $this->get_hours_combined( $hours );
$format = Helper::get_settings( 'titles.opening_hours_format' );
?>
<label><?php esc_html_e( 'Hours:', 'rank-math' ); ?></label>
<div class="rank-math-contact-hours-details">
<?php
foreach ( $combined as $time => $days ) {
if ( $format ) {
$hours = explode( '-', $time );
$time = isset( $hours[1] ) ? date_i18n( 'g:i a', strtotime( $hours[0] ) ) . '-' . date_i18n( 'g:i a', strtotime( $hours[1] ) ) : $time;
}
$time = str_replace( '-', ' &ndash; ', $time );
printf(
'<div class="rank-math-opening-hours"><span class="rank-math-opening-days">%1$s</span><span class="rank-math-opening-time">%2$s</span></div>',
join( ', ', $days ),
$time
);
}
?>
</div>
<?php
}
/**
* Combine hours in an hour
*
* @param array $hours Hours to combine.
* @return array
*/
private function get_hours_combined( $hours ) {
$combined = [];
foreach ( $hours as $hour ) {
if ( empty( $hour['time'] ) ) {
continue;
}
$combined[ trim( $hour['time'] ) ][] = $this->get_localized_day( $hour['day'] );
}
return $combined;
}
/**
* Retrieve the full translated weekday word.
*
* @param string $day Day to translate.
*
* @return string
*/
private function get_localized_day( $day ) {
global $wp_locale;
$hash = [
'Sunday' => 0,
'Monday' => 1,
'Tuesday' => 2,
'Wednesday' => 3,
'Thursday' => 4,
'Friday' => 5,
'Saturday' => 6,
];
return $wp_locale->get_weekday( $hash[ $day ] );
}
/**
* Output phone numbers.
*/
private function display_phone() {
$phones = Helper::get_settings( 'titles.phone_numbers' );
if ( empty( $phones ) ) {
return;
}
$choices = Helper::choices_phone_types();
foreach ( $phones as $phone ) :
if ( empty( $phone['number'] ) ) {
continue;
}
$number = esc_html( $phone['number'] );
$label = isset( $choices[ $phone['type'] ] ) ? $choices[ $phone['type'] ] : ''
?>
<div class="rank-math-phone-number type-<?php echo sanitize_html_class( $phone['type'] ); ?>">
<label><?php echo esc_html( $label ); ?>:</label>
<span><?php echo isset( $phone['number'] ) ? '<a href="tel://' . $number . '">' . $number . '</a>' : ''; ?></span>
</div>
<?php
endforeach;
}
/**
* Output Person phone number.
*/
private function display_person_phone() {
$phone = Helper::get_settings( 'titles.phone' );
if ( empty( $phone ) ) {
return;
}
?>
<div class="rank-math-phone-numberx">
<label><?php echo esc_html__( 'Telephone', 'rank-math' ); ?>:</label>
<span><a href="tel://<?php echo esc_attr( $phone ); ?>"><?php echo esc_html( $phone ); ?></a></span>
</div>
<?php
}
/**
* Output google map.
*/
private function display_map() {
$api_key = Helper::get_settings( 'titles.maps_api_key' );
if ( ! $api_key ) {
return;
}
$address = Helper::get_settings( 'titles.local_address' );
if ( false === $address ) {
return;
}
/**
* Filter address for Google Map in contact shortcode.
*
* @param string $address
*/
$address = $this->do_filter( 'shortcode/contact/map_address', implode( ' ', $address ) );
$address = $this->do_filter( 'shortcode/contact/map_iframe_src', '//maps.google.com/maps?q=' . rawurlencode( $address ) . '&z=15&output=embed&key=' . rawurlencode( $api_key ) );
?>
<iframe src="<?php echo esc_url( $address ); ?>"></iframe>
<?php
}
/**
* Output name.
*/
private function display_name() {
$name = Helper::get_settings( 'titles.knowledgegraph_name' );
if ( false === $name ) {
return;
}
$url = Helper::get_settings( 'titles.url' );
?>
<h4 class="rank-math-name">
<a href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $name ); ?></a>
</h4>
<?php
}
/**
* Output email.
*/
private function display_email() {
$email = Helper::get_settings( 'titles.email' );
if ( false === $email ) {
return;
}
?>
<div class="rank-math-email">
<label><?php esc_html_e( 'Email:', 'rank-math' ); ?></label>
<a href="mailto:<?php echo esc_attr( $email ); ?>"><?php echo esc_html( $email ); ?></a>
</div>
<?php
}
/**
* Output Organization description.
*/
private function display_organization_description() {
$description = Helper::get_settings( 'titles.organization_description' );
if ( ! $description ) {
return;
}
?>
<div class="rank-math-organization-description">
<label><?php esc_html_e( 'Description:', 'rank-math' ); ?></label>
<p><?php echo esc_html( $description ); ?></p>
</div>
<?php
}
/**
* Output Additional Organization details.
*/
private function display_additional_info() {
$properties = Helper::get_settings( 'titles.additional_info' );
if ( empty( $properties ) ) {
return;
}
$choices = Helper::choices_additional_organization_info();
foreach ( $properties as $property ) {
if ( empty( $property['value'] ) ) {
continue;
}
?>
<div class="rank-math-organization-additional-details">
<label><?php echo esc_html( $choices[ $property['type'] ] ); ?>:</label>
<span><?php echo esc_html( $property['value'] ); ?></span>
</div>
<?php
}
}
/**
* Yoast address compatibility functionality.
*
* @param array $args Array of arguments.
* @return string
*/
public function yoast_address( $args ) {
$atts = shortcode_atts(
[
'hide_name' => '0',
'hide_address' => '0',
'show_state' => '1',
'show_country' => '1',
'show_phone' => '1',
'show_phone_2' => '1',
'show_fax' => '1',
'show_email' => '1',
'show_url' => '0',
'show_vat' => '0',
'show_tax' => '0',
'show_coc' => '0',
'show_price_range' => '0',
'show_logo' => '0',
'show_opening_hours' => '0',
],
$args,
'wpseo_address'
);
$show = [ 'address' ];
if ( 1 === absint( $atts['show_phone'] ) ) {
$show[] = 'phone';
}
if ( 1 === absint( $atts['show_opening_hours'] ) ) {
$show[] = 'hours';
}
return $this->contact_info(
[
'show' => join( ',', $show ),
'class' => 'wpseo_address_compat',
]
);
}
/**
* Yoast map compatibility functionality.
*
* @param array $args Array of arguments.
* @return string
*/
public function yoast_map( $args ) {
return $this->contact_info(
[
'show' => 'map',
'class' => 'wpseo_map_compat',
]
);
}
/**
* Yoast opening hours compatibility functionality.
*
* @param array $args Array of arguments.
* @return string
*/
public function yoast_opening_hours( $args ) {
return $this->contact_info(
[
'show' => 'hours',
'class' => 'wpseo_opening_hours_compat',
]
);
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* The PostArchive Class
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Archive class.
*/
class Archive implements IPaper {
/**
* Build the title for a post type archive.
*
* @return string
*/
public function title() {
$post_type = $this->get_queried_post_type();
return Paper::get_from_options( "pt_{$post_type}_archive_title", [], '%pt_plural% Archive %page% %sep% %sitename%' );
}
/**
* Build the description for a post type archive.
*
* @return string
*/
public function description() {
$post_type = $this->get_queried_post_type();
return Paper::get_from_options( "pt_{$post_type}_archive_description", [], '%pt_plural% Archive %page% %sep% %sitename%' );
}
/**
* Retrieves the robots for a post type archive.
*
* @return string The robots to use on a post type archive.
*/
public function robots() {
$robots = [];
$post_type = $this->get_queried_post_type();
if ( Helper::get_settings( "titles.pt_{$post_type}_custom_robots" ) ) {
$robots = Paper::robots_combine( Helper::get_settings( "titles.pt_{$post_type}_robots" ) );
}
return $robots;
}
/**
* Retrieves the advanced robots for a post type archive.
*
* @return array The advanced robots to use on a post type archive.
*/
public function advanced_robots() {
$robots = [];
$post_type = $this->get_queried_post_type();
if ( Helper::get_settings( "titles.pt_{$post_type}_custom_robots" ) ) {
$robots = Paper::advanced_robots_combine( Helper::get_settings( "titles.pt_{$post_type}_advanced_robots" ) );
}
return $robots;
}
/**
* Get the canonical URL.
*
* @return array
*/
public function canonical() {
return [ 'canonical' => get_post_type_archive_link( $this->get_queried_post_type() ) ];
}
/**
* Get the meta keywords.
*
* @return string
*/
public function keywords() {
return '';
}
/**
* Get the queried post type.
*
* @return string
*/
private 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;
}
}

View File

@@ -0,0 +1,115 @@
<?php
/**
* The Author Class
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\User;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Author class.
*/
class Author implements IPaper {
/**
* Get the SEO title set in the user metabox.
*
* @return string
*/
public function title() {
$title = User::get_meta( 'title', $this->get_user_id() );
if ( '' !== $title ) {
return $title;
}
return Paper::get_from_options( 'author_archive_title' );
}
/**
* Get the SEO description set in the user metabox.
*
* @return string
*/
public function description() {
$description = User::get_meta( 'description', $this->get_user_id() );
if ( '' !== $description ) {
return $description;
}
return Paper::get_from_options( 'author_archive_description' );
}
/**
* Get the robots meta value set in the user metabox.
*
* @return string
*/
public function robots() {
$robots = Paper::robots_combine( User::get_meta( 'robots', $this->get_user_id() ) );
if ( empty( $robots ) && Helper::get_settings( 'titles.author_custom_robots' ) ) {
$robots = Paper::robots_combine( Helper::get_settings( 'titles.author_robots' ), true );
}
return $robots;
}
/**
* Get the advanced robots meta set in the user metabox.
*
* @return array
*/
public function advanced_robots() {
$robots = Paper::advanced_robots_combine( User::get_meta( 'advanced_robots', $this->get_user_id() ) );
if ( empty( $robots ) && Helper::get_settings( 'titles.author_custom_robots' ) ) {
$robots = Paper::advanced_robots_combine( Helper::get_settings( 'titles.author_advanced_robots' ), true );
}
return $robots;
}
/**
* Get the canonical URL.
*
* @return array
*/
public function canonical() {
return [
'canonical' => get_author_posts_url( $this->get_user_id(), get_query_var( 'author_name' ) ),
'canonical_override' => User::get_meta( 'canonical_url', $this->get_user_id() ),
];
}
/**
* Get the meta keywords for the user (in our case, the Focus Keywords).
*
* @return string
*/
public function keywords() {
return User::get_meta( 'focus_keyword', $this->get_user_id() );
}
/**
* Get the user ID on the author archive or BBPress profile.
*
* @return int
*/
private function get_user_id() {
$author_id = get_query_var( 'author' );
if ( $author_id ) {
return $author_id;
}
return get_query_var( 'bbp_user_id' );
}
}

View File

@@ -0,0 +1,103 @@
<?php
/**
* The Home Class
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Post;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Blog class.
*/
class Blog implements IPaper {
/**
* Builds the title for Homepage.
*
* @return string The title to use on homepage.
*/
public function title() {
return Paper::get_from_options( 'homepage_title' );
}
/**
* Builds the description for Homepage.
*
* @return string The description to use on a homepage.
*/
public function description() {
return Paper::get_from_options( 'homepage_description', [], get_bloginfo( 'description' ) );
}
/**
* Retrieves the robots for Homepage.
*
* @return string The robots specified for the homepage.
*/
public function robots() {
$robots = [];
if ( Helper::get_settings( 'titles.homepage_custom_robots' ) ) {
$robots = Paper::robots_combine( Helper::get_settings( 'titles.homepage_robots' ) );
}
if ( is_paged() && Helper::get_settings( 'titles.noindex_paginated_pages' ) ) {
$robots['index'] = 'noindex';
}
return $robots;
}
/**
* Retrieves the advanced robots for Homepage.
*
* @return array The advanced robots specified for the homepage.
*/
public function advanced_robots() {
if ( ! Helper::get_settings( 'titles.homepage_custom_robots' ) ) {
return [];
}
return Paper::advanced_robots_combine( Helper::get_settings( 'titles.homepage_advanced_robots' ) );
}
/**
* Retrieves the canonical URL.
*
* @return array
*/
public function canonical() {
$canonical = home_url();
if ( Post::is_posts_page() ) {
$posts_page_id = get_option( 'page_for_posts' );
$canonical = Post::get_meta( 'canonical_url', $posts_page_id );
if ( empty( $canonical ) ) {
$canonical = get_permalink( $posts_page_id );
}
}
return [ 'canonical' => $canonical ];
}
/**
* Retrieves the keywords.
*
* @return string The focus keywords.
*/
public function keywords() {
if ( ! Post::is_posts_page() ) {
return '';
}
return Post::get_meta( 'focus_keyword', get_option( 'page_for_posts' ) );
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* The Date Class
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Date class.
*/
class Date implements IPaper {
/**
* Get the SEO title for a date archive.
*
* @return string
*/
public function title() {
return Paper::get_from_options( 'date_archive_title' );
}
/**
* Get the SEO description for a date archive.
*
* @return string
*/
public function description() {
return Paper::get_from_options( 'date_archive_description' );
}
/**
* Get the robots meta for a date archive.
*
* @return string
*/
public function robots() {
$robots = [];
$robots = Paper::robots_combine( Helper::get_settings( 'titles.date_archive_robots' ) );
if ( Helper::get_settings( 'titles.disable_date_archives' ) ) {
$robots['index'] = 'noindex';
}
return $robots;
}
/**
* Get the advanced robots meta for a date archive.
*
* @return array
*/
public function advanced_robots() {
return Paper::advanced_robots_combine( Helper::get_settings( 'titles.date_advanced_robots' ) );
}
/**
* Get the canonical URL for the current page.
*
* @return array
*/
public function canonical() {
$canonical = '';
if ( is_day() ) {
$canonical = get_day_link( get_query_var( 'year' ), get_query_var( 'monthnum' ), get_query_var( 'day' ) );
} elseif ( is_month() ) {
$canonical = get_month_link( get_query_var( 'year' ), get_query_var( 'monthnum' ) );
} elseif ( is_year() ) {
$canonical = get_year_link( get_query_var( 'year' ) );
}
return [ 'canonical' => $canonical ];
}
/**
* Get the meta keywords.
*
* @return string
*/
public function keywords() {
return '';
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* The 404 paper.
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
defined( 'ABSPATH' ) || exit;
/**
* 404 Error.
*/
class Error_404 implements IPaper {
/**
* Retrieves the SEO title.
*
* @return string
*/
public function title() {
return Paper::get_from_options( '404_title', [], esc_html__( 'Page not found', 'rank-math' ) );
}
/**
* Retrieves the SEO description.
*
* @return string
*/
public function description() {
return '';
}
/**
* Retrieves the robots.
*
* @return string
*/
public function robots() {
return [ 'index' => 'noindex' ];
}
/**
* Retrieves the advanced robots.
*
* @return array
*/
public function advanced_robots() {
return [];
}
/**
* Retrieves the canonical URL.
*
* @return array
*/
public function canonical() {
return [];
}
/**
* Retrieves meta keywords.
*
* @return string
*/
public function keywords() {
return '';
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* The Misc paper.
*
* @since 1.0.28
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
defined( 'ABSPATH' ) || exit;
/**
* Misc class.
*/
class Misc implements IPaper {
/**
* Retrieves the SEO title.
*
* @return string
*/
public function title() {
return '';
}
/**
* Retrieves the SEO description.
*
* @return string
*/
public function description() {
return '';
}
/**
* Retrieves the robots.
*
* @return string
*/
public function robots() {
return [];
}
/**
* Retrieves the advanced robots.
*
* @return array
*/
public function advanced_robots() {
return [];
}
/**
* Retrieves the canonical URL.
*
* @return array
*/
public function canonical() {
return [];
}
/**
* Retrieves meta keywords.
*
* @return string
*/
public function keywords() {
return '';
}
}

View File

@@ -0,0 +1,557 @@
<?php
/**
* The Paper Class
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Post;
use RankMath\Helper;
use RankMath\Sitemap\Router;
use RankMath\Traits\Hooker;
use RankMath\Helpers\Str;
use RankMath\Helpers\Url;
use RankMath\Helpers\Security;
defined( 'ABSPATH' ) || exit;
/**
* Paper class.
*/
class Paper {
use Hooker;
/**
* Hold the class instance.
*
* @var object
*/
private static $instance = null;
/**
* Hold current paper object.
*
* @var IPaper
*/
private $paper = null;
/**
* Hold title.
*
* @var string
*/
private $title = null;
/**
* Hold description.
*
* @var string
*/
private $description = null;
/**
* Hold robots.
*
* @var array
*/
private $robots = null;
/**
* Hold canonical.
*
* @var array
*/
private $canonical = null;
/**
* Hold keywords.
*
* @var string
*/
private $keywords = null;
/**
* Initialize object
*
* @return object Post|Term|User.
*/
public static function get() {
if ( ! is_null( self::$instance ) ) {
return self::$instance;
}
self::$instance = new Paper();
self::$instance->setup();
return self::$instance;
}
/**
* Setup paper.
*/
private function setup() {
foreach ( $this->get_papers() as $class_name => $is_valid ) {
if ( $this->do_filter( 'paper/is_valid/' . strtolower( $class_name ), $is_valid ) ) {
$class_name = '\\RankMath\\Paper\\' . $class_name;
$this->paper = new $class_name();
break;
}
}
if ( ! method_exists( $this->paper, 'set_object' ) ) {
return;
}
if ( Post::is_home_static_page() ) {
$this->paper->set_object( get_queried_object() );
} elseif ( Post::is_simple_page() ) {
$post = Post::get( Post::get_page_id() );
$this->paper->set_object( $post->get_object() );
}
}
/**
* Get papers types.
*
* @return array
*/
private function get_papers() {
return $this->do_filter(
'paper/hash',
[
'Search' => is_search(),
'Shop' => Post::is_shop_page(),
'Singular' => Post::is_home_static_page() || Post::is_simple_page(),
'Blog' => Post::is_home_posts_page(),
'Author' => is_author() || ( Helper::is_module_active( 'bbpress' ) && function_exists( 'bbp_is_single_user' ) && bbp_is_single_user() ),
'Date' => is_date(),
'Taxonomy' => is_category() || is_tag() || is_tax(),
'Archive' => is_archive(),
'Error_404' => is_404(),
'Misc' => true,
]
);
}
/**
* Get title after sanitization.
*
* @return string
*/
public function get_title() {
if ( ! is_null( $this->title ) ) {
return $this->title;
}
/**
* Allow changing the title.
*
* @param string $title The page title being put out.
*/
$this->title = $this->do_filter( 'frontend/title', $this->paper->title() );
// Early Bail!!
if ( '' === $this->title ) {
return $this->title;
}
// Remove excess whitespace.
$this->title = preg_replace( '[\s\s+]', ' ', $this->title );
// Capitalize Titles.
if ( Helper::get_settings( 'titles.capitalize_titles' ) ) {
$this->title = Str::mb_ucwords( $this->title );
}
$this->title = wp_strip_all_tags( stripslashes( $this->title ), true );
$this->title = esc_html( $this->title );
$this->title = convert_smilies( $this->title );
return $this->title;
}
/**
* Get description after sanitization.
*
* @return string
*/
public function get_description() {
if ( ! is_null( $this->description ) ) {
return $this->description;
}
/**
* Allow changing the meta description sentence.
*
* @param string $description The description sentence.
*/
$this->description = $this->do_filter( 'frontend/description', trim( $this->paper->description() ) );
// Early Bail!!
if ( '' === $this->description ) {
return $this->description;
}
$this->description = wp_strip_all_tags( stripslashes( $this->description ), true );
$this->description = esc_attr( $this->description );
return $this->description;
}
/**
* Get robots after sanitization.
*
* @return array
*/
public function get_robots() {
if ( ! is_null( $this->robots ) ) {
return $this->robots;
}
$this->robots = $this->paper->robots();
if ( empty( $this->robots ) ) {
$this->robots = self::robots_combine( Helper::get_settings( 'titles.robots_global' ) );
}
$this->validate_robots();
$this->respect_settings_for_robots();
/**
* Allows filtering of the meta robots.
*
* @param array $robots The meta robots directives to be echoed.
*/
$this->robots = $this->do_filter( 'frontend/robots', array_unique( $this->robots ) );
$this->advanced_robots();
return $this->robots;
}
/**
* Validate robots.
*/
private function validate_robots() {
if ( empty( $this->robots ) || ! is_array( $this->robots ) ) {
$this->robots = [
'index' => 'index',
'follow' => 'follow',
];
return;
}
$this->robots = array_intersect_key(
$this->robots,
[
'index' => '',
'follow' => '',
'noarchive' => '',
'noimageindex' => '',
'nosnippet' => '',
]
);
// Add Index and Follow.
if ( ! isset( $this->robots['index'] ) ) {
$this->robots = [ 'index' => 'index' ] + $this->robots;
}
if ( ! isset( $this->robots['follow'] ) ) {
$this->robots = [ 'follow' => 'follow' ] + $this->robots;
}
}
/**
* Add Advanced robots.
*/
private function advanced_robots() {
// Early Bail if robots is set to noindex or nosnippet!
if ( ( isset( $this->robots['index'] ) && 'noindex' === $this->robots['index'] ) || ( isset( $this->robots['nosnippet'] ) && 'nosnippet' === $this->robots['nosnippet'] ) ) {
return;
}
$advanced_robots = $this->paper->advanced_robots();
if ( ! is_array( $advanced_robots ) ) {
$advanced_robots = wp_parse_args(
Helper::get_settings( 'titles.advanced_robots_global' ),
[
'max-snippet' => -1,
'max-video-preview' => -1,
'max-image-preview' => 'large',
]
);
$advanced_robots = self::advanced_robots_combine( $advanced_robots );
}
$advanced_robots = array_intersect_key(
$advanced_robots,
[
'max-snippet' => '',
'max-video-preview' => '',
'max-image-preview' => '',
]
);
/**
* Allows filtering of the advanced meta robots.
*
* @param array $robots The meta robots directives to be echoed.
*/
$advanced_robots = $this->do_filter( 'frontend/advanced_robots', array_unique( $advanced_robots ) );
$this->robots = ! empty( $advanced_robots ) ? $this->robots + $advanced_robots : $this->robots;
}
/**
* Get focus keywords
*
* @return string
*/
public function get_keywords() {
if ( ! is_null( $this->keywords ) ) {
return $this->keywords;
}
/**
* Allows filtering of the meta keywords.
*
* @param array $keywords The meta keywords to be echoed.
*/
$this->keywords = $this->do_filter( 'frontend/keywords', $this->paper->keywords() );
return $this->keywords;
}
/**
* Respect some robots settings.
*/
private function respect_settings_for_robots() {
// If blog is not public or replytocom is set, then force noindex.
if ( 0 === absint( get_option( 'blog_public' ) ) || isset( $_GET['replytocom'] ) ) {
$this->robots['index'] = 'noindex';
$this->robots['follow'] = 'nofollow';
}
// Force noindex for sub-pages.
if ( is_paged() && Helper::get_settings( 'titles.noindex_archive_subpages' ) ) {
$this->robots['index'] = 'noindex';
}
}
/**
* Get canonical after sanitization.
*
* @param bool $un_paged Whether or not to return the canonical with or without pagination added to the URL.
* @param bool $no_override Whether or not to return a manually overridden canonical.
*
* @return string
*/
public function get_canonical( $un_paged = false, $no_override = false ) {
if ( is_null( $this->canonical ) ) {
$this->generate_canonical();
}
$canonical = $this->canonical['canonical'];
if ( $un_paged ) {
$canonical = $this->canonical['canonical_unpaged'];
} elseif ( $no_override ) {
$canonical = $this->canonical['canonical_no_override'];
}
return $canonical;
}
/**
* Generate canonical URL parts.
*/
private function generate_canonical() {
$this->canonical = wp_parse_args(
$this->paper->canonical(),
[
'canonical' => false,
'canonical_unpaged' => false,
'canonical_override' => false,
]
);
extract( $this->canonical ); // phpcs:ignore
if ( is_front_page() || ( function_exists( 'ampforwp_is_front_page' ) && ampforwp_is_front_page() ) ) {
$canonical = user_trailingslashit( home_url() );
}
// If not singular than we can have pagination.
if ( ! is_singular() ) {
$canonical_unpaged = $canonical;
$canonical = $this->get_canonical_paged( $canonical );
}
$this->canonical['canonical_unpaged'] = $canonical_unpaged;
$this->canonical['canonical_no_override'] = $canonical;
// Force absolute URLs for canonicals.
$canonical = Str::is_non_empty( $canonical ) && true === Url::is_relative( $canonical ) ? $this->base_url( $canonical ) : $canonical;
$canonical = Str::is_non_empty( $canonical_override ) ? $canonical_override : $canonical;
/**
* Filter the canonical URL.
*
* @param string $canonical The canonical URL.
*/
$this->canonical['canonical'] = apply_filters( 'rank_math/frontend/canonical', $canonical );
}
/**
* Get the paged version of the canonical URL if needed.
*
* @param string $canonical The canonical URL.
*
* @return string
*/
private function get_canonical_paged( $canonical ) {
global $wp_rewrite;
if ( ! $canonical || get_query_var( 'paged' ) < 2 ) {
return $canonical;
}
if ( ! $wp_rewrite->using_permalinks() ) {
return Security::add_query_arg_raw(
'paged',
get_query_var( 'paged' ),
is_front_page() ? trailingslashit( $canonical ) : $canonical
);
}
return user_trailingslashit(
trailingslashit( is_front_page() ? Router::get_base_url( '' ) : $canonical ) .
trailingslashit( $wp_rewrite->pagination_base ) .
get_query_var( 'paged' )
);
}
/**
* Get the base URL for relative URLs by parsing the home URL.
*
* @copyright Copyright (C) 2008-2019, Yoast BV
* The following code is a derivative work of the code from the Yoast (https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
*
* @param string $path Optional path string.
* @return string
*/
private function base_url( $path = null ) {
$parts = wp_parse_url( get_option( 'home' ) );
$base_url = trailingslashit( $parts['scheme'] . '://' . $parts['host'] );
if ( ! is_null( $path ) ) {
$base_url .= ltrim( $path, '/' );
}
return $base_url;
}
/**
* Get title or description option from the settings.
* The results will be run through the Helper::replace_vars() function.
*
* @param string $id Name of the option we are looking for.
* @param object|array $object Object to pass to the replace_vars function.
* @param string $default Default value if nothing found.
*
* @return string
*/
public static function get_from_options( $id, $object = [], $default = '' ) {
$value = Helper::get_settings( "titles.$id" );
// Break loop.
if ( ! Str::ends_with( 'default_snippet_name', $value ) && ! Str::ends_with( 'default_snippet_desc', $value ) ) {
$value = \str_replace(
[ '%seo_title%', '%seo_description%' ],
[ '%title%', '%excerpt%' ],
$value
);
}
return Helper::replace_vars( '' !== $value ? $value : $default, $object );
}
/**
* Make robots values as keyed array.
*
* @param array $robots Main instance.
* @param bool $default Append default.
*
* @return array
*/
public static function robots_combine( $robots, $default = false ) {
if ( empty( $robots ) || ! is_array( $robots ) ) {
return ! $default ? [] : [
'index' => 'index',
'follow' => 'follow',
];
}
$robots = array_combine( $robots, $robots );
// Fix noindex key to index.
if ( isset( $robots['noindex'] ) ) {
$robots = [ 'index' => $robots['noindex'] ] + $robots;
unset( $robots['noindex'] );
}
// Fix nofollow key to follow.
if ( isset( $robots['nofollow'] ) ) {
$robots = [ 'follow' => $robots['nofollow'] ] + $robots;
unset( $robots['nofollow'] );
}
return $robots;
}
/**
* Make robots values as keyed array.
*
* @param array $advanced_robots Main instance.
*
* @return array
*/
public static function advanced_robots_combine( $advanced_robots ) {
if ( empty( $advanced_robots ) ) {
return;
}
$robots = [];
foreach ( $advanced_robots as $key => $data ) {
if ( $data ) {
$robots[ $key ] = $key . ':' . $data;
}
}
return $robots;
}
/**
* Should apply shortcode on content.
*
* @return bool
*/
public static function should_apply_shortcode() {
if (
Post::is_woocommerce_page() ||
( function_exists( 'is_wcfm_page' ) && is_wcfm_page() )
) {
return false;
}
return apply_filters( 'rank_math/paper/auto_generated_description/apply_shortcode', false );
}
/**
* Clears and reinitializes the object.
*/
public static function reset() {
self::$instance = null;
return self::get();
}
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* The Search Results paper.
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Search results.
*/
class Search implements IPaper {
/**
* Retrieves the SEO title.
*
* @return string
*/
public function title() {
return Paper::get_from_options( 'search_title', [], 'Searched for %search_query% %page% %sep% %sitename%' );
}
/**
* Retrieves the SEO description.
*
* @return string
*/
public function description() {
return '';
}
/**
* Retrieves the robots.
*
* @return string
*/
public function robots() {
return Helper::get_settings( 'titles.noindex_search' ) ? [ 'index' => 'noindex' ] : [];
}
/**
* Retrieves the advanced robots.
*
* @return array
*/
public function advanced_robots() {
return [];
}
/**
* Retrieves the canonical URL.
*
* @return array
*/
public function canonical() {
$search_query = get_search_query();
return [ 'canonical' => ! empty( $search_query ) && ! preg_match( '|^page/\d+$|', $search_query ) ? get_search_link() : '' ];
}
/**
* Retrieves meta keywords.
*
* @return string
*/
public function keywords() {
return '';
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* The Shop paper.
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Post;
use RankMath\Helper;
use RankMath\Helpers\Str;
defined( 'ABSPATH' ) || exit;
/**
* Shop.
*/
class Shop extends Singular {
/**
* Retrieves the WooCommerce Shop SEO title.
*
* @return string
*/
public function title() {
$post = Post::get( Post::get_shop_page_id() );
$title = $this->get_post_title( $post->get_object() );
// Early Bail!
if ( Str::is_non_empty( $title ) ) {
return $title;
}
return Paper::get_from_options( 'pt_product_archive_title', [], '%pt_plural% Archive %page% %sep% %sitename%' );
}
/**
* Retrieves the WooCommerce Shop SEO description.
*
* @return string
*/
public function description() {
$post = Post::get( Post::get_shop_page_id() );
$desc = $this->get_post_description( $post->get_object() );
return '' !== $desc ? $desc : Paper::get_from_options( 'pt_product_archive_description', [], '%pt_plural% Archive %page% %sep% %sitename%' );
}
/**
* Retrieves the WooCommerce Shop robots.
*
* @return string
*/
public function robots() {
$post = Post::get( Post::get_shop_page_id() );
return $this->get_post_robots( $post->get_object() );
}
/**
* Retrieves the WooCommerce Shop advanced robots.
*
* @return array
*/
public function advanced_robots() {
$post = Post::get( Post::get_shop_page_id() );
$object = $post->get_object();
return $this->get_post_advanced_robots( $object );
}
/**
* Retrieves meta keywords.
*
* @return string The focus keywords.
*/
public function keywords() {
return Post::get_meta( 'focus_keyword', Post::get_shop_page_id() );
}
}

View File

@@ -0,0 +1,226 @@
<?php
/**
* The Singular Class
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Post;
use RankMath\Helper;
use RankMath\Helpers\Security;
use RankMath\Helpers\Str;
defined( 'ABSPATH' ) || exit;
/**
* Singular class.
*/
class Singular implements IPaper {
/**
* Post object.
*
* @var WP_Post
*/
private $object;
/**
* Retrieves the SEO title.
*
* @return string
*/
public function title() {
return $this->get_post_title( $this->object );
}
/**
* Retrieves the SEO description.
*
* @return string
*/
public function description() {
return $this->get_post_description( $this->object );
}
/**
* Retrieves the robots.
*
* @return string
*/
public function robots() {
return $this->get_post_robots( $this->object );
}
/**
* Retrieves the advanced robots.
*
* @return array
*/
public function advanced_robots() {
return $this->get_post_advanced_robots( $this->object );
}
/**
* Retrieves the canonical URL.
*
* @return array
*/
public function canonical() {
$object_id = Post::get_page_id();
$canonical = get_permalink( $object_id );
$canonical_unpaged = $canonical;
$canonical_override = Post::get_meta( 'canonical_url', $object_id );
/**
* Fix paginated pages canonical, but only if the page is truly paginated.
*
* @copyright Copyright (C) 2008-2019, Yoast BV
* The following code is a derivative work of the code from the Yoast(https://github.com/Yoast/wordpress-seo/), which is licensed under GPL v3.
*/
if ( is_singular() && get_query_var( 'page' ) > 1 ) {
$num_pages = ( substr_count( get_queried_object()->post_content, '<!--nextpage-->' ) + 1 );
if ( $num_pages && get_query_var( 'page' ) <= $num_pages ) {
global $wp_rewrite;
$canonical = ! $wp_rewrite->using_permalinks() ? Security::add_query_arg_raw( 'page', get_query_var( 'page' ), $canonical ) :
user_trailingslashit( trailingslashit( $canonical ) . get_query_var( 'page' ) );
}
}
return [
'canonical' => $canonical,
'canonical_unpaged' => $canonical,
'canonical_override' => $canonical_override,
];
}
/**
* Retrieves meta keywords.
*
* @return string The focus keywords.
*/
public function keywords() {
return Post::get_meta( 'focus_keyword', $this->object->ID );
}
/**
* Set post object.
*
* @param WP_Post $object Current post object.
*/
public function set_object( $object ) {
$this->object = $object;
}
/**
* Get the SEO title set in the post metabox.
*
* @param object|null $object Post object to retrieve the title for.
*
* @return string
*/
protected function get_post_title( $object = null ) {
if ( ! is_object( $object ) ) {
return Paper::get_from_options( '404_title', [], esc_html__( 'Page not found', 'rank-math' ) );
}
$title = Post::get_meta( 'title', $object->ID );
if ( '' !== $title ) {
return $title;
}
$post_type = isset( $object->post_type ) ? $object->post_type : $object->query_var;
return Paper::get_from_options( "pt_{$post_type}_title", $object, '%title% %sep% %sitename%' );
}
/**
* Retrieves the SEO description set in the post metabox.
*
* Retrieve in this order:
* 1. Custom meta description set for the post in SERP field
* 2. Excerpt
* 3. Description template set in the Titles & Meta
* 4. Paragraph with the focus keyword
* 5. The First paragraph of the content
*
* @param object|null $object Object to retrieve the description from.
*
* @return string The SEO description for the specified object, or queried object if not supplied.
*/
protected function get_post_description( $object = null ) {
if ( ! is_object( $object ) ) {
return '';
}
// 1. Custom meta description set for the post in SERP field.
$description = Post::get_meta( 'description', $object->ID );
if ( '' !== $description ) {
return $description;
}
// 2. Excerpt
if ( ! empty( $object->post_excerpt ) ) {
return $object->post_excerpt;
}
// 3. Description template set in the Titles & Meta.
$post_type = isset( $object->post_type ) ? $object->post_type : $object->query_var;
return Str::truncate( Paper::get_from_options( "pt_{$post_type}_description", $object ), 160 );
}
/**
* Retrieves the robots set in the post metabox.
*
* @param object|null $object Object to retrieve the robots data from.
*
* @return string The robots for the specified object, or queried object if not supplied.
*/
protected function get_post_robots( $object = null ) {
if ( ! is_object( $object ) ) {
return [];
}
$post_type = $object->post_type;
$robots = Paper::robots_combine( Post::get_meta( 'robots', $object->ID ) );
if ( empty( $robots ) && Helper::get_settings( "titles.pt_{$post_type}_custom_robots" ) ) {
$robots = Paper::robots_combine( Helper::get_settings( "titles.pt_{$post_type}_robots" ), true );
}
// `noindex` these conditions.
$noindex_private = 'private' === $object->post_status;
$no_index_subpages = is_paged() && Helper::get_settings( 'titles.noindex_paginated_pages' );
$noindex_password_protected = ! empty( $object->post_password ) && Helper::get_settings( 'titles.noindex_password_protected' );
if ( $noindex_private || $noindex_password_protected || $no_index_subpages ) {
$robots['index'] = 'noindex';
}
return $robots;
}
/**
* Retrieves the advanced robots set in the post metabox.
*
* @param object|null $object Object to retrieve the robots data from.
*
* @return string The robots for the specified object, or queried object if not supplied.
*/
protected function get_post_advanced_robots( $object = null ) {
if ( ! is_object( $this->object ) ) {
return [];
}
$post_type = $this->object->post_type;
$robots = Paper::advanced_robots_combine( Post::get_meta( 'advanced_robots', $this->object->ID ) );
if ( ! is_array( $robots ) && Helper::get_settings( "titles.pt_{$post_type}_custom_robots" ) ) {
$robots = Paper::advanced_robots_combine( Helper::get_settings( "titles.pt_{$post_type}_advanced_robots" ), true );
}
return $robots;
}
}

View File

@@ -0,0 +1,157 @@
<?php
/**
* The Term Class
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
use RankMath\Term;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Taxonomy class.
*/
class Taxonomy implements IPaper {
/**
* Retrieves the SEO title for a taxonomy.
*
* @return string The SEO title for the taxonomy.
*/
public function title() {
$object = get_queried_object();
if ( ! is_object( $object ) ) {
return Paper::get_from_options( '404_title', [], esc_html__( 'Page not found', 'rank-math' ) );
}
$title = Term::get_meta( 'title', $object, $object->taxonomy );
if ( '' !== $title ) {
return $title;
}
return Paper::get_from_options( "tax_{$object->taxonomy}_title", $object );
}
/**
* Retrieves the SEO description for a taxonomy.
*
* @return string The SEO description for the taxonomy.
*/
public function description() {
$object = get_queried_object();
$description = Term::get_meta( 'description', $object, $object->taxonomy );
if ( '' !== $description ) {
return $description;
}
return Paper::get_from_options( "tax_{$object->taxonomy}_description", $object );
}
/**
* Retrieves the robots for a taxonomy.
*
* @return string The robots for the taxonomy
*/
public function robots() {
$object = get_queried_object();
$robots = Paper::robots_combine( Term::get_meta( 'robots', $object ) );
if ( is_object( $object ) && empty( $robots ) && Helper::get_settings( "titles.tax_{$object->taxonomy}_custom_robots" ) ) {
$robots = Paper::robots_combine( Helper::get_settings( "titles.tax_{$object->taxonomy}_robots" ), true );
}
if ( $this->noindex_term( $object ) ) {
$robots['index'] = 'noindex';
}
return $robots;
}
/**
* Retrieves the advanced robots for a taxonomy.
*
* @return array The advanced robots for the taxonomy
*/
public function advanced_robots() {
$object = get_queried_object();
$robots = Paper::advanced_robots_combine( Term::get_meta( 'advanced_robots', $object ) );
if ( is_object( $object ) && empty( $robots ) && Helper::get_settings( "titles.tax_{$object->taxonomy}_custom_robots" ) ) {
$robots = Paper::advanced_robots_combine( Helper::get_settings( "titles.tax_{$object->taxonomy}_advanced_robots" ), true );
}
return $robots;
}
/**
* Retrieves the canonical URL.
*
* @return array
*/
public function canonical() {
$object = get_queried_object();
if ( empty( $object ) || Term::is_multiple_terms_query() ) {
return [];
}
$term_link = get_term_link( $object, $object->taxonomy );
return [
'canonical' => is_wp_error( $term_link ) ? '' : $term_link,
'canonical_override' => Term::get_meta( 'canonical_url', $object, $object->taxonomy ),
];
}
/**
* Retrieves the keywords.
*
* @return string The focus keywords.
*/
public function keywords() {
$object = get_queried_object();
if ( empty( $object ) || Term::is_multiple_terms_query() ) {
return '';
}
return Term::get_meta( 'focus_keyword', $object, $object->taxonomy );
}
/**
* Whether to noindex empty terms.
*
* @param object $object Current taxonomy term object.
*
* @return bool
*/
private function noindex_term( $object ) {
if ( Term::is_multiple_terms_query() ) {
return true;
}
if ( is_object( $object ) && 0 === $object->count && Helper::get_settings( 'titles.noindex_empty_taxonomies' ) ) {
$children = get_terms(
$object->taxonomy,
[
'parent' => $object->term_id,
'number' => 1,
'fields' => 'ids',
]
);
if ( empty( $children ) ) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* The Paper Interface
*
* @since 1.0.22
* @package RankMath
* @subpackage RankMath\Paper
* @author Rank Math <support@rankmath.com>
*/
namespace RankMath\Paper;
defined( 'ABSPATH' ) || exit;
/**
* Paper interface.
*/
interface IPaper {
/**
* Retrieves the SEO title.
*
* @return string
*/
public function title();
/**
* Retrieves the SEO description.
*
* @return string
*/
public function description();
/**
* Retrieves the robots.
*
* @return string
*/
public function robots();
/**
* Retrieves the advanced robots.
*
* @return array
*/
public function advanced_robots();
/**
* Retrieves the canonical URL.
*
* @return array
*/
public function canonical();
/**
* Retrieves the keywords.
*
* @return string The focus keywords.
*/
public function keywords();
}