You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
7.3 KiB
PHP
313 lines
7.3 KiB
PHP
<?php
|
|
/**
|
|
* The sitemap provider for author archives.
|
|
*
|
|
* @since 0.9.0
|
|
* @package RankMath
|
|
* @subpackage RankMath\Sitemap
|
|
* @author Rank Math <support@rankmath.com>
|
|
*
|
|
* @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.
|
|
*/
|
|
|
|
namespace RankMath\Sitemap\Providers;
|
|
|
|
use DateTime;
|
|
use DateTimeZone;
|
|
use RankMath\Helper;
|
|
use RankMath\Sitemap\Router;
|
|
use RankMath\Sitemap\Sitemap;
|
|
use RankMath\Traits\Hooker;
|
|
|
|
defined( 'ABSPATH' ) || exit;
|
|
|
|
/**
|
|
* Author class.
|
|
*/
|
|
class Author implements Provider {
|
|
|
|
use Hooker;
|
|
|
|
/**
|
|
* Holds the Sitemap slug.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $sitemap_slug = null;
|
|
|
|
|
|
/**
|
|
* The constructor.
|
|
*/
|
|
public function __construct() {
|
|
$this->sitemap_slug = Router::get_sitemap_slug( 'author' );
|
|
|
|
$this->filter( 'rank_math/sitemap/author/query', 'exclude_users', 5 );
|
|
$this->filter( 'rank_math/sitemap/author/query', 'exclude_roles', 5 );
|
|
$this->filter( 'rank_math/sitemap/author/query', 'exclude_post_types', 5 );
|
|
}
|
|
|
|
/**
|
|
* Check if provider supports given item type.
|
|
*
|
|
* @param string $type Type string to check for.
|
|
* @return boolean
|
|
*/
|
|
public function handles_type( $type ) {
|
|
return $this->sitemap_slug === $type && Helper::get_settings( 'sitemap.authors_sitemap' );
|
|
}
|
|
|
|
/**
|
|
* Get set of sitemaps index link data.
|
|
*
|
|
* @param int $max_entries Entries per sitemap.
|
|
* @return array
|
|
*/
|
|
public function get_index_links( $max_entries ) {
|
|
if ( ! Helper::get_settings( 'sitemap.authors_sitemap' ) ) {
|
|
return [];
|
|
}
|
|
|
|
$users = $this->get_index_users();
|
|
if ( empty( $users ) ) {
|
|
return [];
|
|
}
|
|
|
|
$page = 1;
|
|
$index = [];
|
|
$user_pages = array_chunk( $users, $max_entries );
|
|
|
|
if ( 1 === count( $user_pages ) ) {
|
|
$page = '';
|
|
}
|
|
|
|
foreach ( $user_pages as $user_page ) {
|
|
$user = array_shift( $user_page ); // Time descending, first user on page is most recently updated.
|
|
$item = $this->do_filter(
|
|
'sitemap/index/entry',
|
|
[
|
|
'loc' => Router::get_base_url( $this->sitemap_slug . '-sitemap' . $page . '.xml' ),
|
|
'lastmod' => '@' . $user->last_update,
|
|
],
|
|
'author',
|
|
$user
|
|
);
|
|
|
|
if ( ! $item ) {
|
|
continue;
|
|
}
|
|
|
|
$index[] = $item;
|
|
|
|
$page++;
|
|
}
|
|
|
|
return $index;
|
|
}
|
|
|
|
/**
|
|
* Get set of sitemap link data.
|
|
*
|
|
* @param string $type Sitemap type.
|
|
* @param int $max_entries Entries per sitemap.
|
|
* @param int $current_page Current page of the sitemap.
|
|
* @return array
|
|
*/
|
|
public function get_sitemap_links( $type, $max_entries, $current_page ) {
|
|
$links = [];
|
|
|
|
if ( $current_page < 1 ) {
|
|
$current_page = 1;
|
|
}
|
|
|
|
$users = $this->get_users(
|
|
[
|
|
'offset' => ( $current_page - 1 ) * $max_entries,
|
|
'number' => $max_entries,
|
|
]
|
|
);
|
|
|
|
if ( empty( $users ) ) {
|
|
return $links;
|
|
}
|
|
|
|
Sitemap::maybe_redirect( count( $users ), $max_entries );
|
|
foreach ( $users as $user ) {
|
|
$url = $this->get_sitemap_url( $user );
|
|
if ( ! empty( $url ) ) {
|
|
$links[] = $url;
|
|
}
|
|
}
|
|
|
|
return $links;
|
|
}
|
|
|
|
/**
|
|
* Get sitemap urlset.
|
|
*
|
|
* @param WP_User $user User instance.
|
|
*
|
|
* @return bool|array
|
|
*/
|
|
private function get_sitemap_url( $user ) {
|
|
$author_link = get_author_posts_url( $user->ID );
|
|
if ( empty( $author_link ) ) {
|
|
return false;
|
|
}
|
|
|
|
$mod = isset( $user->last_update ) ? $user->last_update : strtotime( $user->user_registered );
|
|
|
|
$date = new DateTime();
|
|
$date->setTimestamp( $mod );
|
|
$date->setTimezone( new DateTimeZone( 'UTC' ) );
|
|
|
|
$url = [
|
|
'loc' => $author_link,
|
|
'mod' => $date->format( DATE_W3C ),
|
|
];
|
|
|
|
/** This filter is documented at includes/modules/sitemap/providers/class-post-type.php */
|
|
return $this->do_filter( 'sitemap/entry', $url, 'user', $user );
|
|
}
|
|
|
|
/**
|
|
* Retrieve users, taking account of all necessary exclusions.
|
|
*
|
|
* @param array $args Arguments to add.
|
|
* @return array
|
|
*/
|
|
public function get_users( $args = [] ) {
|
|
$defaults = [
|
|
'orderby' => 'meta_value_num',
|
|
'order' => 'DESC',
|
|
'meta_query' => [
|
|
'relation' => 'AND',
|
|
[
|
|
'relation' => 'OR',
|
|
[
|
|
'key' => 'last_update',
|
|
],
|
|
[
|
|
'key' => 'last_update',
|
|
'compare' => 'NOT EXISTS',
|
|
],
|
|
],
|
|
[
|
|
'relation' => 'OR',
|
|
[
|
|
'key' => 'rank_math_robots',
|
|
'value' => 'noindex',
|
|
'compare' => 'NOT LIKE',
|
|
],
|
|
[
|
|
'key' => 'rank_math_robots',
|
|
'compare' => 'NOT EXISTS',
|
|
],
|
|
],
|
|
],
|
|
];
|
|
|
|
$args = $this->do_filter( 'sitemap/author/query', wp_parse_args( $args, $defaults ) );
|
|
return get_users( $args );
|
|
}
|
|
|
|
/**
|
|
* Exclude users.
|
|
*
|
|
* @param array $args Array of user query arguments.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function exclude_users( $args ) {
|
|
$exclude = Helper::get_settings( 'sitemap.exclude_users' );
|
|
if ( ! empty( $exclude ) ) {
|
|
$args['exclude'] = wp_parse_id_list( $exclude );
|
|
}
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* Exclude roles.
|
|
*
|
|
* @param array $args Array of user query arguments.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function exclude_roles( $args ) {
|
|
$exclude_roles = Helper::get_settings( 'sitemap.exclude_roles' );
|
|
if ( ! empty( $exclude_roles ) ) {
|
|
$args['role__not_in'] = $exclude_roles;
|
|
}
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* Exclude post types.
|
|
*
|
|
* @param array $args Array of user query arguments.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function exclude_post_types( $args ) {
|
|
// Exclude post types.
|
|
$public_post_types = get_post_types( [ 'public' => true ] );
|
|
|
|
// We're not supporting sitemaps for author pages for attachments.
|
|
unset( $public_post_types['attachment'] );
|
|
|
|
$args['has_published_posts'] = array_keys( $public_post_types );
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* Get all users according to author sitemap settings.
|
|
*
|
|
* @return array
|
|
*/
|
|
private function get_index_users() {
|
|
global $wpdb;
|
|
$exclude_users = Helper::get_settings( 'sitemap.exclude_users' );
|
|
$exclude_roles = Helper::get_settings( 'sitemap.exclude_roles' );
|
|
$exclude_users_query = ! $exclude_users ? '' : 'AND post_author NOT IN ( ' . esc_sql( $exclude_users ) . ' )';
|
|
$exclude_roles_query = '';
|
|
$meta_query = "(
|
|
( um.meta_key = 'rank_math_robots' AND um.meta_value NOT LIKE '%noindex%' )
|
|
OR um.user_id IS NULL
|
|
)
|
|
AND ( umt1.meta_key = 'last_update' OR umt1.user_id IS NULL )
|
|
";
|
|
if ( $exclude_roles ) {
|
|
$exclude_roles_query = "AND ( umt.meta_key ='wp_capabilities' AND ( ";
|
|
foreach ( $exclude_roles as $key => $role ) {
|
|
$exclude_roles_query .= 0 === $key ? " umt.meta_value NOT LIKE '%" . esc_sql( $role ) . "%'" : " AND umt.meta_value NOT LIKE '%" . esc_sql( $role ) . "%'";
|
|
}
|
|
|
|
$exclude_roles_query .= ' ) )';
|
|
}
|
|
|
|
$meta_query .= $exclude_roles_query;
|
|
|
|
$sql = "
|
|
SELECT u.ID, umt1.meta_value as last_update
|
|
FROM {$wpdb->users} as u
|
|
LEFT JOIN {$wpdb->usermeta} AS um ON ( u.ID = um.user_id AND um.meta_key = 'rank_math_robots' )
|
|
LEFT JOIN {$wpdb->usermeta} AS umt ON ( u.ID = umt.user_id AND umt.meta_key = 'wp_capabilities' )
|
|
LEFT JOIN {$wpdb->usermeta} AS umt1 ON ( u.ID = umt1.user_id AND umt1.meta_key = 'last_update' )
|
|
WHERE ( {$meta_query} )
|
|
AND u.ID IN (
|
|
SELECT post_author
|
|
FROM {$wpdb->posts} as p
|
|
WHERE p.post_status = 'publish' AND p.post_password = ''
|
|
{$exclude_users_query}
|
|
)
|
|
ORDER BY umt1.meta_value DESC
|
|
";
|
|
|
|
return $wpdb->get_results( $sql ); // phpcs:ignore
|
|
}
|
|
}
|