Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
@@ -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' => ' / ',
|
||||
'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 “%s”', '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;
|
||||
}
|
||||
}
|
@@ -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=(["\'])(?:.*(?:\?|&|&)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;
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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( '-', ' – ', $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',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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' );
|
||||
}
|
||||
}
|
@@ -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' ) );
|
||||
}
|
||||
}
|
@@ -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 '';
|
||||
}
|
||||
}
|
@@ -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 '';
|
||||
}
|
||||
}
|
@@ -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 '';
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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 '';
|
||||
}
|
||||
}
|
@@ -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() );
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
Reference in New Issue
Block a user