| Current Path : /home/x/b/o/xbodynamge/namtation/wp-content/ |
| Current File : /home/x/b/o/xbodynamge/namtation/wp-content/indexing.tar |
indexable-prepare-indexation-action.php 0000666 00000000452 15114513331 0014261 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
/**
* Action for preparing the indexing routine.
*
* @deprecated 15.3 - Use \Yoast\WP\SEO\Actions\Indexing\Indexing_Prepare_Action instead.
* @codeCoverageIgnore
*/
class Indexable_Prepare_Indexation_Action extends Indexing_Prepare_Action {
}
abstract-indexing-action.php 0000666 00000005472 15114624762 0012162 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
/**
* Base class of indexing actions.
*/
abstract class Abstract_Indexing_Action implements Indexation_Action_Interface, Limited_Indexing_Action_Interface {
/**
* The transient name.
*
* This is a trick to force derived classes to define a transient themselves.
*
* @var string
*/
const UNINDEXED_COUNT_TRANSIENT = null;
/**
* The transient cache key for limited counts.
*
* @var string
*/
const UNINDEXED_LIMITED_COUNT_TRANSIENT = self::UNINDEXED_COUNT_TRANSIENT . '_limited';
/**
* Builds a query for selecting the ID's of unindexed posts.
*
* @param bool $limit The maximum number of post IDs to return.
*
* @return string The prepared query string.
*/
abstract protected function get_select_query( $limit );
/**
* Builds a query for counting the number of unindexed posts.
*
* @return string The prepared query string.
*/
abstract protected function get_count_query();
/**
* Returns a limited number of unindexed posts.
*
* @param int $limit Limit the maximum number of unindexed posts that are counted.
*
* @return int The limited number of unindexed posts. 0 if the query fails.
*/
public function get_limited_unindexed_count( $limit ) {
$transient = \get_transient( static::UNINDEXED_LIMITED_COUNT_TRANSIENT );
if ( $transient !== false ) {
return (int) $transient;
}
\set_transient( static::UNINDEXED_LIMITED_COUNT_TRANSIENT, 0, ( \MINUTE_IN_SECONDS * 15 ) );
$query = $this->get_select_query( $limit );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Function get_count_query returns a prepared query.
$unindexed_object_ids = $this->wpdb->get_col( $query );
$count = (int) \count( $unindexed_object_ids );
\set_transient( static::UNINDEXED_LIMITED_COUNT_TRANSIENT, $count, ( \MINUTE_IN_SECONDS * 15 ) );
return $count;
}
/**
* Returns the total number of unindexed posts.
*
* @return int|false The total number of unindexed posts. False if the query fails.
*/
public function get_total_unindexed() {
$transient = \get_transient( static::UNINDEXED_COUNT_TRANSIENT );
if ( $transient !== false ) {
return (int) $transient;
}
// Store transient before doing the query so multiple requests won't make multiple queries.
// Only store this for 15 minutes to ensure that if the query doesn't complete a wrong count is not kept too long.
\set_transient( static::UNINDEXED_COUNT_TRANSIENT, 0, ( \MINUTE_IN_SECONDS * 15 ) );
$query = $this->get_count_query();
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Function get_count_query returns a prepared query.
$count = $this->wpdb->get_var( $query );
if ( \is_null( $count ) ) {
return false;
}
\set_transient( static::UNINDEXED_COUNT_TRANSIENT, $count, \DAY_IN_SECONDS );
return (int) $count;
}
}
abstract-link-indexing-action.php 0000666 00000005344 15114624762 0013113 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use wpdb;
use Yoast\WP\SEO\Builders\Indexable_Link_Builder;
use Yoast\WP\SEO\Models\SEO_Links;
use Yoast\WP\SEO\Repositories\Indexable_Repository;
/**
* Reindexing action for link indexables.
*/
abstract class Abstract_Link_Indexing_Action extends Abstract_Indexing_Action {
/**
* The link builder.
*
* @var Indexable_Link_Builder
*/
protected $link_builder;
/**
* The indexable repository.
*
* @var Indexable_Repository
*/
protected $repository;
/**
* The WordPress database instance.
*
* @var wpdb
*/
protected $wpdb;
/**
* Indexable_Post_Indexing_Action constructor
*
* @param Indexable_Link_Builder $link_builder The indexable link builder.
* @param Indexable_Repository $repository The indexable repository.
* @param wpdb $wpdb The WordPress database instance.
*/
public function __construct(
Indexable_Link_Builder $link_builder,
Indexable_Repository $repository,
wpdb $wpdb
) {
$this->link_builder = $link_builder;
$this->repository = $repository;
$this->wpdb = $wpdb;
}
/**
* Builds links for indexables which haven't had their links indexed yet.
*
* @return SEO_Links[] The created SEO links.
*/
public function index() {
$objects = $this->get_objects();
$indexables = [];
foreach ( $objects as $object ) {
$indexable = $this->repository->find_by_id_and_type( $object->id, $object->type );
$this->link_builder->build( $indexable, $object->content );
$indexable->save();
$indexables[] = $indexable;
}
if ( \count( $indexables ) > 0 ) {
\delete_transient( static::UNINDEXED_COUNT_TRANSIENT );
\delete_transient( static::UNINDEXED_LIMITED_COUNT_TRANSIENT );
}
return $indexables;
}
/**
* In the case of term-links and post-links we want to use the total unindexed count, because using
* the limited unindexed count actually leads to worse performance.
*
* @param int|bool $limit Unused.
*
* @return int The total number of unindexed links.
*/
public function get_limited_unindexed_count( $limit = false ) {
return $this->get_total_unindexed();
}
/**
* Returns the number of texts that will be indexed in a single link indexing pass.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_link_indexing_limit' - Allow filtering the number of texts indexed during each link indexing pass.
*
* @api int The maximum number of texts indexed.
*/
return \apply_filters( 'wpseo_link_indexing_limit', 5 );
}
/**
* Returns objects to be indexed.
*
* @return array Objects to be indexed, should be an array of objects with object_id, object_type and content.
*/
abstract protected function get_objects();
}
indexable-indexing-complete-action.php 0000666 00000001316 15114624762 0014111 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use Yoast\WP\SEO\Helpers\Indexable_Helper;
/**
* Indexing action to call when the indexable indexing process is completed.
*/
class Indexable_Indexing_Complete_Action {
/**
* The options helper.
*
* @var Indexable_Helper
*/
protected $indexable_helper;
/**
* Indexable_Indexing_Complete_Action constructor.
*
* @param Indexable_Helper $indexable_helper The indexable helper.
*/
public function __construct( Indexable_Helper $indexable_helper ) {
$this->indexable_helper = $indexable_helper;
}
/**
* Wraps up the indexing process.
*
* @return void
*/
public function complete() {
$this->indexable_helper->finish_indexing();
}
}
indexable-post-indexation-action.php 0000666 00000013264 15114624762 0013630 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use wpdb;
use Yoast\WP\Lib\Model;
use Yoast\WP\SEO\Helpers\Post_Helper;
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
use Yoast\WP\SEO\Models\Indexable;
use Yoast\WP\SEO\Repositories\Indexable_Repository;
use Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions;
/**
* Reindexing action for post indexables.
*/
class Indexable_Post_Indexation_Action extends Abstract_Indexing_Action {
/**
* The transient cache key.
*
* @var string
*/
const UNINDEXED_COUNT_TRANSIENT = 'wpseo_total_unindexed_posts';
/**
* The transient cache key for limited counts.
*
* @var string
*/
const UNINDEXED_LIMITED_COUNT_TRANSIENT = self::UNINDEXED_COUNT_TRANSIENT . '_limited';
/**
* The post type helper.
*
* @var Post_Type_Helper
*/
protected $post_type_helper;
/**
* The post helper.
*
* @var Post_Helper
*/
protected $post_helper;
/**
* The indexable repository.
*
* @var Indexable_Repository
*/
protected $repository;
/**
* The WordPress database instance.
*
* @var wpdb
*/
protected $wpdb;
/**
* The latest version of Post Indexables.
*
* @var int
*/
protected $version;
/**
* Indexable_Post_Indexing_Action constructor
*
* @param Post_Type_Helper $post_type_helper The post type helper.
* @param Indexable_Repository $repository The indexable repository.
* @param wpdb $wpdb The WordPress database instance.
* @param Indexable_Builder_Versions $builder_versions The latest versions for each Indexable type.
* @param Post_Helper $post_helper The post helper.
*/
public function __construct(
Post_Type_Helper $post_type_helper,
Indexable_Repository $repository,
wpdb $wpdb,
Indexable_Builder_Versions $builder_versions,
Post_Helper $post_helper
) {
$this->post_type_helper = $post_type_helper;
$this->repository = $repository;
$this->wpdb = $wpdb;
$this->version = $builder_versions->get_latest_version_for_type( 'post' );
$this->post_helper = $post_helper;
}
/**
* Creates indexables for unindexed posts.
*
* @return Indexable[] The created indexables.
*/
public function index() {
$query = $this->get_select_query( $this->get_limit() );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Function get_select_query returns a prepared query.
$post_ids = $this->wpdb->get_col( $query );
$indexables = [];
foreach ( $post_ids as $post_id ) {
$indexables[] = $this->repository->find_by_id_and_type( (int) $post_id, 'post' );
}
if ( \count( $indexables ) > 0 ) {
\delete_transient( static::UNINDEXED_COUNT_TRANSIENT );
\delete_transient( static::UNINDEXED_LIMITED_COUNT_TRANSIENT );
}
return $indexables;
}
/**
* Returns the number of posts that will be indexed in a single indexing pass.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_post_indexation_limit' - Allow filtering the amount of posts indexed during each indexing pass.
*
* @api int The maximum number of posts indexed.
*/
$limit = \apply_filters( 'wpseo_post_indexation_limit', 25 );
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = 25;
}
return $limit;
}
/**
* Builds a query for counting the number of unindexed posts.
*
* @return string The prepared query string.
*/
protected function get_count_query() {
$indexable_table = Model::get_table_name( 'Indexable' );
$post_types = $this->post_type_helper->get_indexable_post_types();
$excluded_post_statuses = $this->post_helper->get_excluded_post_statuses();
$replacements = \array_merge(
$post_types,
$excluded_post_statuses
);
$replacements[] = $this->version;
// Warning: If this query is changed, makes sure to update the query in get_select_query as well.
// @phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
return $this->wpdb->prepare(
"
SELECT COUNT(P.ID)
FROM {$this->wpdb->posts} AS P
WHERE P.post_type IN (" . \implode( ', ', \array_fill( 0, \count( $post_types ), '%s' ) ) . ')
AND P.post_status NOT IN (' . \implode( ', ', \array_fill( 0, \count( $excluded_post_statuses ), '%s' ) ) . ")
AND P.ID not in (
SELECT I.object_id from $indexable_table as I
WHERE I.object_type = 'post'
AND I.version = %d )",
$replacements
);
}
/**
* Builds a query for selecting the ID's of unindexed posts.
*
* @param bool $limit The maximum number of post IDs to return.
*
* @return string The prepared query string.
*/
protected function get_select_query( $limit = false ) {
$indexable_table = Model::get_table_name( 'Indexable' );
$post_types = $this->post_type_helper->get_indexable_post_types();
$excluded_post_statuses = $this->post_helper->get_excluded_post_statuses();
$replacements = \array_merge(
$post_types,
$excluded_post_statuses
);
$replacements[] = $this->version;
$limit_query = '';
if ( $limit ) {
$limit_query = 'LIMIT %d';
$replacements[] = $limit;
}
// Warning: If this query is changed, makes sure to update the query in get_count_query as well.
// @phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
return $this->wpdb->prepare(
"
SELECT P.ID
FROM {$this->wpdb->posts} AS P
WHERE P.post_type IN (" . \implode( ', ', \array_fill( 0, \count( $post_types ), '%s' ) ) . ')
AND P.post_status NOT IN (' . \implode( ', ', \array_fill( 0, \count( $excluded_post_statuses ), '%s' ) ) . ")
AND P.ID not in (
SELECT I.object_id from $indexable_table as I
WHERE I.object_type = 'post'
AND I.version = %d )
$limit_query",
$replacements
);
}
}
indexation-action-interface.php 0000666 00000001432 15114624762 0012644 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
/**
* Interface definition of reindexing action for indexables.
*/
interface Indexation_Action_Interface {
/**
* Returns the total number of unindexed objects.
*
* @return int The total number of unindexed objects.
*/
public function get_total_unindexed();
/**
* Indexes a number of objects.
*
* NOTE: ALWAYS use limits, this method is intended to be called multiple times over several requests.
*
* For indexing that requires JavaScript simply return the objects that should be indexed.
*
* @return array The reindexed objects.
*/
public function index();
/**
* Returns the number of objects that will be indexed in a single indexing pass.
*
* @return int The limit.
*/
public function get_limit();
}
indexing-prepare-action.php 0000666 00000001264 15114624762 0012010 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use Yoast\WP\SEO\Helpers\Indexing_Helper;
/**
* Class Indexing_Prepare_Action.
*
* Action for preparing the indexing routine.
*/
class Indexing_Prepare_Action {
/**
* The indexing helper.
*
* @var Indexing_Helper
*/
protected $indexing_helper;
/**
* Action for preparing the indexing routine.
*
* @param Indexing_Helper $indexing_helper The indexing helper.
*/
public function __construct(
Indexing_Helper $indexing_helper
) {
$this->indexing_helper = $indexing_helper;
}
/**
* Prepares the indexing routine.
*
* @return void
*/
public function prepare() {
$this->indexing_helper->prepare();
}
}
indexing-complete-action.php 0000666 00000001227 15114624762 0012161 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use Yoast\WP\SEO\Helpers\Indexing_Helper;
/**
* Indexing action to call when the indexing is completed.
*/
class Indexing_Complete_Action {
/**
* The indexing helper.
*
* @var Indexing_Helper
*/
protected $indexing_helper;
/**
* Indexing_Complete_Action constructor.
*
* @param Indexing_Helper $indexing_helper The indexing helper.
*/
public function __construct( Indexing_Helper $indexing_helper ) {
$this->indexing_helper = $indexing_helper;
}
/**
* Wraps up the indexing process.
*
* @return void
*/
public function complete() {
$this->indexing_helper->complete();
}
}
term-link-indexing-action.php 0000666 00000006424 15114624762 0012257 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use Yoast\WP\Lib\Model;
use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
/**
* Reindexing action for term link indexables.
*/
class Term_Link_Indexing_Action extends Abstract_Link_Indexing_Action {
/**
* The transient name.
*
* @var string
*/
const UNINDEXED_COUNT_TRANSIENT = 'wpseo_unindexed_term_link_count';
/**
* The transient cache key for limited counts.
*
* @var string
*/
const UNINDEXED_LIMITED_COUNT_TRANSIENT = self::UNINDEXED_COUNT_TRANSIENT . '_limited';
/**
* The post type helper.
*
* @var Taxonomy_Helper
*/
protected $taxonomy_helper;
/**
* Sets the required helper.
*
* @required
*
* @param Taxonomy_Helper $taxonomy_helper The taxonomy helper.
*
* @return void
*/
public function set_helper( Taxonomy_Helper $taxonomy_helper ) {
$this->taxonomy_helper = $taxonomy_helper;
}
/**
* Returns objects to be indexed.
*
* @return array Objects to be indexed.
*/
protected function get_objects() {
$query = $this->get_select_query( $this->get_limit() );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Function get_select_query returns a prepared query.
$terms = $this->wpdb->get_results( $query );
return \array_map(
static function ( $term ) {
return (object) [
'id' => (int) $term->term_id,
'type' => 'term',
'content' => $term->description,
];
},
$terms
);
}
/**
* Builds a query for counting the number of unindexed term links.
*
* @return string The prepared query string.
*/
protected function get_count_query() {
$public_taxonomies = $this->taxonomy_helper->get_indexable_taxonomies();
$placeholders = \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) );
$indexable_table = Model::get_table_name( 'Indexable' );
// Warning: If this query is changed, makes sure to update the query in get_select_query as well.
return $this->wpdb->prepare(
"
SELECT COUNT(T.term_id)
FROM {$this->wpdb->term_taxonomy} AS T
LEFT JOIN $indexable_table AS I
ON T.term_id = I.object_id
AND I.object_type = 'term'
AND I.link_count IS NOT NULL
WHERE I.object_id IS NULL
AND T.taxonomy IN ($placeholders)",
$public_taxonomies
);
}
/**
* Builds a query for selecting the ID's of unindexed term links.
*
* @param int|false $limit The maximum number of term link IDs to return.
*
* @return string The prepared query string.
*/
protected function get_select_query( $limit = false ) {
$public_taxonomies = $this->taxonomy_helper->get_indexable_taxonomies();
$indexable_table = Model::get_table_name( 'Indexable' );
$replacements = $public_taxonomies;
$limit_query = '';
if ( $limit ) {
$limit_query = 'LIMIT %d';
$replacements[] = $limit;
}
// Warning: If this query is changed, makes sure to update the query in get_count_query as well.
return $this->wpdb->prepare(
"
SELECT T.term_id, T.description
FROM {$this->wpdb->term_taxonomy} AS T
LEFT JOIN $indexable_table AS I
ON T.term_id = I.object_id
AND I.object_type = 'term'
AND I.link_count IS NOT NULL
WHERE I.object_id IS NULL
AND T.taxonomy IN (" . \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) ) . ")
$limit_query",
$replacements
);
}
}
indexable-general-indexation-action.php 0000666 00000007164 15114624762 0014262 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use Yoast\WP\SEO\Models\Indexable;
use Yoast\WP\SEO\Repositories\Indexable_Repository;
/**
* General reindexing action for indexables.
*/
class Indexable_General_Indexation_Action implements Indexation_Action_Interface, Limited_Indexing_Action_Interface {
/**
* The transient cache key.
*/
const UNINDEXED_COUNT_TRANSIENT = 'wpseo_total_unindexed_general_items';
/**
* Represents the indexables repository.
*
* @var Indexable_Repository
*/
protected $indexable_repository;
/**
* Indexable_General_Indexation_Action constructor.
*
* @param Indexable_Repository $indexable_repository The indexables repository.
*/
public function __construct( Indexable_Repository $indexable_repository ) {
$this->indexable_repository = $indexable_repository;
}
/**
* Returns the total number of unindexed objects.
*
* @return int The total number of unindexed objects.
*/
public function get_total_unindexed() {
$transient = \get_transient( static::UNINDEXED_COUNT_TRANSIENT );
if ( $transient !== false ) {
return (int) $transient;
}
$indexables_to_create = $this->query();
$result = \count( $indexables_to_create );
\set_transient( static::UNINDEXED_COUNT_TRANSIENT, $result, \DAY_IN_SECONDS );
return $result;
}
/**
* Returns a limited number of unindexed posts.
*
* @param int $limit Limit the maximum number of unindexed posts that are counted.
*
* @return int|false The limited number of unindexed posts. False if the query fails.
*/
public function get_limited_unindexed_count( $limit ) {
return $this->get_total_unindexed();
}
/**
* Creates indexables for unindexed system pages, the date archive, and the homepage.
*
* @return Indexable[] The created indexables.
*/
public function index() {
$indexables = [];
$indexables_to_create = $this->query();
if ( isset( $indexables_to_create['404'] ) ) {
$indexables[] = $this->indexable_repository->find_for_system_page( '404' );
}
if ( isset( $indexables_to_create['search'] ) ) {
$indexables[] = $this->indexable_repository->find_for_system_page( 'search-result' );
}
if ( isset( $indexables_to_create['date_archive'] ) ) {
$indexables[] = $this->indexable_repository->find_for_date_archive();
}
if ( isset( $indexables_to_create['home_page'] ) ) {
$indexables[] = $this->indexable_repository->find_for_home_page();
}
\set_transient( static::UNINDEXED_COUNT_TRANSIENT, 0, \DAY_IN_SECONDS );
return $indexables;
}
/**
* Returns the number of objects that will be indexed in a single indexing pass.
*
* @return int The limit.
*/
public function get_limit() {
// This matches the maximum number of indexables created by this action.
return 4;
}
/**
* Check which indexables already exist and return the values of the ones to create.
*
* @return array The indexable types to create.
*/
private function query() {
$indexables_to_create = [];
if ( ! $this->indexable_repository->find_for_system_page( '404', false ) ) {
$indexables_to_create['404'] = true;
}
if ( ! $this->indexable_repository->find_for_system_page( 'search-result', false ) ) {
$indexables_to_create['search'] = true;
}
if ( ! $this->indexable_repository->find_for_date_archive( false ) ) {
$indexables_to_create['date_archive'] = true;
}
$need_home_page_indexable = ( (int) \get_option( 'page_on_front' ) === 0 && \get_option( 'show_on_front' ) === 'posts' );
if ( $need_home_page_indexable && ! $this->indexable_repository->find_for_home_page( false ) ) {
$indexables_to_create['home_page'] = true;
}
return $indexables_to_create;
}
}
limited-indexing-action-interface.php 0000666 00000000763 15114624762 0013742 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
/**
* Interface definition of a reindexing action for indexables that have a limited unindexed count.
*/
interface Limited_Indexing_Action_Interface {
/**
* Returns a limited number of unindexed posts.
*
* @param int $limit Limit the maximum number of unindexed posts that are counted.
*
* @return int|false The limited number of unindexed posts. False if the query fails.
*/
public function get_limited_unindexed_count( $limit );
}
indexable-term-indexation-action.php 0000666 00000011723 15114624762 0013610 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use wpdb;
use Yoast\WP\Lib\Model;
use Yoast\WP\SEO\Helpers\Taxonomy_Helper;
use Yoast\WP\SEO\Models\Indexable;
use Yoast\WP\SEO\Repositories\Indexable_Repository;
use Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions;
/**
* Reindexing action for term indexables.
*/
class Indexable_Term_Indexation_Action extends Abstract_Indexing_Action {
/**
* The transient cache key.
*/
const UNINDEXED_COUNT_TRANSIENT = 'wpseo_total_unindexed_terms';
/**
* The transient cache key for limited counts.
*
* @var string
*/
const UNINDEXED_LIMITED_COUNT_TRANSIENT = self::UNINDEXED_COUNT_TRANSIENT . '_limited';
/**
* The post type helper.
*
* @var Taxonomy_Helper
*/
protected $taxonomy;
/**
* The indexable repository.
*
* @var Indexable_Repository
*/
protected $repository;
/**
* The WordPress database instance.
*
* @var wpdb
*/
protected $wpdb;
/**
* The latest version of the Indexable term builder
*
* @var int
*/
protected $version;
/**
* Indexable_Term_Indexation_Action constructor
*
* @param Taxonomy_Helper $taxonomy The taxonomy helper.
* @param Indexable_Repository $repository The indexable repository.
* @param wpdb $wpdb The WordPress database instance.
* @param Indexable_Builder_Versions $builder_versions The latest versions of all indexable builders.
*/
public function __construct(
Taxonomy_Helper $taxonomy,
Indexable_Repository $repository,
wpdb $wpdb,
Indexable_Builder_Versions $builder_versions
) {
$this->taxonomy = $taxonomy;
$this->repository = $repository;
$this->wpdb = $wpdb;
$this->version = $builder_versions->get_latest_version_for_type( 'term' );
}
/**
* Creates indexables for unindexed terms.
*
* @return Indexable[] The created indexables.
*/
public function index() {
$query = $this->get_select_query( $this->get_limit() );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Function get_select_query returns a prepared query.
$term_ids = $this->wpdb->get_col( $query );
$indexables = [];
foreach ( $term_ids as $term_id ) {
$indexables[] = $this->repository->find_by_id_and_type( (int) $term_id, 'term' );
}
if ( \count( $indexables ) > 0 ) {
\delete_transient( static::UNINDEXED_COUNT_TRANSIENT );
\delete_transient( static::UNINDEXED_LIMITED_COUNT_TRANSIENT );
}
return $indexables;
}
/**
* Returns the number of terms that will be indexed in a single indexing pass.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_term_indexation_limit' - Allow filtering the number of terms indexed during each indexing pass.
*
* @api int The maximum number of terms indexed.
*/
$limit = \apply_filters( 'wpseo_term_indexation_limit', 25 );
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = 25;
}
return $limit;
}
/**
* Builds a query for counting the number of unindexed terms.
*
* @return string The prepared query string.
*/
protected function get_count_query() {
$indexable_table = Model::get_table_name( 'Indexable' );
$taxonomy_table = $this->wpdb->term_taxonomy;
$public_taxonomies = $this->taxonomy->get_indexable_taxonomies();
$taxonomies_placeholders = \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) );
$replacements = [ $this->version ];
\array_push( $replacements, ...$public_taxonomies );
// Warning: If this query is changed, makes sure to update the query in get_count_query as well.
return $this->wpdb->prepare(
"
SELECT COUNT(term_id)
FROM {$taxonomy_table} AS T
LEFT JOIN $indexable_table AS I
ON T.term_id = I.object_id
AND I.object_type = 'term'
AND I.version = %d
WHERE I.object_id IS NULL
AND taxonomy IN ($taxonomies_placeholders)",
$replacements
);
}
/**
* Builds a query for selecting the ID's of unindexed terms.
*
* @param bool $limit The maximum number of term IDs to return.
*
* @return string The prepared query string.
*/
protected function get_select_query( $limit = false ) {
$indexable_table = Model::get_table_name( 'Indexable' );
$taxonomy_table = $this->wpdb->term_taxonomy;
$public_taxonomies = $this->taxonomy->get_indexable_taxonomies();
$placeholders = \implode( ', ', \array_fill( 0, \count( $public_taxonomies ), '%s' ) );
$replacements = [ $this->version ];
\array_push( $replacements, ...$public_taxonomies );
$limit_query = '';
if ( $limit ) {
$limit_query = 'LIMIT %d';
$replacements[] = $limit;
}
// Warning: If this query is changed, makes sure to update the query in get_count_query as well.
return $this->wpdb->prepare(
"
SELECT term_id
FROM {$taxonomy_table} AS T
LEFT JOIN $indexable_table AS I
ON T.term_id = I.object_id
AND I.object_type = 'term'
AND I.version = %d
WHERE I.object_id IS NULL
AND taxonomy IN ($placeholders)
$limit_query",
$replacements
);
}
}
indexable-post-type-archive-indexation-action.php 0000666 00000013462 15114624762 0016226 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use Yoast\WP\SEO\Builders\Indexable_Builder;
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
use Yoast\WP\SEO\Models\Indexable;
use Yoast\WP\SEO\Repositories\Indexable_Repository;
use Yoast\WP\SEO\Values\Indexables\Indexable_Builder_Versions;
/**
* Reindexing action for post type archive indexables.
*
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
*/
class Indexable_Post_Type_Archive_Indexation_Action implements Indexation_Action_Interface, Limited_Indexing_Action_Interface {
/**
* The transient cache key.
*/
const UNINDEXED_COUNT_TRANSIENT = 'wpseo_total_unindexed_post_type_archives';
/**
* The post type helper.
*
* @var Post_Type_Helper
*/
protected $post_type;
/**
* The indexable repository.
*
* @var Indexable_Repository
*/
protected $repository;
/**
* The indexable builder.
*
* @var Indexable_Builder
*/
protected $builder;
/**
* The current version of the post type archive indexable builder.
*
* @var int
*/
protected $version;
/**
* Indexation_Post_Type_Archive_Action constructor.
*
* @param Indexable_Repository $repository The indexable repository.
* @param Indexable_Builder $builder The indexable builder.
* @param Post_Type_Helper $post_type The post type helper.
* @param Indexable_Builder_Versions $versions The current versions of all indexable builders.
*/
public function __construct(
Indexable_Repository $repository,
Indexable_Builder $builder,
Post_Type_Helper $post_type,
Indexable_Builder_Versions $versions
) {
$this->repository = $repository;
$this->builder = $builder;
$this->post_type = $post_type;
$this->version = $versions->get_latest_version_for_type( 'post-type-archive' );
}
/**
* Returns the total number of unindexed post type archives.
*
* @param int $limit Limit the number of counted objects.
*
* @return int The total number of unindexed post type archives.
*/
public function get_total_unindexed( $limit = false ) {
$transient = \get_transient( static::UNINDEXED_COUNT_TRANSIENT );
if ( $transient !== false ) {
return (int) $transient;
}
\set_transient( static::UNINDEXED_COUNT_TRANSIENT, 0, \DAY_IN_SECONDS );
$result = \count( $this->get_unindexed_post_type_archives( $limit ) );
\set_transient( static::UNINDEXED_COUNT_TRANSIENT, $result, \DAY_IN_SECONDS );
return $result;
}
/**
* Creates indexables for post type archives.
*
* @return Indexable[] The created indexables.
*/
public function index() {
$unindexed_post_type_archives = $this->get_unindexed_post_type_archives( $this->get_limit() );
$indexables = [];
foreach ( $unindexed_post_type_archives as $post_type_archive ) {
$indexables[] = $this->builder->build_for_post_type_archive( $post_type_archive );
}
if ( \count( $indexables ) > 0 ) {
\delete_transient( static::UNINDEXED_COUNT_TRANSIENT );
}
return $indexables;
}
/**
* Returns the number of post type archives that will be indexed in a single indexing pass.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_post_type_archive_indexation_limit' - Allow filtering the number of posts indexed during each indexing pass.
*
* @api int The maximum number of posts indexed.
*/
$limit = \apply_filters( 'wpseo_post_type_archive_indexation_limit', 25 );
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = 25;
}
return $limit;
}
/**
* Retrieves the list of post types for which no indexable for its archive page has been made yet.
*
* @param int|false $limit Limit the number of retrieved indexables to this number.
*
* @return array The list of post types for which no indexable for its archive page has been made yet.
*/
protected function get_unindexed_post_type_archives( $limit = false ) {
$post_types_with_archive_pages = $this->get_post_types_with_archive_pages();
$indexed_post_types = $this->get_indexed_post_type_archives();
$unindexed_post_types = \array_diff( $post_types_with_archive_pages, $indexed_post_types );
if ( $limit ) {
return \array_slice( $unindexed_post_types, 0, $limit );
}
return $unindexed_post_types;
}
/**
* Returns the names of all the post types that have archive pages.
*
* @return array The list of names of all post types that have archive pages.
*/
protected function get_post_types_with_archive_pages() {
// We only want to index archive pages of public post types that have them.
$public_post_types = $this->post_type->get_public_post_types( 'object' );
$post_types_with_archive = \array_filter( $public_post_types, [ $this->post_type, 'has_archive' ] );
// We only need the post type names, not the objects.
$post_types = [];
foreach ( $post_types_with_archive as $post_type_with_archive ) {
$post_types[] = $post_type_with_archive->name;
}
return $post_types;
}
/**
* Retrieves the list of post type names for which an archive indexable exists.
*
* @return array The list of names of post types with unindexed archive pages.
*/
protected function get_indexed_post_type_archives() {
$results = $this->repository->query()
->select( 'object_sub_type' )
->where( 'object_type', 'post-type-archive' )
->where_equal( 'version', $this->version )
->find_array();
if ( $results === false ) {
return [];
}
$callback = static function( $result ) {
return $result['object_sub_type'];
};
return \array_map( $callback, $results );
}
/**
* Returns a limited number of unindexed posts.
*
* @param int $limit Limit the maximum number of unindexed posts that are counted.
*
* @return int|false The limited number of unindexed posts. False if the query fails.
*/
public function get_limited_unindexed_count( $limit ) {
return $this->get_total_unindexed( $limit );
}
}
post-link-indexing-action.php 0000666 00000007514 15114624762 0012276 0 ustar 00 <?php
namespace Yoast\WP\SEO\Actions\Indexing;
use Yoast\WP\Lib\Model;
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
/**
* Reindexing action for post link indexables.
*/
class Post_Link_Indexing_Action extends Abstract_Link_Indexing_Action {
/**
* The transient name.
*
* @var string
*/
const UNINDEXED_COUNT_TRANSIENT = 'wpseo_unindexed_post_link_count';
/**
* The transient cache key for limited counts.
*
* @var string
*/
const UNINDEXED_LIMITED_COUNT_TRANSIENT = self::UNINDEXED_COUNT_TRANSIENT . '_limited';
/**
* The post type helper.
*
* @var Post_Type_Helper
*/
protected $post_type_helper;
/**
* Sets the required helper.
*
* @required
*
* @param Post_Type_Helper $post_type_helper The post type helper.
*
* @return void
*/
public function set_helper( Post_Type_Helper $post_type_helper ) {
$this->post_type_helper = $post_type_helper;
}
/**
* Returns objects to be indexed.
*
* @return array Objects to be indexed.
*/
protected function get_objects() {
$query = $this->get_select_query( $this->get_limit() );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Function get_select_query returns a prepared query.
$posts = $this->wpdb->get_results( $query );
return \array_map(
static function ( $post ) {
return (object) [
'id' => (int) $post->ID,
'type' => 'post',
'content' => $post->post_content,
];
},
$posts
);
}
/**
* Builds a query for counting the number of unindexed post links.
*
* @return string The prepared query string.
*/
protected function get_count_query() {
$public_post_types = $this->post_type_helper->get_indexable_post_types();
$indexable_table = Model::get_table_name( 'Indexable' );
$links_table = Model::get_table_name( 'SEO_Links' );
// Warning: If this query is changed, makes sure to update the query in get_select_query as well.
return $this->wpdb->prepare(
"SELECT COUNT(P.ID)
FROM {$this->wpdb->posts} AS P
LEFT JOIN $indexable_table AS I
ON P.ID = I.object_id
AND I.link_count IS NOT NULL
AND I.object_type = 'post'
LEFT JOIN $links_table AS L
ON L.post_id = P.ID
AND L.target_indexable_id IS NULL
AND L.type = 'internal'
AND L.target_post_id IS NOT NULL
AND L.target_post_id != 0
WHERE ( I.object_id IS NULL OR L.post_id IS NOT NULL )
AND P.post_status = 'publish'
AND P.post_type IN (" . \implode( ', ', \array_fill( 0, \count( $public_post_types ), '%s' ) ) . ')',
$public_post_types
);
}
/**
* Builds a query for selecting the ID's of unindexed post links.
*
* @param int|false $limit The maximum number of post link IDs to return.
*
* @return string The prepared query string.
*/
protected function get_select_query( $limit = false ) {
$public_post_types = $this->post_type_helper->get_indexable_post_types();
$indexable_table = Model::get_table_name( 'Indexable' );
$links_table = Model::get_table_name( 'SEO_Links' );
$replacements = $public_post_types;
$limit_query = '';
if ( $limit ) {
$limit_query = 'LIMIT %d';
$replacements[] = $limit;
}
// Warning: If this query is changed, makes sure to update the query in get_count_query as well.
return $this->wpdb->prepare(
"
SELECT P.ID, P.post_content
FROM {$this->wpdb->posts} AS P
LEFT JOIN $indexable_table AS I
ON P.ID = I.object_id
AND I.link_count IS NOT NULL
AND I.object_type = 'post'
LEFT JOIN $links_table AS L
ON L.post_id = P.ID
AND L.target_indexable_id IS NULL
AND L.type = 'internal'
AND L.target_post_id IS NOT NULL
AND L.target_post_id != 0
WHERE ( I.object_id IS NULL OR L.post_id IS NOT NULL )
AND P.post_status = 'publish'
AND P.post_type IN (" . \implode( ', ', \array_fill( 0, \count( $public_post_types ), '%s' ) ) . ")
$limit_query",
$replacements
);
}
}