Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
/**
|
||||
* The HTML sitemap generator for authors.
|
||||
*
|
||||
* @since 1.0.104
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Sitemap
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Sitemap\Html;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Admin\Database\Database;
|
||||
use RankMath\Sitemap\Providers\Author;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Terms class.
|
||||
*/
|
||||
class Authors extends Author {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Get all authors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_authors() {
|
||||
$sort_map = [
|
||||
'published' => [
|
||||
'field' => 'user_registered',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
'modified' => [
|
||||
'field' => 'user_registered',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
'alphabetical' => [
|
||||
'field' => 'display_name',
|
||||
'order' => 'ASC',
|
||||
],
|
||||
'post_id' => [
|
||||
'field' => 'ID',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
];
|
||||
|
||||
$sort_setting = Helper::get_settings( 'sitemap.html_sitemap_sort' );
|
||||
$sort = ( isset( $sort_map[ $sort_setting ] ) ) ? $sort_map[ $sort_setting ] : $sort_map['published'];
|
||||
|
||||
/**
|
||||
* Filter: 'rank_math/sitemap/html_sitemap/sort_items' - Allow changing the sort order of the HTML sitemap.
|
||||
*
|
||||
* @var array $sort {
|
||||
* @type string $field The field to sort by.
|
||||
* @type string $order The sort order.
|
||||
* }
|
||||
* @var string $order The item type.
|
||||
* @var string $empty Empty string (unused).
|
||||
*/
|
||||
$sort = $this->do_filter( 'sitemap/html_sitemap/sort_items', $sort, 'authors', '' );
|
||||
$defaults = [
|
||||
'orderby' => $sort['field'],
|
||||
'order' => $sort['order'],
|
||||
];
|
||||
$args = $this->do_filter( 'sitemap/author/query', wp_parse_args( [ 'posts_per_page' => -1 ], $defaults ) );
|
||||
$users = $this->get_users( $args );
|
||||
|
||||
if ( empty( $users ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is not in the excluded roles and doesn't have noindex set.
|
||||
*
|
||||
* @param object $user Partial user data from database.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function should_include_user( $user ) {
|
||||
$excluded_roles = (array) Helper::get_settings( 'sitemap.exclude_roles' );
|
||||
$roles = (array) get_userdata( $user->ID )->roles;
|
||||
$intersect = array_intersect( $roles, $excluded_roles );
|
||||
if ( ! empty( $intersect ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$robots = get_user_meta( $user->ID, 'rank_math_robots', true );
|
||||
if ( is_array( $robots ) && in_array( 'noindex', $robots, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the HTML sitemap for authors.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generate_sitemap() {
|
||||
$users = $this->get_authors();
|
||||
if ( empty( $users ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$output[] = '<div class="rank-math-html-sitemap__section rank-math-html-sitemap__section--authors">';
|
||||
$output[] = '<h2 class="rank-math-html-sitemap__title">' . esc_html__( 'Authors', 'rank-math' ) . '</h2>';
|
||||
$output[] = '<ul class="rank-math-html-sitemap__list">';
|
||||
$output[] = $this->generate_authors_list( $users );
|
||||
$output[] = '</ul>';
|
||||
$output[] = '</div>';
|
||||
|
||||
$output = implode( '', $output );
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate HTML list of authors.
|
||||
*
|
||||
* @param array $authors List of authors.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_authors_list( $authors ) {
|
||||
if ( empty( $authors ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$output = [];
|
||||
foreach ( $authors as $author ) {
|
||||
$output[] = '<li class="rank-math-html-sitemap__item">'
|
||||
. '<a href="' . esc_url( $this->get_author_link( $author ) ) . '" class="rank-math-html-sitemap__link">'
|
||||
. esc_html( $this->get_author_title( $author ) )
|
||||
. '</a>'
|
||||
. '</li>';
|
||||
}
|
||||
|
||||
return implode( '', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the author link.
|
||||
*
|
||||
* @param object $author Author data from database (not a WP_User object).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_author_link( $author ) {
|
||||
return get_author_posts_url( $author->ID, $author->user_nicename );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the author title.
|
||||
*
|
||||
* @param object $author The author data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_author_title( $author ) {
|
||||
if ( Helper::get_settings( 'sitemap.html_sitemap_seo_titles' ) !== 'seo_titles' ) {
|
||||
return $author->display_name;
|
||||
}
|
||||
|
||||
// Custom SEO title.
|
||||
$meta = get_user_meta( $author->ID, 'rank_math_title', true );
|
||||
if ( ! empty( $meta ) ) {
|
||||
return Helper::replace_vars( $meta, $author );
|
||||
}
|
||||
|
||||
// Default SEO title from the global settings.
|
||||
$template = Helper::get_settings( 'titles.pt_author_title' );
|
||||
if ( ! empty( $template ) ) {
|
||||
return Helper::replace_vars( $template, $author );
|
||||
}
|
||||
|
||||
// Fallback to author name.
|
||||
return $author->display_name;
|
||||
}
|
||||
}
|
@@ -0,0 +1,313 @@
|
||||
<?php
|
||||
/**
|
||||
* The HTML sitemap generator for posts.
|
||||
*
|
||||
* @since 1.0.104
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Sitemap
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Sitemap\Html;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Admin\Database\Database;
|
||||
use RankMath\Sitemap\Sitemap as SitemapBase;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Posts class.
|
||||
*/
|
||||
class Posts {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* An array of posts that have a parent.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $children = [];
|
||||
|
||||
/**
|
||||
* Get all posts from a given post type.
|
||||
*
|
||||
* @param string $post_type Post type.
|
||||
* @param array $post_parents An array of post parent ids.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_posts( $post_type, $post_parents = [] ) {
|
||||
global $wpdb;
|
||||
$sort_map = [
|
||||
'published' => [
|
||||
'field' => 'post_date',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
'modified' => [
|
||||
'field' => 'post_modified',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
'alphabetical' => [
|
||||
'field' => 'post_title',
|
||||
'order' => 'ASC',
|
||||
],
|
||||
'post_id' => [
|
||||
'field' => 'ID',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
];
|
||||
|
||||
$sort_setting = Helper::get_settings( 'sitemap.html_sitemap_sort' );
|
||||
$sort = ( isset( $sort_map[ $sort_setting ] ) ) ? $sort_map[ $sort_setting ] : $sort_map['published'];
|
||||
|
||||
/**
|
||||
* Filter: 'rank_math/sitemap/html_sitemap/sort_items' - Allow changing the sort order of the HTML sitemap.
|
||||
*
|
||||
* @var array $sort {
|
||||
* @type string $field The field to sort by.
|
||||
* @type string $order The sort order.
|
||||
* }
|
||||
* @var string $post_type The post type name.
|
||||
* @var string $order The item type.
|
||||
*/
|
||||
$sort = $this->do_filter( 'sitemap/html_sitemap/sort_items', $sort, 'posts', $post_type );
|
||||
|
||||
$statuses = [ 'publish' ];
|
||||
|
||||
/**
|
||||
* Filter: 'rank_math/sitemap/html_sitemap_post_statuses' - Allow changing the post statuses that should be included in the sitemap.
|
||||
*
|
||||
* @var array $statuses Post statuses.
|
||||
* @var string $post_type Post type name.
|
||||
*/
|
||||
$statuses = $this->do_filter( 'sitemap/html_sitemap_post_statuses', $statuses, $post_type );
|
||||
$get_child = ! empty( $post_parents ) ? " WHERE post_parent !='' " : '';
|
||||
$sql = "
|
||||
SELECT l.ID, post_title, post_name, post_parent, post_date, post_type, l.post_modified
|
||||
FROM (
|
||||
SELECT DISTINCT p.ID, p.post_modified FROM {$wpdb->posts} as p
|
||||
LEFT JOIN {$wpdb->postmeta} AS pm ON ( p.ID = pm.post_id AND pm.meta_key = 'rank_math_robots' )
|
||||
WHERE (
|
||||
( pm.meta_key = 'rank_math_robots' AND pm.meta_value NOT LIKE '%noindex%' ) OR
|
||||
pm.post_id IS NULL
|
||||
)
|
||||
AND p.post_type IN ( '" . $post_type . "' ) AND p.post_status IN ( '" . join( "', '", esc_sql( $statuses ) ) . "' )
|
||||
ORDER BY p.post_modified DESC
|
||||
)
|
||||
o JOIN {$wpdb->posts} l ON l.ID = o.ID " . $get_child . " ORDER BY " . $sort['field'] . " " . $sort['order']; // phpcs:ignore
|
||||
return $wpdb->get_results( $wpdb->prepare( $sql ) ); // phpcs:ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the HTML sitemap for a given post type.
|
||||
*
|
||||
* @param string $post_type Post type name.
|
||||
* @param bool $show_dates Whether to show dates.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generate_sitemap( $post_type, $show_dates ) {
|
||||
$posts = $this->get_posts( $post_type );
|
||||
|
||||
if ( empty( $posts ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$output[] = '<div class="rank-math-html-sitemap__section rank-math-html-sitemap__section--post-type rank-math-html-sitemap__section--' . $post_type . '">';
|
||||
$output[] = '<h2 class="rank-math-html-sitemap__title">' . esc_html( get_post_type_object( $post_type )->labels->name ) . '</h2>';
|
||||
$output[] = '<ul class="rank-math-html-sitemap__list">';
|
||||
$output[] = $this->generate_posts_list( $posts, $show_dates, $post_type );
|
||||
$output[] = '</ul>';
|
||||
$output[] = '</div>';
|
||||
|
||||
$output = implode( '', $output );
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the post list HTML.
|
||||
*
|
||||
* @param array $posts Array of posts.
|
||||
* @param bool $show_dates Whether to show dates.
|
||||
* @param string $post_type Post type name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_posts_list( $posts, $show_dates, $post_type ) {
|
||||
if ( empty( $posts ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( is_post_type_hierarchical( $post_type ) ) {
|
||||
$post_ids = [];
|
||||
$post_list = [];
|
||||
array_map(
|
||||
function ( $post ) use ( &$post_ids, &$post_list ) {
|
||||
$post_ids[] = $post->ID;
|
||||
$post_list[ $post->ID ] = $post;
|
||||
},
|
||||
$posts
|
||||
);
|
||||
|
||||
$children = $this->get_posts( $post_type, $post_ids );
|
||||
foreach ( $children as $child ) {
|
||||
// Confirm if child has a parent available, the parent might not be index-able and re-add the child to $posts!
|
||||
$parent = array_filter(
|
||||
$post_list,
|
||||
function ( $post ) use ( $child ) {
|
||||
return $child->post_parent === $post->ID;
|
||||
}
|
||||
);
|
||||
|
||||
if ( empty( $parent ) ) {
|
||||
$child->child_has_no_parent = true;
|
||||
$post_list[ $child->ID ] = $child;
|
||||
continue;
|
||||
}
|
||||
$this->children[ $post_type ][ $child->post_parent ][ $child->ID ] = $child;
|
||||
}
|
||||
|
||||
$post_list = $this->remove_with_parent( $post_list );
|
||||
return $this->generate_posts_list_hierarchical( $post_list, $show_dates, $post_type );
|
||||
}
|
||||
|
||||
return $this->generate_posts_list_flat( $posts, $show_dates );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post list HTML for non-hierarchical post types.
|
||||
*
|
||||
* @param array $posts The posts to output.
|
||||
* @param bool $show_dates Whether to show the post dates.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_posts_list_flat( $posts, $show_dates ) {
|
||||
$output = [];
|
||||
foreach ( $posts as $post ) {
|
||||
if ( ! SitemapBase::is_object_indexable( absint( $post->ID ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = $this->do_filter( 'sitemap/entry', esc_url( $this->get_post_link( $post ) ), 'post', $post );
|
||||
if ( empty( $url ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$output[] = '<li class="rank-math-html-sitemap__item">'
|
||||
. '<a href="' . esc_url( $this->get_post_link( $post ) ) . '" class="rank-math-html-sitemap__link">'
|
||||
. esc_html( $this->get_post_title( $post ) )
|
||||
. '</a>'
|
||||
. ( $show_dates ? ' <span class="rank-math-html-sitemap__date">(' . esc_html( mysql2date( get_option( 'date_format' ), $post->post_date ) ) . ')</span>' : '' )
|
||||
. '</li>';
|
||||
}
|
||||
|
||||
return implode( '', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post list HTML for hierarchical post types. This will output the
|
||||
* posts in a nested list.
|
||||
*
|
||||
* @param array $posts The posts to output.
|
||||
* @param bool $show_dates Whether to show the post dates.
|
||||
* @param string $post_type Post type name.
|
||||
* @param bool $child Whether the passed posts are children.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_posts_list_hierarchical( $posts, $show_dates, $post_type, $child = false ) {
|
||||
$output = [];
|
||||
$exclude = wp_parse_id_list( Helper::get_settings( 'sitemap.exclude_posts' ) );
|
||||
|
||||
foreach ( $posts as $post ) {
|
||||
$check_parent_index = empty( $post->post_parent ) ? 0 : SitemapBase::is_object_indexable( $post->post_parent );
|
||||
$is_indexable = SitemapBase::is_object_indexable( absint( $post->ID ) );
|
||||
|
||||
if ( ( ! $check_parent_index || $child ) && $is_indexable ) {
|
||||
$output[] = '<li class="rank-math-html-sitemap__item">'
|
||||
. '<a href="' . esc_url( get_permalink( $post->ID ) ) . '" class="rank-math-html-sitemap__link">'
|
||||
. esc_html( $this->get_post_title( $post ) )
|
||||
. '</a>'
|
||||
. ( $show_dates ? ' <span class="rank-math-html-sitemap__date">(' . esc_html( mysql2date( get_option( 'date_format' ), $post->post_date ) ) . ')</span>' : '' );
|
||||
}
|
||||
|
||||
if ( ! empty( $this->children[ $post_type ][ $post->ID ] ) ) {
|
||||
if ( $is_indexable ) {
|
||||
$output[] = '<ul class="rank-math-html-sitemap__list">';
|
||||
}
|
||||
|
||||
$output[] = $this->generate_posts_list_hierarchical( $this->children[ $post_type ][ $post->ID ], $show_dates, $post_type, true ); // phpcs:ignore
|
||||
|
||||
if ( $is_indexable ) {
|
||||
$output[] = '</ul>';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $is_indexable ) {
|
||||
$output[] = '</li>';
|
||||
}
|
||||
}
|
||||
|
||||
return implode( '', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post permalink.
|
||||
*
|
||||
* @param object $post The post object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_post_link( $post ) {
|
||||
return get_permalink( $post->ID );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the post title.
|
||||
*
|
||||
* @param object $post The post data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_post_title( $post ) {
|
||||
if ( Helper::get_settings( 'sitemap.html_sitemap_seo_titles' ) !== 'seo_titles' ) {
|
||||
return $post->post_title;
|
||||
}
|
||||
|
||||
// Custom SEO title.
|
||||
$meta = get_post_meta( $post->ID, 'rank_math_title', true );
|
||||
if ( ! empty( $meta ) ) {
|
||||
return Helper::replace_vars( $meta, get_post( $post->ID ) );
|
||||
}
|
||||
|
||||
// Default SEO title from the global settings.
|
||||
$template = Helper::get_settings( "titles.pt_{$post->post_type}_title" );
|
||||
if ( ! empty( $template ) ) {
|
||||
return Helper::replace_vars( $template, get_post( $post->ID ) );
|
||||
}
|
||||
|
||||
// Fallback to post title.
|
||||
return $post->post_title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes posts with a parent to avoid them being rendered twice.
|
||||
*
|
||||
* @param array $posts Array of post objects.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function remove_with_parent( $posts ) {
|
||||
return array_filter(
|
||||
$posts,
|
||||
function ( $post ) {
|
||||
return ! $post->post_parent || isset( $post->child_has_no_parent );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
/**
|
||||
* The Sitemap module - HTML Sitemap feature.
|
||||
*
|
||||
* @since 1.0.104
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Sitemap
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Sitemap\Html;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Sitemap\Providers\Taxonomy;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Sitemap\Cache;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Sitemap class.
|
||||
*/
|
||||
class Sitemap extends Taxonomy {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Generators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $generators;
|
||||
|
||||
/**
|
||||
* Cache.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( ! Helper::get_settings( 'sitemap.html_sitemap' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cache = new Cache();
|
||||
$this->generators = [
|
||||
'posts' => new Posts(),
|
||||
'terms' => new Terms(),
|
||||
'authors' => new Authors(),
|
||||
];
|
||||
|
||||
$display_mode = Helper::get_settings( 'sitemap.html_sitemap_display' );
|
||||
if ( 'page' === $display_mode ) {
|
||||
$this->action( 'the_content', 'show_on_page' );
|
||||
} elseif ( 'shortcode' === $display_mode ) {
|
||||
add_shortcode( 'rank_math_html_sitemap', [ $this, 'shortcode' ] );
|
||||
|
||||
// Compatibility code for the [aioseo_html_sitemap] shortcode.
|
||||
add_shortcode( 'aioseo_html_sitemap', [ $this, 'shortcode' ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML sitemap cache.
|
||||
*
|
||||
* @param string $name Name of the cache.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_cache( $name ) {
|
||||
if ( true !== \RankMath\Sitemap\Sitemap::is_cache_enabled() ) {
|
||||
return false;
|
||||
}
|
||||
return $this->cache->get_sitemap( $name, 1, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HTML sitemap cache.
|
||||
*
|
||||
* @param string $name Name of the cache.
|
||||
* @param string $content Content of the cache.
|
||||
*/
|
||||
private function set_cache( $name, $content ) {
|
||||
$this->cache->store_sitemap( $name, 1, $content, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get generator.
|
||||
*
|
||||
* @param string $generator Generator name.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
private function get_generator( $generator ) {
|
||||
if ( ! isset( $this->generators[ $generator ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->generators[ $generator ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the HTML sitemap output.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_output() {
|
||||
$post_types = self::get_post_types();
|
||||
$taxonomies = self::get_taxonomies();
|
||||
|
||||
/**
|
||||
* Filter the setting of excluding empty terms from the XML sitemap.
|
||||
*
|
||||
* @param boolean $exclude Defaults to true.
|
||||
* @param array $taxonomies Array of names for the taxonomies being processed.
|
||||
*/
|
||||
|
||||
$show_dates = Helper::get_settings( 'sitemap.html_sitemap_show_dates' );
|
||||
$output = [];
|
||||
|
||||
$output[] = '<div class="rank-math-html-sitemap">';
|
||||
foreach ( $post_types as $post_type ) {
|
||||
$cached = $this->get_cache( $post_type );
|
||||
if ( ! empty( $cached ) ) {
|
||||
$output[] = $cached;
|
||||
continue;
|
||||
}
|
||||
|
||||
$sitemap = $this->get_generator( 'posts' )->generate_sitemap( $post_type, $show_dates );
|
||||
$this->set_cache( $post_type, $sitemap );
|
||||
$output[] = $sitemap;
|
||||
}
|
||||
|
||||
if ( ! empty( $taxonomies ) ) {
|
||||
foreach ( $taxonomies as $taxonomy => $object ) {
|
||||
|
||||
$cached = $this->get_cache( $taxonomy );
|
||||
if ( ! empty( $cached ) ) {
|
||||
$output[] = $cached;
|
||||
continue;
|
||||
}
|
||||
|
||||
$hide_empty = ! Helper::get_settings( 'sitemap.tax_' . $taxonomy . '_include_empty' );
|
||||
$sitemap = $this->get_generator( 'terms' )->generate_sitemap(
|
||||
$taxonomy,
|
||||
$show_dates,
|
||||
[
|
||||
'hide_empty' => $hide_empty,
|
||||
'exclude' => wp_parse_id_list( Helper::get_settings( 'sitemap.exclude_terms' ) ),
|
||||
]
|
||||
);
|
||||
$this->set_cache( $taxonomy, $sitemap );
|
||||
$output[] = $sitemap;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->should_show_author_sitemap() ) {
|
||||
$cached = $this->get_cache( 'author' );
|
||||
if ( ! empty( $cached ) ) {
|
||||
$output[] = $cached;
|
||||
} else {
|
||||
$sitemap = $this->get_generator( 'authors' )->generate_sitemap();
|
||||
$this->set_cache( 'author', $sitemap );
|
||||
$output[] = $sitemap;
|
||||
}
|
||||
}
|
||||
|
||||
$output[] = '</div>';
|
||||
|
||||
return implode( '', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post types to be included in the HTML sitemap.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_post_types() {
|
||||
$post_types = [];
|
||||
foreach ( Helper::get_accessible_post_types() as $post_type ) {
|
||||
if ( ! Helper::get_settings( "sitemap.pt_{$post_type}_html_sitemap" ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$post_types[] = $post_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter: 'rank_math/sitemap/html_sitemap_post_types' - Allow changing the post types to be included in the HTML sitemap.
|
||||
*
|
||||
* @var array $post_types The post types to be included in the HTML sitemap.
|
||||
*/
|
||||
return apply_filters( 'rank_math/sitemap/html_sitemap_post_types', $post_types );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if author sitemap should be shown or not.
|
||||
*/
|
||||
private function should_show_author_sitemap() {
|
||||
$show = Helper::get_settings( 'sitemap.authors_html_sitemap' );
|
||||
if ( ! $show ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$disable_author_archives = Helper::get_settings( 'titles.disable_author_archives' );
|
||||
if ( $disable_author_archives ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$robots = Helper::get_settings( 'titles.author_robots' );
|
||||
if ( is_array( $robots ) && in_array( 'noindex', $robots, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get taxonomies to be included in the HTML sitemap.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_taxonomies() {
|
||||
$taxonomies = [];
|
||||
foreach ( Helper::get_accessible_taxonomies() as $taxonomy ) {
|
||||
if ( ! Helper::get_settings( "sitemap.tax_{$taxonomy->name}_html_sitemap" ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$taxonomies[ $taxonomy->name ] = $taxonomy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter: 'rank_math/sitemap/html_sitemap_taxonomies' - Allow changing the taxonomies to be included in the HTML sitemap.
|
||||
*
|
||||
* @var array $taxonomies The taxonomies to be included in the HTML sitemap.
|
||||
*/
|
||||
return apply_filters( 'rank_math/sitemap/html_sitemap_taxonomies', $taxonomies );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show sitemap on a page (after content).
|
||||
*
|
||||
* @param mixed $content The page content.
|
||||
*/
|
||||
public function show_on_page( $content ) {
|
||||
if ( ! is_page() ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
if ( ! is_main_query() || ! in_the_loop() ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
$post_id = get_the_ID();
|
||||
if ( (int) Helper::get_settings( 'sitemap.html_sitemap_page' ) !== $post_id ) {
|
||||
return $content;
|
||||
}
|
||||
|
||||
return $content . $this->get_output();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcode callback.
|
||||
*/
|
||||
public function shortcode() {
|
||||
return $this->get_output();
|
||||
}
|
||||
}
|
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
/**
|
||||
* The HTML sitemap generator for terms.
|
||||
*
|
||||
* @since 1.0.104
|
||||
* @package RankMath
|
||||
* @subpackage RankMath\Sitemap
|
||||
* @author Rank Math <support@rankmath.com>
|
||||
*/
|
||||
|
||||
namespace RankMath\Sitemap\Html;
|
||||
|
||||
use RankMath\Helper;
|
||||
use RankMath\Traits\Hooker;
|
||||
use RankMath\Admin\Database\Database;
|
||||
use RankMath\Sitemap\Sitemap as SitemapBase;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Terms class.
|
||||
*/
|
||||
class Terms {
|
||||
|
||||
use Hooker;
|
||||
|
||||
/**
|
||||
* Get all terms from a given taxonomy.
|
||||
*
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
* @param int $parent Parent term ID.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_terms( $taxonomy, $parent = 0 ) {
|
||||
$sort_map = [
|
||||
'published' => [
|
||||
'field' => 'term_id',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
'modified' => [
|
||||
'field' => 'term_id',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
'alphabetical' => [
|
||||
'field' => 'name',
|
||||
'order' => 'ASC',
|
||||
],
|
||||
'post_id' => [
|
||||
'field' => 'term_id',
|
||||
'order' => 'DESC',
|
||||
],
|
||||
];
|
||||
|
||||
$sort_setting = Helper::get_settings( 'sitemap.html_sitemap_sort' );
|
||||
$sort = ( isset( $sort_map[ $sort_setting ] ) ) ? $sort_map[ $sort_setting ] : $sort_map['published'];
|
||||
|
||||
/**
|
||||
* Filter: 'rank_math/sitemap/html_sitemap/sort_items' - Allow changing the sort order of the HTML sitemap.
|
||||
*
|
||||
* @var array $sort {
|
||||
* @type string $field The field to sort by.
|
||||
* @type string $order The sort order.
|
||||
* }
|
||||
* @var string $taxonomy The taxonomy name.
|
||||
* @var string $order The item type.
|
||||
*/
|
||||
$sort = $this->do_filter( 'sitemap/html_sitemap/sort_items', $sort, 'terms', $taxonomy );
|
||||
|
||||
$exclude = wp_parse_id_list( Helper::get_settings( 'sitemap.exclude_terms' ) );
|
||||
$terms_table = Database::table( 'terms' );
|
||||
$tt_table = Database::table( 'term_taxonomy' );
|
||||
|
||||
$query = $terms_table->where( 'taxonomy', $taxonomy )
|
||||
->select( [ $terms_table->table . '.term_id', 'name', 'slug', 'taxonomy' ] )
|
||||
->leftJoin( $tt_table->table, $terms_table->table . '.term_id', $tt_table->table . '.term_id' )
|
||||
->where( 'parent', $parent );
|
||||
|
||||
if ( ! empty( $exclude ) ) {
|
||||
$query->whereNotIn( $terms_table->table . '.term_id', $exclude );
|
||||
}
|
||||
|
||||
$terms = $query->orderBy( $sort['field'], $sort['order'] )->get();
|
||||
|
||||
return $this->get_indexable_terms( $terms, $taxonomy );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the HTML sitemap for a given taxonomy.
|
||||
*
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
* @param bool $show_dates Whether to show dates.
|
||||
* @param array $args Array with term query arguments.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generate_sitemap( $taxonomy, $show_dates, $args = [] ) {
|
||||
$terms = get_terms( $taxonomy, $args );
|
||||
$terms = $this->get_indexable_terms( $terms, $taxonomy );
|
||||
if ( empty( $terms ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$output[] = '<div class="rank-math-html-sitemap__section rank-math-html-sitemap__section--taxonomy rank-math-html-sitemap__section--' . $taxonomy . '">';
|
||||
$output[] = '<h2 class="rank-math-html-sitemap__title">' . esc_html( get_taxonomy( $taxonomy )->labels->name ) . '</h2>';
|
||||
$output[] = '<ul class="rank-math-html-sitemap__list">';
|
||||
$output[] = $this->generate_terms_list( $terms, $taxonomy );
|
||||
$output[] = '</ul>';
|
||||
$output[] = '</div>';
|
||||
|
||||
$output = implode( '', $output );
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the term list HTML.
|
||||
*
|
||||
* @param array $terms The terms to output.
|
||||
* @param object $taxonomy The taxonomy object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_terms_list( $terms, $taxonomy ) {
|
||||
if ( empty( $terms ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( is_taxonomy_hierarchical( $taxonomy ) ) {
|
||||
return $this->generate_terms_list_hierarchical( $terms, $taxonomy );
|
||||
}
|
||||
|
||||
return $this->generate_terms_list_flat( $terms, $taxonomy );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the term list HTML for non-hierarchical taxonomies.
|
||||
*
|
||||
* @param array $terms The terms to output.
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_terms_list_flat( $terms, $taxonomy ) {
|
||||
$output = [];
|
||||
foreach ( $terms as $term ) {
|
||||
$output[] = '<li class="rank-math-html-sitemap__item">'
|
||||
. '<a href="' . esc_url( $this->get_term_link( (int) $term->term_id, $taxonomy ) ) . '" class="rank-math-html-sitemap__link">'
|
||||
. esc_html( $this->get_term_title( $term, $taxonomy ) )
|
||||
. '</a>'
|
||||
. '</li>';
|
||||
}
|
||||
|
||||
return implode( '', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the term list HTML for hierarchical taxonomies. This will output the
|
||||
* terms in a nested list.
|
||||
*
|
||||
* @param array $terms The terms to output.
|
||||
* @param string $taxonomy The taxonomy name.
|
||||
* @param bool $remove_children Whether to remove terms that have a parent.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_terms_list_hierarchical( $terms, $taxonomy, $remove_children = true ) {
|
||||
$output = [];
|
||||
if ( $remove_children ) {
|
||||
// Remove initial with parents because they are queried below in $this->get_terms!
|
||||
$terms = $this->remove_with_parent( $terms );
|
||||
}
|
||||
foreach ( $terms as $term ) {
|
||||
$output[] = '<li class="rank-math-html-sitemap__item">'
|
||||
. '<a href="' . esc_url( $this->get_term_link( (int) $term->term_id, $taxonomy ) ) . '" class="rank-math-html-sitemap__link">'
|
||||
. esc_html( $this->get_term_title( $term, $taxonomy ) )
|
||||
. '</a>';
|
||||
|
||||
$children = $this->get_terms( $taxonomy, $term->term_id );
|
||||
|
||||
if ( ! empty( $children ) ) {
|
||||
$output[] = '<ul class="rank-math-html-sitemap__list">';
|
||||
$output[] = $this->generate_terms_list_hierarchical( $children, $taxonomy, false );
|
||||
$output[] = '</ul>';
|
||||
}
|
||||
$output[] = '</li>';
|
||||
}
|
||||
|
||||
return implode( '', $output );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the term link.
|
||||
*
|
||||
* @param int $term_id The term ID.
|
||||
* @param string $taxonomy The taxonomy name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_term_link( $term_id, $taxonomy ) {
|
||||
$term = get_term( $term_id, $taxonomy );
|
||||
if ( is_wp_error( $term ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return get_term_link( $term );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the term title.
|
||||
*
|
||||
* @param object $term The term data.
|
||||
* @param string $taxonomy The taxonomy name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_term_title( $term, $taxonomy ) {
|
||||
if ( Helper::get_settings( 'sitemap.html_sitemap_seo_titles' ) !== 'seo_titles' ) {
|
||||
return $term->name;
|
||||
}
|
||||
|
||||
// Custom SEO title.
|
||||
$meta = get_term_meta( $term->term_id, 'rank_math_title', true );
|
||||
if ( ! empty( $meta ) ) {
|
||||
return Helper::replace_vars( $meta, get_term( $term->term_id, $taxonomy ) );
|
||||
}
|
||||
|
||||
// Default SEO title from the global settings.
|
||||
$template = Helper::get_settings( "titles.tax_{$taxonomy}_title" );
|
||||
if ( ! empty( $template ) ) {
|
||||
return Helper::replace_vars( $template, get_term( $term->term_id, $taxonomy ) );
|
||||
}
|
||||
|
||||
// Fallback to term name.
|
||||
return $term->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes terms that have a parent from the list.
|
||||
*
|
||||
* @param array $terms The terms list.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function remove_with_parent( $terms ) {
|
||||
return array_filter(
|
||||
$terms,
|
||||
function ( $term ) {
|
||||
return ! $term->parent;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove terms that are not indexable.
|
||||
*
|
||||
* @param array $terms Array of terms.
|
||||
* @param string $taxonomy Taxonomy name that `$terms` are part of.
|
||||
* @return array
|
||||
*/
|
||||
private function get_indexable_terms( $terms, $taxonomy ) {
|
||||
return array_filter(
|
||||
$terms,
|
||||
function( $term ) use ( $taxonomy ) {
|
||||
return SitemapBase::is_object_indexable( get_term( $term->term_id, $taxonomy ), 'term' );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user