khaihihi
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* Post Builder for the indexables.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Builders
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Builders;
|
||||
|
||||
use Yoast\WP\SEO\Models\Indexable;
|
||||
|
||||
/**
|
||||
* Formats the term meta to indexable format.
|
||||
*/
|
||||
class Indexable_Author_Builder {
|
||||
|
||||
/**
|
||||
* Formats the data.
|
||||
*
|
||||
* @param int $user_id The user to retrieve the indexable for.
|
||||
* @param \Yoast\WP\SEO\Models\Indexable $indexable The indexable to format.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\Indexable The extended indexable.
|
||||
*/
|
||||
public function build( $user_id, Indexable $indexable ) {
|
||||
$meta_data = $this->get_meta_data( $user_id );
|
||||
|
||||
$indexable->permalink = \get_author_posts_url( $user_id );
|
||||
$indexable->title = $meta_data['wpseo_title'];
|
||||
$indexable->description = $meta_data['wpseo_metadesc'];
|
||||
$indexable->is_cornerstone = false;
|
||||
$indexable->is_robots_noindex = ( $meta_data['wpseo_noindex_author'] === 'on' );
|
||||
$indexable->is_robots_nofollow = null;
|
||||
$indexable->is_robots_noarchive = null;
|
||||
$indexable->is_robots_noimageindex = null;
|
||||
$indexable->is_robots_nosnippet = null;
|
||||
|
||||
return $indexable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the meta data for this indexable.
|
||||
*
|
||||
* @param int $user_id The user to retrieve the meta data for.
|
||||
*
|
||||
* @return array List of meta entries.
|
||||
*/
|
||||
protected function get_meta_data( $user_id ) {
|
||||
$keys = [
|
||||
'wpseo_title',
|
||||
'wpseo_metadesc',
|
||||
'wpseo_noindex_author',
|
||||
];
|
||||
|
||||
$output = [];
|
||||
foreach ( $keys as $key ) {
|
||||
$output[ $key ] = $this->get_author_meta( $user_id, $key );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the author meta.
|
||||
*
|
||||
* @param int $user_id The user to retrieve the indexable for.
|
||||
* @param string $key The meta entry to retrieve.
|
||||
*
|
||||
* @return string The value of the meta field.
|
||||
*/
|
||||
protected function get_author_meta( $user_id, $key ) {
|
||||
$value = \get_the_author_meta( $key, $user_id );
|
||||
if ( \is_string( $value ) && $value === '' ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* Post Builder for the indexables.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Builders
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Builders;
|
||||
|
||||
use Exception;
|
||||
use Yoast\WP\SEO\Models\Indexable;
|
||||
use Yoast\WP\SEO\Repositories\SEO_Meta_Repository;
|
||||
|
||||
/**
|
||||
* Formats the post meta to indexable format.
|
||||
*/
|
||||
class Indexable_Post_Builder {
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Repositories\SEO_Meta_Repository
|
||||
*/
|
||||
protected $seo_meta_repository;
|
||||
|
||||
/**
|
||||
* Indexable_Post_Builder constructor.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Repositories\SEO_Meta_Repository $seo_meta_repository The SEO Meta repository.
|
||||
*/
|
||||
public function __construct( SEO_Meta_Repository $seo_meta_repository ) {
|
||||
$this->seo_meta_repository = $seo_meta_repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the data.
|
||||
*
|
||||
* @param int $post_id The post ID to use.
|
||||
* @param \Yoast\WP\SEO\Models\Indexable $indexable The indexable to format.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\Indexable The extended indexable.
|
||||
*/
|
||||
public function build( $post_id, Indexable $indexable ) {
|
||||
$indexable->permalink = \get_permalink( $post_id );
|
||||
$indexable->object_sub_type = \get_post_type( $post_id );
|
||||
|
||||
$indexable->primary_focus_keyword_score = $this->get_keyword_score(
|
||||
$this->get_meta_value( $post_id, 'focuskw' ),
|
||||
(int) $this->get_meta_value( $post_id, 'linkdex' )
|
||||
);
|
||||
|
||||
$indexable->readability_score = (int) $this->get_meta_value( $post_id, 'content_score' );
|
||||
|
||||
$indexable->is_cornerstone = ( $this->get_meta_value( $post_id, 'is_cornerstone' ) === '1' );
|
||||
$indexable->is_robots_noindex = $this->get_robots_noindex(
|
||||
$this->get_meta_value( $post_id, 'meta-robots-noindex' )
|
||||
);
|
||||
|
||||
// Set additional meta-robots values.
|
||||
$indexable->is_robots_nofollow = ( $this->get_meta_value( $post_id, 'meta-robots-nofollow' ) === '1' );
|
||||
$noindex_advanced = $this->get_meta_value( $post_id, 'meta-robots-adv' );
|
||||
$meta_robots = \explode( ',', $noindex_advanced );
|
||||
foreach ( $this->get_robots_options() as $meta_robots_option ) {
|
||||
$indexable->{ 'is_robots_' . $meta_robots_option } = \in_array( $meta_robots_option, $meta_robots, true ) ? 1 : null;
|
||||
}
|
||||
|
||||
foreach ( $this->get_indexable_lookup() as $meta_key => $indexable_key ) {
|
||||
$indexable->{ $indexable_key } = $this->get_meta_value( $post_id, $meta_key );
|
||||
}
|
||||
|
||||
$indexable = $this->set_link_count( $post_id, $indexable );
|
||||
|
||||
return $indexable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the meta robots noindex value to the indexable value.
|
||||
*
|
||||
* @param int $value Meta value to convert.
|
||||
*
|
||||
* @return bool|null True for noindex, false for index, null for default of parent/type.
|
||||
*/
|
||||
protected function get_robots_noindex( $value ) {
|
||||
$value = (int) $value;
|
||||
|
||||
switch ( $value ) {
|
||||
case 1:
|
||||
return true;
|
||||
case 2:
|
||||
return false;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the robot options to search for.
|
||||
*
|
||||
* @return array List of robots values.
|
||||
*/
|
||||
protected function get_robots_options() {
|
||||
return [ 'noimageindex', 'noarchive', 'nosnippet' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the focus keyword score.
|
||||
*
|
||||
* @param string $keyword The focus keyword that is set.
|
||||
* @param int $score The score saved on the meta data.
|
||||
*
|
||||
* @return null|int Score to use.
|
||||
*/
|
||||
protected function get_keyword_score( $keyword, $score ) {
|
||||
if ( empty( $keyword ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the lookup table.
|
||||
*
|
||||
* @return array Lookup table for the indexable fields.
|
||||
*/
|
||||
protected function get_indexable_lookup() {
|
||||
return [
|
||||
'focuskw' => 'primary_focus_keyword',
|
||||
'canonical' => 'canonical',
|
||||
'title' => 'title',
|
||||
'metadesc' => 'description',
|
||||
'bctitle' => 'breadcrumb_title',
|
||||
'opengraph-title' => 'og_title',
|
||||
'opengraph-image' => 'og_image',
|
||||
'opengraph-description' => 'og_description',
|
||||
'twitter-title' => 'twitter_title',
|
||||
'twitter-image' => 'twitter_image',
|
||||
'twitter-description' => 'twitter_description',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the link count from existing data.
|
||||
*
|
||||
* @param int $post_id The post ID to use.
|
||||
* @param \Yoast\WP\SEO\Models\Indexable $indexable The indexable to extend.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\Indexable The extended indexable.
|
||||
*/
|
||||
protected function set_link_count( $post_id, Indexable $indexable ) {
|
||||
try {
|
||||
$seo_meta = $this->seo_meta_repository->find_by_post_id( $post_id );
|
||||
|
||||
if ( $seo_meta ) {
|
||||
$indexable->link_count = $seo_meta->internal_link_count;
|
||||
$indexable->incoming_link_count = $seo_meta->incoming_link_count;
|
||||
}
|
||||
// @codingStandardsIgnoreLine Generic.CodeAnalysis.EmptyStatement.DetectedCATCH -- There is nothing to do.
|
||||
} catch ( Exception $exception ) {
|
||||
// Do nothing...
|
||||
}
|
||||
|
||||
return $indexable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current value for the meta field.
|
||||
*
|
||||
* @param int $post_id The post ID to use.
|
||||
* @param string $meta_key Meta key to fetch.
|
||||
*
|
||||
* @return mixed The value of the indexable entry to use.
|
||||
*/
|
||||
protected function get_meta_value( $post_id, $meta_key ) {
|
||||
$value = \WPSEO_Meta::get_value( $meta_key, $post_id );
|
||||
if ( \is_string( $value ) && $value === '' ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* Post Builder for the indexables.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Builders
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Builders;
|
||||
|
||||
use Yoast\WP\SEO\Models\Indexable;
|
||||
|
||||
/**
|
||||
* Formats the term meta to indexable format.
|
||||
*/
|
||||
class Indexable_Term_Builder {
|
||||
|
||||
/**
|
||||
* Formats the data.
|
||||
*
|
||||
* @param int $term_id ID of the term to save data for.
|
||||
* @param \Yoast\WP\SEO\Models\Indexable $indexable The indexable to format.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\Indexable The extended indexable.
|
||||
*/
|
||||
public function build( $term_id, Indexable $indexable ) {
|
||||
$term = \get_term( $term_id );
|
||||
$taxonomy = $term->taxonomy;
|
||||
$term_meta = \WPSEO_Taxonomy_Meta::get_term_meta( $term_id, $taxonomy );
|
||||
|
||||
$indexable->permalink = \get_term_link( $term_id, $taxonomy );
|
||||
$indexable->object_sub_type = $taxonomy;
|
||||
|
||||
$indexable->primary_focus_keyword_score = $this->get_keyword_score(
|
||||
$this->get_meta_value( 'wpseo_focuskw', $term_meta ),
|
||||
$this->get_meta_value( 'wpseo_linkdex', $term_meta )
|
||||
);
|
||||
|
||||
$indexable->is_robots_noindex = $this->get_noindex_value( $this->get_meta_value( 'wpseo_noindex', $term_meta ) );
|
||||
|
||||
foreach ( $this->get_indexable_lookup() as $meta_key => $indexable_key ) {
|
||||
$indexable->{ $indexable_key } = $this->get_meta_value( $meta_key, $term_meta );
|
||||
}
|
||||
|
||||
// Not implemented yet.
|
||||
$indexable->is_cornerstone = false;
|
||||
$indexable->is_robots_nofollow = null;
|
||||
$indexable->is_robots_noarchive = null;
|
||||
$indexable->is_robots_noimageindex = null;
|
||||
$indexable->is_robots_nosnippet = null;
|
||||
|
||||
return $indexable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the meta noindex value to the indexable value.
|
||||
*
|
||||
* @param string $meta_value Term meta to base the value on.
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
protected function get_noindex_value( $meta_value ) {
|
||||
if ( $meta_value === 'noindex' ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( $meta_value === 'index' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the focus keyword score.
|
||||
*
|
||||
* @param string $keyword The focus keyword that is set.
|
||||
* @param int $score The score saved on the meta data.
|
||||
*
|
||||
* @return null|int Score to use.
|
||||
*/
|
||||
protected function get_keyword_score( $keyword, $score ) {
|
||||
if ( empty( $keyword ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the lookup table.
|
||||
*
|
||||
* @return array Lookup table for the indexable fields.
|
||||
*/
|
||||
protected function get_indexable_lookup() {
|
||||
return [
|
||||
'wpseo_canonical' => 'canonical',
|
||||
'wpseo_focuskw' => 'primary_focus_keyword',
|
||||
'wpseo_title' => 'title',
|
||||
'wpseo_desc' => 'description',
|
||||
'wpseo_content_score' => 'readability_score',
|
||||
'wpseo_bctitle' => 'breadcrumb_title',
|
||||
'wpseo_opengraph-title' => 'og_title',
|
||||
'wpseo_opengraph-description' => 'og_description',
|
||||
'wpseo_opengraph-image' => 'og_image',
|
||||
'wpseo_twitter-title' => 'twitter_title',
|
||||
'wpseo_twitter-description' => 'twitter_description',
|
||||
'wpseo_twitter-image' => 'twitter_image',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a meta value from the given meta data.
|
||||
*
|
||||
* @param string $meta_key The key to extract.
|
||||
* @param array $term_meta The meta data.
|
||||
*
|
||||
* @return null|string The meta value.
|
||||
*/
|
||||
protected function get_meta_value( $meta_key, $term_meta ) {
|
||||
if ( ! \array_key_exists( $meta_key, $term_meta ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$value = $term_meta[ $meta_key ];
|
||||
if ( \is_string( $value ) && $value === '' ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO plugin file.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Conditionals
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Conditionals;
|
||||
|
||||
/**
|
||||
* Conditional that is only met when in the admin.
|
||||
*/
|
||||
class Admin_Conditional implements Conditional {
|
||||
|
||||
/**
|
||||
* Returns whether or not this conditional is met.
|
||||
*
|
||||
* @return boolean Whether or not the conditional is met.
|
||||
*/
|
||||
public function is_met() {
|
||||
return \is_admin();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO plugin file.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Conditionals
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Conditionals;
|
||||
|
||||
/**
|
||||
* Conditional interface, used to prevent integrations from loading.
|
||||
*
|
||||
* @package Yoast\WP\SEO\Conditionals
|
||||
*/
|
||||
interface Conditional {
|
||||
|
||||
/**
|
||||
* Returns whether or not this conditional is met.
|
||||
*
|
||||
* @return boolean Whether or not the conditional is met.
|
||||
*/
|
||||
public function is_met();
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO plugin file.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Conditionals
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Conditionals;
|
||||
|
||||
/**
|
||||
* Abstract class for creating conditionals based on feature flags.
|
||||
*/
|
||||
abstract class Feature_Flag_Conditional implements Conditional {
|
||||
|
||||
/**
|
||||
* Returns whether or not this conditional is met.
|
||||
*
|
||||
* @return boolean Whether or not the conditional is met.
|
||||
*/
|
||||
public function is_met() {
|
||||
$feature_flag = \strtoupper( $this->get_feature_flag() );
|
||||
|
||||
return \defined( 'YOAST_SEO_' . $feature_flag ) && \constant( 'YOAST_SEO_' . $feature_flag ) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the feature flag.
|
||||
* 'YOAST_SEO_' is automatically prepended to it and it will be uppercased.
|
||||
*
|
||||
* @return string the name of the feature flag.
|
||||
*/
|
||||
abstract protected function get_feature_flag();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO plugin file.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Conditionals
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Conditionals;
|
||||
|
||||
/**
|
||||
* Conditional for the indexables feature flag.
|
||||
*/
|
||||
class Indexables_Feature_Flag_Conditional extends Feature_Flag_Conditional {
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function get_feature_flag() {
|
||||
return 'indexables';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO plugin file.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Conditionals
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Conditionals;
|
||||
|
||||
/**
|
||||
* Trait for integrations that do not have any conditionals.
|
||||
*/
|
||||
trait No_Conditionals {
|
||||
|
||||
/**
|
||||
* Returns an empty array, meaning no conditionals are required to load whatever uses this trait.
|
||||
*
|
||||
* @return array The conditionals that must be met to load this.
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Config
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Config;
|
||||
|
||||
/**
|
||||
* Makes sure the dependencies are loaded and the environment is prepared to use them.
|
||||
* This is achieved by setting up class aliases and defines required constants.
|
||||
*/
|
||||
class Dependency_Management {
|
||||
|
||||
/**
|
||||
* Checks if the prefixes are available.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return bool True if prefixes are available.
|
||||
*/
|
||||
public function prefixed_available() {
|
||||
static $available = null;
|
||||
|
||||
if ( $available === null ) {
|
||||
$available = \is_file( \WPSEO_PATH . \YOAST_VENDOR_PREFIX_DIRECTORY . '/dependencies-prefixed.txt' );
|
||||
}
|
||||
|
||||
return $available;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Config
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Database;
|
||||
|
||||
use Yoast\WP\SEO\Conditionals\No_Conditionals;
|
||||
use Yoast\WP\SEO\Loggers\Logger;
|
||||
use Yoast\WP\SEO\WordPress\Initializer;
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
use YoastSEO_Vendor\ORM;
|
||||
|
||||
/**
|
||||
* Configures the ORM with the database credentials.
|
||||
*/
|
||||
class Database_Setup implements Initializer {
|
||||
use No_Conditionals;
|
||||
|
||||
/**
|
||||
* The logger object.
|
||||
*
|
||||
* @var \YoastSEO_Vendor\Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Database_Setup constructor.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Loggers\Logger $logger The logger.
|
||||
*/
|
||||
public function __construct( Logger $logger ) {
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the database setup.
|
||||
*/
|
||||
public function initialize() {
|
||||
ORM::configure( 'mysql:host=' . \DB_HOST . ';dbname=' . \DB_NAME );
|
||||
ORM::configure( 'username', \DB_USER );
|
||||
ORM::configure( 'password', \DB_PASSWORD );
|
||||
|
||||
Yoast_Model::$auto_prefix_models = '\\Yoast\\WP\\SEO\\Models\\';
|
||||
Yoast_Model::$logger = $this->logger;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Config
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Database;
|
||||
|
||||
use Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional;
|
||||
use Yoast\WP\SEO\Loggers\Logger;
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
use Yoast\WP\SEO\WordPress\Initializer;
|
||||
|
||||
/**
|
||||
* Triggers database migrations and handles results.
|
||||
*/
|
||||
class Migration_Runner implements Initializer {
|
||||
|
||||
/**
|
||||
* The value for a migration success state.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const MIGRATION_STATE_SUCCESS = 0;
|
||||
|
||||
/**
|
||||
* The value for a migration state error.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const MIGRATION_STATE_ERROR = 1;
|
||||
|
||||
/**
|
||||
* The value that communicates a migration problem.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const MIGRATION_ERROR_TRANSIENT_KEY = 'yoast_migration_problem_';
|
||||
|
||||
/**
|
||||
* The Ruckusing framework runner.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\Database\Ruckusing_Framework
|
||||
*/
|
||||
protected $framework;
|
||||
|
||||
/**
|
||||
* The logger object.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\Loggers\Logger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Retrieves the conditionals for the migrations.
|
||||
*
|
||||
* @return array The conditionals.
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Indexables_Feature_Flag_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrations constructor.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Database\Ruckusing_Framework $framework The Ruckusing framework runner.
|
||||
* @param \Yoast\WP\SEO\Loggers\Logger $logger A PSR compatible logger.
|
||||
*/
|
||||
public function __construct( Ruckusing_Framework $framework, Logger $logger ) {
|
||||
$this->framework = $framework;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs this initializer.
|
||||
*
|
||||
* @throws \Exception When a migration errored.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize() {
|
||||
$this->run_migrations( 'free', Yoast_Model::get_table_name( 'migrations' ), \WPSEO_PATH . 'migrations' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the migrations.
|
||||
*
|
||||
* @param string $name The name of the migration.
|
||||
* @param string $migrations_table_name The migrations table name.
|
||||
* @param string $migrations_directory The migrations directory.
|
||||
*
|
||||
* @return bool True on success, false on failure.
|
||||
* @throws \Exception If the migration fails and YOAST_ENVIRONMENT is not production.
|
||||
*/
|
||||
public function run_migrations( $name, $migrations_table_name, $migrations_directory ) {
|
||||
try {
|
||||
$framework_runner = $this->framework->get_framework_runner( $migrations_table_name, $migrations_directory );
|
||||
/**
|
||||
* This variable represents Ruckusing_Adapter_MySQL_Base adapter.
|
||||
*
|
||||
* @var \YoastSEO_Vendor\Ruckusing_Adapter_MySQL_Base $adapter
|
||||
*/
|
||||
$adapter = $framework_runner->get_adapter();
|
||||
|
||||
// Create our own migrations table with a 191 string limit to support older versions of MySQL.
|
||||
// Run this before calling the framework runner so it doesn't create it's own.
|
||||
if ( ! $adapter->has_table( $migrations_table_name ) ) {
|
||||
$table = $adapter->create_table( $migrations_table_name, [ 'id' => false ] );
|
||||
$table->column( 'version', 'string', [ 'limit' => 191 ] );
|
||||
$table->finish();
|
||||
$adapter->add_index( $migrations_table_name, 'version', [ 'unique' => true ] );
|
||||
}
|
||||
|
||||
// Create our own task manager so we can set RUCKUSING_BASE to a nonsense directory as it's impossible to
|
||||
// determine the actual directory if the plugin is installed with composer.
|
||||
$task_manager = $this->framework->get_framework_task_manager( $adapter, $migrations_table_name, $migrations_directory );
|
||||
$task_manager->execute( $framework_runner, 'db:migrate', [] );
|
||||
}
|
||||
catch ( \Exception $exception ) {
|
||||
$this->logger->error( $exception->getMessage() );
|
||||
|
||||
// Something went wrong...
|
||||
$this->set_failed_state( $name, $exception->getMessage() );
|
||||
|
||||
if ( \defined( 'YOAST_ENVIRONMENT' ) && \YOAST_ENVIRONMENT !== 'production' ) {
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->set_success_state( $name );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the state of the migrations.
|
||||
*
|
||||
* @param string $name The name of the migration.
|
||||
*
|
||||
* @return bool True if migrations have completed successfully.
|
||||
*/
|
||||
public function is_usable( $name ) {
|
||||
return ( $this->get_migration_state( $name ) === self::MIGRATION_STATE_SUCCESS );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the state of the migrations.
|
||||
*
|
||||
* @param string $name The name of the migration.
|
||||
*
|
||||
* @return bool True if migrations have completed successfully.
|
||||
*/
|
||||
public function has_migration_error( $name ) {
|
||||
return ( $this->get_migration_state( $name ) === self::MIGRATION_STATE_ERROR );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles state persistence for a failed migration environment.
|
||||
*
|
||||
* @param string $name The name of the migration.
|
||||
* @param string $message Message explaining the reason for the failed state.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function set_failed_state( $name, $message ) {
|
||||
// @todo do something with the message.
|
||||
\set_transient( $this->get_error_transient_key( $name ), self::MIGRATION_STATE_ERROR, \DAY_IN_SECONDS );
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the problem state from the system.
|
||||
*
|
||||
* @param string $name The name of the migration.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function set_success_state( $name ) {
|
||||
\delete_transient( $this->get_error_transient_key( $name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current migration state.
|
||||
*
|
||||
* @param string $name The name of the migration.
|
||||
*
|
||||
* @return int|null Migration state.
|
||||
*/
|
||||
protected function get_migration_state( $name ) {
|
||||
return \get_transient( $this->get_error_transient_key( $name ), self::MIGRATION_STATE_SUCCESS );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the error state transient key to use.
|
||||
*
|
||||
* @param string $name The name of the migration.
|
||||
*
|
||||
* @return string The transient key to use for storing the error state.
|
||||
*/
|
||||
protected function get_error_transient_key( $name ) {
|
||||
return self::MIGRATION_ERROR_TRANSIENT_KEY . $name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Config
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Database;
|
||||
|
||||
use wpdb;
|
||||
use Yoast\WP\SEO\Config\Dependency_Management;
|
||||
use Yoast\WP\SEO\Loggers\Migration_Logger;
|
||||
use YoastSEO_Vendor\Ruckusing_FrameworkRunner;
|
||||
use YoastSEO_Vendor\Ruckusing_Task_Manager;
|
||||
use YoastSEO_Vendor\Task_Db_Migrate;
|
||||
|
||||
/**
|
||||
* Class Ruckusing_Framework
|
||||
*/
|
||||
class Ruckusing_Framework {
|
||||
|
||||
/**
|
||||
* The database object.
|
||||
*
|
||||
* @var \wpdb
|
||||
*/
|
||||
protected $wpdb;
|
||||
|
||||
/**
|
||||
* The dependency management checker.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\Config\Dependency_Management
|
||||
*/
|
||||
protected $dependency_management;
|
||||
|
||||
/**
|
||||
* The migration logger object.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\Loggers\Migration_Logger
|
||||
*/
|
||||
protected $migration_logger;
|
||||
|
||||
/**
|
||||
* Ruckusing_Framework constructor.
|
||||
*
|
||||
* @param \wpdb $wpdb The wpdb instance.
|
||||
* @param \Yoast\WP\SEO\Config\Dependency_Management $dependency_management The dependency management checker.
|
||||
* @param \Yoast\WP\SEO\Loggers\Migration_Logger $migration_logger The migration logger, extends the
|
||||
* Ruckusing logger.
|
||||
*/
|
||||
public function __construct( wpdb $wpdb, Dependency_Management $dependency_management, Migration_Logger $migration_logger ) {
|
||||
$this->wpdb = $wpdb;
|
||||
$this->dependency_management = $dependency_management;
|
||||
$this->migration_logger = $migration_logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ruckusing framework runner.
|
||||
*
|
||||
* @param string $migrations_table_name The migrations table name.
|
||||
* @param string $migrations_directory The migrations directory.
|
||||
*
|
||||
* @return \YoastSEO_Vendor\Ruckusing_FrameworkRunner The framework runner.
|
||||
*/
|
||||
public function get_framework_runner( $migrations_table_name, $migrations_directory ) {
|
||||
$this->maybe_set_constant();
|
||||
|
||||
$configuration = $this->get_configuration( $migrations_table_name, $migrations_directory );
|
||||
$instance = new Ruckusing_FrameworkRunner( $configuration, [ 'db:migrate', 'env=production' ], $this->migration_logger );
|
||||
|
||||
/*
|
||||
* As the Ruckusing_FrameworkRunner is setting its own error and exception handlers,
|
||||
* we need to restore the defaults.
|
||||
*/
|
||||
\restore_error_handler();
|
||||
\restore_exception_handler();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ruckusing framework task manager.
|
||||
*
|
||||
* @param \YoastSEO_Vendor\Ruckusing_Adapter_MySQL_Base $adapter The MySQL adapter.
|
||||
* @param string $migrations_table_name The migrations table name.
|
||||
* @param string $migrations_directory The migrations directory.
|
||||
*
|
||||
* @return \YoastSEO_Vendor\Ruckusing_Task_Manager The task manager.
|
||||
* @throws \YoastSEO_Vendor\Ruckusing_Exception If any of the arguments are invalid.
|
||||
*/
|
||||
public function get_framework_task_manager( $adapter, $migrations_table_name, $migrations_directory ) {
|
||||
$task_manager = new Ruckusing_Task_Manager( $adapter, $this->get_configuration( $migrations_table_name, $migrations_directory ) );
|
||||
$task_manager->register_task( 'db:migrate', new Task_Db_Migrate( $adapter ) );
|
||||
|
||||
return $task_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the framework configuration for a given migrations table name and directory.
|
||||
*
|
||||
* @param string $migrations_table_name The migrations table name.
|
||||
* @param string $migrations_directory The migrations directory.
|
||||
*
|
||||
* @return array The configuration
|
||||
*/
|
||||
public function get_configuration( $migrations_table_name, $migrations_directory ) {
|
||||
return [
|
||||
'db' => [
|
||||
'production' => [
|
||||
'type' => 'mysql',
|
||||
'host' => \DB_HOST,
|
||||
'port' => 3306,
|
||||
'database' => \DB_NAME,
|
||||
'user' => \DB_USER,
|
||||
'password' => \DB_PASSWORD,
|
||||
'charset' => $this->wpdb->charset,
|
||||
'directory' => '', // This needs to be set, to use the migrations folder as base folder.
|
||||
'schema_version_table_name' => $migrations_table_name,
|
||||
],
|
||||
],
|
||||
'migrations_dir' => [ 'default' => $migrations_directory ],
|
||||
// This needs to be set but is not used.
|
||||
'db_dir' => true,
|
||||
// This needs to be set but is not used.
|
||||
'log_dir' => true,
|
||||
// This needs to be set but is not used.
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the constant required by the ruckusing framework.
|
||||
*
|
||||
* @return bool Whether or not the constant is now the correct value.
|
||||
*/
|
||||
public function maybe_set_constant() {
|
||||
$constant_name = $this->dependency_management->prefixed_available() ? \YOAST_VENDOR_NS_PREFIX . '\RUCKUSING_BASE' : 'RUCKUSING_BASE';
|
||||
$constant_value = \WPSEO_PATH . 'migrations' . \DIRECTORY_SEPARATOR . 'ruckusing';
|
||||
|
||||
if ( \defined( $constant_name ) ) {
|
||||
return \constant( $constant_name ) === $constant_value;
|
||||
}
|
||||
|
||||
return \define( $constant_name, $constant_value );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Exception to use when a method does not exist.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Exceptions
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Exceptions;
|
||||
|
||||
/**
|
||||
* The exception when a method does not exists.
|
||||
*/
|
||||
class Missing_Method extends \Exception {
|
||||
|
||||
/**
|
||||
* Creates exception for a method that does not exists in a class.
|
||||
*
|
||||
* @param string $method The method that does not exists.
|
||||
* @param string $class_name The class name.
|
||||
*
|
||||
* @return static Instance of the exception.
|
||||
*/
|
||||
public static function for_class( $method, $class_name ) {
|
||||
return new static(
|
||||
\sprintf(
|
||||
/* translators: %1$s expands to the method name. %2$s expands to the class name */
|
||||
\__( 'Method %1$s() does not exist in class %2$s', 'wordpress-seo' ),
|
||||
$method,
|
||||
$class_name
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
325
wp-content/plugins/wordpress-seo/src/generated/container.php
Normal file
325
wp-content/plugins/wordpress-seo/src/generated/container.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
namespace Yoast\WP\SEO\Generated;
|
||||
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Container;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
|
||||
|
||||
/**
|
||||
* This class has been auto-generated
|
||||
* by the Symfony Dependency Injection Component.
|
||||
*
|
||||
* @final since Symfony 3.3
|
||||
*/
|
||||
class Cached_Container extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->services = [];
|
||||
$this->normalizedIds = [
|
||||
'yoast\\wp\\seo\\builders\\indexable_author_builder' => 'Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder',
|
||||
'yoast\\wp\\seo\\builders\\indexable_post_builder' => 'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder',
|
||||
'yoast\\wp\\seo\\builders\\indexable_term_builder' => 'Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder',
|
||||
'yoast\\wp\\seo\\conditionals\\admin_conditional' => 'Yoast\\WP\\SEO\\Conditionals\\Admin_Conditional',
|
||||
'yoast\\wp\\seo\\conditionals\\indexables_feature_flag_conditional' => 'Yoast\\WP\\SEO\\Conditionals\\Indexables_Feature_Flag_Conditional',
|
||||
'yoast\\wp\\seo\\database\\database_setup' => 'Yoast\\WP\\SEO\\Database\\Database_Setup',
|
||||
'yoast\\wp\\seo\\database\\migration_runner' => 'Yoast\\WP\\SEO\\Database\\Migration_Runner',
|
||||
'yoast\\wp\\seo\\loader' => 'Yoast\\WP\\SEO\\Loader',
|
||||
'yoast\\wp\\seo\\loggers\\logger' => 'Yoast\\WP\\SEO\\Loggers\\Logger',
|
||||
'yoast\\wp\\seo\\repositories\\indexable_repository' => 'Yoast\\WP\\SEO\\Repositories\\Indexable_Repository',
|
||||
'yoast\\wp\\seo\\repositories\\primary_term_repository' => 'Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository',
|
||||
'yoast\\wp\\seo\\repositories\\seo_links_repository' => 'Yoast\\WP\\SEO\\Repositories\\SEO_Links_Repository',
|
||||
'yoast\\wp\\seo\\repositories\\seo_meta_repository' => 'Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository',
|
||||
'yoast\\wp\\seo\\watchers\\indexable_author_watcher' => 'Yoast\\WP\\SEO\\Watchers\\Indexable_Author_Watcher',
|
||||
'yoast\\wp\\seo\\watchers\\indexable_post_watcher' => 'Yoast\\WP\\SEO\\Watchers\\Indexable_Post_Watcher',
|
||||
'yoast\\wp\\seo\\watchers\\indexable_term_watcher' => 'Yoast\\WP\\SEO\\Watchers\\Indexable_Term_Watcher',
|
||||
'yoast\\wp\\seo\\watchers\\primary_term_watcher' => 'Yoast\\WP\\SEO\\Watchers\\Primary_Term_Watcher',
|
||||
];
|
||||
$this->methodMap = [
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder' => 'getIndexableAuthorBuilderService',
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder' => 'getIndexablePostBuilderService',
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder' => 'getIndexableTermBuilderService',
|
||||
'Yoast\\WP\\SEO\\Conditionals\\Admin_Conditional' => 'getAdminConditionalService',
|
||||
'Yoast\\WP\\SEO\\Conditionals\\Indexables_Feature_Flag_Conditional' => 'getIndexablesFeatureFlagConditionalService',
|
||||
'Yoast\\WP\\SEO\\Database\\Database_Setup' => 'getDatabaseSetupService',
|
||||
'Yoast\\WP\\SEO\\Database\\Migration_Runner' => 'getMigrationRunnerService',
|
||||
'Yoast\\WP\\SEO\\Loader' => 'getLoaderService',
|
||||
'Yoast\\WP\\SEO\\Loggers\\Logger' => 'getLoggerService',
|
||||
'Yoast\\WP\\SEO\\Repositories\\Indexable_Repository' => 'getIndexableRepositoryService',
|
||||
'Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository' => 'getPrimaryTermRepositoryService',
|
||||
'Yoast\\WP\\SEO\\Repositories\\SEO_Links_Repository' => 'getSEOLinksRepositoryService',
|
||||
'Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository' => 'getSEOMetaRepositoryService',
|
||||
'Yoast\\WP\\SEO\\Watchers\\Indexable_Author_Watcher' => 'getIndexableAuthorWatcherService',
|
||||
'Yoast\\WP\\SEO\\Watchers\\Indexable_Post_Watcher' => 'getIndexablePostWatcherService',
|
||||
'Yoast\\WP\\SEO\\Watchers\\Indexable_Term_Watcher' => 'getIndexableTermWatcherService',
|
||||
'Yoast\\WP\\SEO\\Watchers\\Primary_Term_Watcher' => 'getPrimaryTermWatcherService',
|
||||
'wp_query' => 'getWpQueryService',
|
||||
'wpdb' => 'getWpdbService',
|
||||
];
|
||||
$this->privates = [
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder' => true,
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder' => true,
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder' => true,
|
||||
'Yoast\\WP\\SEO\\Loggers\\Logger' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\Indexable_Repository' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\SEO_Links_Repository' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository' => true,
|
||||
'wp_query' => true,
|
||||
'wpdb' => true,
|
||||
];
|
||||
|
||||
$this->aliases = [];
|
||||
}
|
||||
|
||||
public function getRemovedIds()
|
||||
{
|
||||
return [
|
||||
'Psr\\Container\\ContainerInterface' => true,
|
||||
'YoastSEO_Vendor\\Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder' => true,
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder' => true,
|
||||
'Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder' => true,
|
||||
'Yoast\\WP\\SEO\\Config\\Dependency_Management' => true,
|
||||
'Yoast\\WP\\SEO\\Database\\Ruckusing_Framework' => true,
|
||||
'Yoast\\WP\\SEO\\Exceptions\\Missing_Method' => true,
|
||||
'Yoast\\WP\\SEO\\Helpers\\Author_Archive_Helper' => true,
|
||||
'Yoast\\WP\\SEO\\Helpers\\Home_Url_Helper' => true,
|
||||
'Yoast\\WP\\SEO\\Loggers\\Logger' => true,
|
||||
'Yoast\\WP\\SEO\\Loggers\\Migration_Logger' => true,
|
||||
'Yoast\\WP\\SEO\\Oauth\\Client' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\Indexable_Repository' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\SEO_Links_Repository' => true,
|
||||
'Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository' => true,
|
||||
'wp_query' => true,
|
||||
'wpdb' => true,
|
||||
];
|
||||
}
|
||||
|
||||
public function compile()
|
||||
{
|
||||
throw new LogicException('You cannot compile a dumped container that was already compiled.');
|
||||
}
|
||||
|
||||
public function isCompiled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isFrozen()
|
||||
{
|
||||
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Conditionals\Admin_Conditional' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Conditionals\Admin_Conditional
|
||||
*/
|
||||
protected function getAdminConditionalService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Conditionals\\Admin_Conditional'] = new \Yoast\WP\SEO\Conditionals\Admin_Conditional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional
|
||||
*/
|
||||
protected function getIndexablesFeatureFlagConditionalService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Conditionals\\Indexables_Feature_Flag_Conditional'] = new \Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Database\Database_Setup' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Database\Database_Setup
|
||||
*/
|
||||
protected function getDatabaseSetupService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Database\\Database_Setup'] = new \Yoast\WP\SEO\Database\Database_Setup(${($_ = isset($this->services['Yoast\\WP\\SEO\\Loggers\\Logger']) ? $this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] : ($this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] = new \Yoast\WP\SEO\Loggers\Logger())) && false ?: '_'});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Database\Migration_Runner' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Database\Migration_Runner
|
||||
*/
|
||||
protected function getMigrationRunnerService()
|
||||
{
|
||||
$a = ${($_ = isset($this->services['Yoast\\WP\\SEO\\Loggers\\Logger']) ? $this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] : ($this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] = new \Yoast\WP\SEO\Loggers\Logger())) && false ?: '_'};
|
||||
|
||||
return $this->services['Yoast\\WP\\SEO\\Database\\Migration_Runner'] = new \Yoast\WP\SEO\Database\Migration_Runner(new \Yoast\WP\SEO\Database\Ruckusing_Framework(${($_ = isset($this->services['wpdb']) ? $this->services['wpdb'] : $this->getWpdbService()) && false ?: '_'}, new \Yoast\WP\SEO\Config\Dependency_Management(), new \Yoast\WP\SEO\Loggers\Migration_Logger($a)), $a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Loader' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Loader
|
||||
*/
|
||||
protected function getLoaderService()
|
||||
{
|
||||
$this->services['Yoast\\WP\\SEO\\Loader'] = $instance = new \Yoast\WP\SEO\Loader($this);
|
||||
|
||||
$instance->register_initializer('Yoast\\WP\\SEO\\Database\\Database_Setup');
|
||||
$instance->register_initializer('Yoast\\WP\\SEO\\Database\\Migration_Runner');
|
||||
$instance->register_integration('Yoast\\WP\\SEO\\Watchers\\Indexable_Author_Watcher');
|
||||
$instance->register_integration('Yoast\\WP\\SEO\\Watchers\\Indexable_Post_Watcher');
|
||||
$instance->register_integration('Yoast\\WP\\SEO\\Watchers\\Indexable_Term_Watcher');
|
||||
$instance->register_integration('Yoast\\WP\\SEO\\Watchers\\Primary_Term_Watcher');
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Watchers\Indexable_Author_Watcher' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Watchers\Indexable_Author_Watcher
|
||||
*/
|
||||
protected function getIndexableAuthorWatcherService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Watchers\\Indexable_Author_Watcher'] = new \Yoast\WP\SEO\Watchers\Indexable_Author_Watcher(${($_ = isset($this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository']) ? $this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository'] : $this->getIndexableRepositoryService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder']) ? $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder'] : ($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder'] = new \Yoast\WP\SEO\Builders\Indexable_Author_Builder())) && false ?: '_'});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Watchers\Indexable_Post_Watcher' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Watchers\Indexable_Post_Watcher
|
||||
*/
|
||||
protected function getIndexablePostWatcherService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Watchers\\Indexable_Post_Watcher'] = new \Yoast\WP\SEO\Watchers\Indexable_Post_Watcher(${($_ = isset($this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository']) ? $this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository'] : $this->getIndexableRepositoryService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder']) ? $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder'] : $this->getIndexablePostBuilderService()) && false ?: '_'});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Watchers\Indexable_Term_Watcher' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Watchers\Indexable_Term_Watcher
|
||||
*/
|
||||
protected function getIndexableTermWatcherService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Watchers\\Indexable_Term_Watcher'] = new \Yoast\WP\SEO\Watchers\Indexable_Term_Watcher(${($_ = isset($this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository']) ? $this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository'] : $this->getIndexableRepositoryService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder']) ? $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder'] : ($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder'] = new \Yoast\WP\SEO\Builders\Indexable_Term_Builder())) && false ?: '_'});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the public 'Yoast\WP\SEO\Watchers\Primary_Term_Watcher' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Watchers\Primary_Term_Watcher
|
||||
*/
|
||||
protected function getPrimaryTermWatcherService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Watchers\\Primary_Term_Watcher'] = new \Yoast\WP\SEO\Watchers\Primary_Term_Watcher(${($_ = isset($this->services['Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository']) ? $this->services['Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository'] : $this->getPrimaryTermRepositoryService()) && false ?: '_'});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Builders\Indexable_Author_Builder' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Builders\Indexable_Author_Builder
|
||||
*/
|
||||
protected function getIndexableAuthorBuilderService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder'] = new \Yoast\WP\SEO\Builders\Indexable_Author_Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Builders\Indexable_Post_Builder' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Builders\Indexable_Post_Builder
|
||||
*/
|
||||
protected function getIndexablePostBuilderService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder'] = new \Yoast\WP\SEO\Builders\Indexable_Post_Builder(${($_ = isset($this->services['Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository']) ? $this->services['Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository'] : $this->getSEOMetaRepositoryService()) && false ?: '_'});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Builders\Indexable_Term_Builder' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Builders\Indexable_Term_Builder
|
||||
*/
|
||||
protected function getIndexableTermBuilderService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder'] = new \Yoast\WP\SEO\Builders\Indexable_Term_Builder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Loggers\Logger' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Loggers\Logger
|
||||
*/
|
||||
protected function getLoggerService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] = new \Yoast\WP\SEO\Loggers\Logger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Repositories\Indexable_Repository' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\Indexable_Repository
|
||||
*/
|
||||
protected function getIndexableRepositoryService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Repositories\\Indexable_Repository'] = \Yoast\WP\SEO\Repositories\Indexable_Repository::get_instance(${($_ = isset($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder']) ? $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder'] : ($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Author_Builder'] = new \Yoast\WP\SEO\Builders\Indexable_Author_Builder())) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder']) ? $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Post_Builder'] : $this->getIndexablePostBuilderService()) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder']) ? $this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder'] : ($this->services['Yoast\\WP\\SEO\\Builders\\Indexable_Term_Builder'] = new \Yoast\WP\SEO\Builders\Indexable_Term_Builder())) && false ?: '_'}, ${($_ = isset($this->services['Yoast\\WP\\SEO\\Loggers\\Logger']) ? $this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] : ($this->services['Yoast\\WP\\SEO\\Loggers\\Logger'] = new \Yoast\WP\SEO\Loggers\Logger())) && false ?: '_'});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Repositories\Primary_Term_Repository' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\Primary_Term_Repository
|
||||
*/
|
||||
protected function getPrimaryTermRepositoryService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Repositories\\Primary_Term_Repository'] = \Yoast\WP\SEO\Repositories\Primary_Term_Repository::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Repositories\SEO_Links_Repository' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\SEO_Links_Repository
|
||||
*/
|
||||
protected function getSEOLinksRepositoryService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Repositories\\SEO_Links_Repository'] = \Yoast\WP\SEO\Repositories\SEO_Links_Repository::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'Yoast\WP\SEO\Repositories\SEO_Meta_Repository' shared autowired service.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\SEO_Meta_Repository
|
||||
*/
|
||||
protected function getSEOMetaRepositoryService()
|
||||
{
|
||||
return $this->services['Yoast\\WP\\SEO\\Repositories\\SEO_Meta_Repository'] = \Yoast\WP\SEO\Repositories\SEO_Meta_Repository::get_instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'wp_query' shared service.
|
||||
*
|
||||
* @return \WP_Query
|
||||
*/
|
||||
protected function getWpQueryService()
|
||||
{
|
||||
return $this->services['wp_query'] = \Yoast\WP\SEO\WordPress\Wrapper::get_wp_query();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the private 'wpdb' shared service.
|
||||
*
|
||||
* @return \wpdb
|
||||
*/
|
||||
protected function getWpdbService()
|
||||
{
|
||||
return $this->services['wpdb'] = \Yoast\WP\SEO\WordPress\Wrapper::get_wpdb();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* A helper object for author archives.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Helpers
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Helpers;
|
||||
|
||||
/**
|
||||
* Class Author_Archive_Helper
|
||||
*/
|
||||
class Author_Archive_Helper {
|
||||
|
||||
/**
|
||||
* Gets the array of post types that are shown on an author's archive.
|
||||
*
|
||||
* @return array The post types that are shown on an author's archive.
|
||||
*/
|
||||
public function get_author_archive_post_types() {
|
||||
/**
|
||||
* Filters the array of post types that are shown on an author's archive.
|
||||
*
|
||||
* @param array $args The post types that are shown on an author archive.
|
||||
*/
|
||||
return \apply_filters( 'wpseo_author_archive_post_types', [ 'post' ] );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* A helper object for the home url.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Helpers
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Helpers;
|
||||
|
||||
/**
|
||||
* Class Home_Url_Helper
|
||||
*/
|
||||
class Home_Url_Helper {
|
||||
|
||||
/**
|
||||
* The home url.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $home_url;
|
||||
|
||||
/**
|
||||
* The parsed home url.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $parsed_home_url;
|
||||
|
||||
/**
|
||||
* Retrieves the home url.
|
||||
*
|
||||
* @return string The home url.
|
||||
*/
|
||||
public function get() {
|
||||
if ( static::$home_url === null ) {
|
||||
static::$home_url = \home_url();
|
||||
}
|
||||
|
||||
return static::$home_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the home url that has been parsed.
|
||||
*
|
||||
* @return array The parsed url.
|
||||
*/
|
||||
public function get_parsed() {
|
||||
if ( static::$parsed_home_url === null ) {
|
||||
static::$parsed_home_url = \wp_parse_url( $this->get() );
|
||||
}
|
||||
|
||||
return static::$parsed_home_url;
|
||||
}
|
||||
}
|
||||
126
wp-content/plugins/wordpress-seo/src/loader.php
Normal file
126
wp-content/plugins/wordpress-seo/src/loader.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\WP\SEO
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO;
|
||||
|
||||
use YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class that manages loading integrations if and only if all their conditionals are met.
|
||||
*/
|
||||
class Loader {
|
||||
|
||||
/**
|
||||
* The registered integrations.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\WordPress\Integration[]
|
||||
*/
|
||||
protected $integrations = [];
|
||||
|
||||
/**
|
||||
* The registered initializer.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\WordPress\Initializer[]
|
||||
*/
|
||||
protected $initializers = [];
|
||||
|
||||
/**
|
||||
* The dependency injection container.
|
||||
*
|
||||
* @var \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Loader constructor.
|
||||
*
|
||||
* @param \YoastSEO_Vendor\Symfony\Component\DependencyInjection\ContainerInterface $container The dependency injection container.
|
||||
*/
|
||||
public function __construct( ContainerInterface $container ) {
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers an integration.
|
||||
*
|
||||
* @param string $class The class name of the integration to be loaded.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_integration( $class ) {
|
||||
$this->integrations[] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a initializer.
|
||||
*
|
||||
* @param string $class The class name of the initializer to be loaded.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_initializer( $class ) {
|
||||
$this->initializers[] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all registered classes if their conditionals are met.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function load() {
|
||||
$this->load_initializers();
|
||||
$this->load_integrations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all registered initializers if their conditionals are met.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function load_initializers() {
|
||||
foreach ( $this->initializers as $class ) {
|
||||
if ( ! $this->conditionals_are_met( $class ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->container->get( $class )->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all registered integrations if their conditionals are met.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function load_integrations() {
|
||||
foreach ( $this->integrations as $class ) {
|
||||
if ( ! $this->conditionals_are_met( $class ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->container->get( $class )->register_hooks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all conditionals of a given integration are met.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\WordPress\Loadable $class The class name of the integration.
|
||||
*
|
||||
* @return bool Whether or not all conditionals of the integration are met.
|
||||
*/
|
||||
protected function conditionals_are_met( $class ) {
|
||||
$conditionals = $class::get_conditionals();
|
||||
foreach ( $conditionals as $conditional ) {
|
||||
if ( ! $this->container->get( $conditional )->is_met() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
34
wp-content/plugins/wordpress-seo/src/loaders/oauth.php
Normal file
34
wp-content/plugins/wordpress-seo/src/loaders/oauth.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* WPSEO plugin file.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Loaders
|
||||
*/
|
||||
|
||||
use Yoast\WP\SEO\Config\Dependency_Management;
|
||||
use Yoast\WP\SEO\Oauth\Client;
|
||||
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface;
|
||||
|
||||
if ( ! defined( 'WPSEO_VERSION' ) ) {
|
||||
header( 'Status: 403 Forbidden' );
|
||||
header( 'HTTP/1.1 403 Forbidden' );
|
||||
exit();
|
||||
}
|
||||
|
||||
if ( file_exists( dirname( WPSEO_FILE ) . '/vendor_prefixed/guzzlehttp/guzzle/src/functions.php' ) ) {
|
||||
require_once dirname( WPSEO_FILE ) . '/vendor_prefixed/guzzlehttp/guzzle/src/functions.php';
|
||||
}
|
||||
|
||||
if ( file_exists( dirname( WPSEO_FILE ) . '/vendor_prefixed/guzzlehttp/psr7/src/functions.php' ) ) {
|
||||
require_once dirname( WPSEO_FILE ) . '/vendor_prefixed/guzzlehttp/psr7/src/functions.php';
|
||||
}
|
||||
|
||||
if ( file_exists( dirname( WPSEO_FILE ) . '/vendor_prefixed/guzzlehttp/promises/src/functions.php' ) ) {
|
||||
require_once dirname( WPSEO_FILE ) . '/vendor_prefixed/guzzlehttp/promises/src/functions.php';
|
||||
}
|
||||
|
||||
$yoast_seo_dependecy_management = new Dependency_Management();
|
||||
$yoast_seo_dependecy_management->initialize();
|
||||
|
||||
class_alias( Client::class, 'WPSEO_MyYoast_Client' );
|
||||
class_alias( AccessTokenInterface::class, 'WPSEO_MyYoast_AccessToken_Interface' );
|
||||
55
wp-content/plugins/wordpress-seo/src/loggers/logger.php
Normal file
55
wp-content/plugins/wordpress-seo/src/loggers/logger.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the Model class.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Loggers
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Loggers;
|
||||
|
||||
use YoastSEO_Vendor\Psr\Log\LoggerInterface;
|
||||
use YoastSEO_Vendor\Psr\Log\LoggerTrait;
|
||||
use YoastSEO_Vendor\Psr\Log\NullLogger;
|
||||
|
||||
/**
|
||||
* Creates an instance of a logger object.
|
||||
*/
|
||||
class Logger implements LoggerInterface {
|
||||
use LoggerTrait;
|
||||
|
||||
/**
|
||||
* The logger object.
|
||||
*
|
||||
* @var \YoastSEO_Vendor\Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $wrapped_logger;
|
||||
|
||||
/**
|
||||
* Logger constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->wrapped_logger = new NullLogger();
|
||||
|
||||
/**
|
||||
* Gives the possibility to set override the logger interface.
|
||||
*
|
||||
* @api \YoastSEO_Vendor\Psr\Log\LoggerInterface $logger Instance of NullLogger.
|
||||
*
|
||||
* @return \YoastSEO_Vendor\Psr\Log\LoggerInterface The logger object.
|
||||
*/
|
||||
$this->wrapped_logger = \apply_filters( 'wpseo_logger', $this->wrapped_logger );
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs with an arbitrary level.
|
||||
*
|
||||
* @param mixed $level The log level.
|
||||
* @param string $message The log message.
|
||||
* @param array $context The log context.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function log( $level, $message, array $context = [] ) {
|
||||
$this->wrapped_logger->log( $level, $message, $context );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* Empty migration logger.
|
||||
*
|
||||
* @package Yoast\YoastSEO
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Loggers;
|
||||
|
||||
use YoastSEO_Vendor\Ruckusing_Util_Logger;
|
||||
|
||||
/**
|
||||
* Logger to make sure the output is not written into a file.
|
||||
*/
|
||||
class Migration_Logger extends Ruckusing_Util_Logger {
|
||||
|
||||
/**
|
||||
* The logger object.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\Loggers\Logger
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Creates an instance of Ruckusing_Util_Logger.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Loggers\Logger $logger The logger to wrap.
|
||||
*/
|
||||
public function __construct( Logger $logger ) {
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param string $msg Message to log.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function log( $msg ) {
|
||||
$this->logger->info( $msg );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the log file handler.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close() {
|
||||
}
|
||||
}
|
||||
38
wp-content/plugins/wordpress-seo/src/main.php
Normal file
38
wp-content/plugins/wordpress-seo/src/main.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Loaders
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO;
|
||||
|
||||
use Yoast\WP\SEO\Dependency_Injection\Container_Compiler;
|
||||
use Yoast\WP\SEO\Generated\Cached_Container;
|
||||
|
||||
if ( ! \defined( 'WPSEO_VERSION' ) ) {
|
||||
\header( 'Status: 403 Forbidden' );
|
||||
\header( 'HTTP/1.1 403 Forbidden' );
|
||||
exit();
|
||||
}
|
||||
|
||||
$development = \defined( 'YOAST_ENVIRONMENT' ) && \YOAST_ENVIRONMENT === 'development';
|
||||
if ( $development && \class_exists( '\Yoast\WP\SEO\Dependency_Injection\Container_Compiler' ) ) {
|
||||
// Exception here is unhandled as it will only occur in development.
|
||||
Container_Compiler::compile( $development );
|
||||
}
|
||||
|
||||
if ( \file_exists( __DIR__ . '/generated/container.php' ) ) {
|
||||
require_once __DIR__ . '/generated/container.php';
|
||||
$container = new Cached_Container();
|
||||
try {
|
||||
$container->get( Loader::class )->load();
|
||||
} catch ( \Exception $e ) {
|
||||
if ( $development ) {
|
||||
throw $e;
|
||||
}
|
||||
// Don't crash the entire site, simply don't load.
|
||||
// TODO: Add error notifications here.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Models
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Models;
|
||||
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Abstract class for indexable extensions.
|
||||
*/
|
||||
abstract class Indexable_Extension extends Yoast_Model {
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Models\Indexable
|
||||
*/
|
||||
protected $indexable = null;
|
||||
|
||||
/**
|
||||
* Returns the indexable this extension belongs to.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\Indexable The indexable.
|
||||
*/
|
||||
public function indexable() {
|
||||
if ( $this->indexable === null ) {
|
||||
$this->indexable = $this->belongs_to( 'Indexable', 'indexable_id', 'id' )->find_one();
|
||||
}
|
||||
|
||||
return $this->indexable;
|
||||
}
|
||||
}
|
||||
100
wp-content/plugins/wordpress-seo/src/models/indexable.php
Normal file
100
wp-content/plugins/wordpress-seo/src/models/indexable.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* Model for the Indexable table.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Models
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Models;
|
||||
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Indexable table definition.
|
||||
*
|
||||
* @property int $id
|
||||
* @property int $object_id
|
||||
* @property string $object_type
|
||||
* @property string $object_sub_type
|
||||
*
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
*
|
||||
* @property string $permalink
|
||||
* @property string $permalink_hash
|
||||
* @property string $canonical
|
||||
* @property int $content_score
|
||||
*
|
||||
* @property boolean $is_robots_noindex
|
||||
* @property boolean $is_robots_nofollow
|
||||
* @property boolean $is_robots_noarchive
|
||||
* @property boolean $is_robots_noimageindex
|
||||
* @property boolean $is_robots_nosnippet
|
||||
*
|
||||
* @property string $title
|
||||
* @property string $description
|
||||
* @property string $breadcrumb_title
|
||||
*
|
||||
* @property boolean $is_cornerstone
|
||||
*
|
||||
* @property string $primary_focus_keyword
|
||||
* @property int $primary_focus_keyword_score
|
||||
*
|
||||
* @property int $readability_score
|
||||
*
|
||||
* @property int $link_count
|
||||
* @property int $incoming_link_count
|
||||
*
|
||||
* @property string $og_title
|
||||
* @property string $og_description
|
||||
* @property string $og_image
|
||||
*
|
||||
* @property string $twitter_title
|
||||
* @property string $twitter_description
|
||||
* @property string $twitter_image
|
||||
*/
|
||||
class Indexable extends Yoast_Model {
|
||||
|
||||
/**
|
||||
* Whether nor this model uses timestamps.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $uses_timestamps = true;
|
||||
|
||||
/**
|
||||
* The loaded indexable extensions.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\Models\Indexable_Extension[]
|
||||
*/
|
||||
protected $loaded_extensions = [];
|
||||
|
||||
/**
|
||||
* Returns an Indexable_Extension by it's name.
|
||||
*
|
||||
* @param string $class_name The class name of the extension to load.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\Indexable_Extension|bool The extension.
|
||||
*/
|
||||
public function get_extension( $class_name ) {
|
||||
if ( ! $this->loaded_extensions[ $class_name ] ) {
|
||||
$this->loaded_extensions[ $class_name ] = $this->has_one( $class_name, 'indexable_id', 'id' )->find_one();
|
||||
}
|
||||
|
||||
return $this->loaded_extensions[ $class_name ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhances the save method.
|
||||
*
|
||||
* @return boolean True on succes.
|
||||
*/
|
||||
public function save() {
|
||||
if ( $this->permalink ) {
|
||||
$this->permalink = \trailingslashit( $this->permalink );
|
||||
$this->permalink_hash = \strlen( $this->permalink ) . ':' . \md5( $this->permalink );
|
||||
}
|
||||
|
||||
return parent::save();
|
||||
}
|
||||
}
|
||||
31
wp-content/plugins/wordpress-seo/src/models/primary-term.php
Normal file
31
wp-content/plugins/wordpress-seo/src/models/primary-term.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Model for the Primary Term table.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Models
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Models;
|
||||
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Primary Term model definition.
|
||||
*
|
||||
* @property int $id Identifier.
|
||||
* @property int $post_id Post ID.
|
||||
* @property int $term_id Term ID.
|
||||
* @property string $taxonomy Taxonomy.
|
||||
*
|
||||
* @property string $created_at
|
||||
* @property string $updated_at
|
||||
*/
|
||||
class Primary_Term extends Yoast_Model {
|
||||
|
||||
/**
|
||||
* Whether nor this model uses timestamps.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $uses_timestamps = true;
|
||||
}
|
||||
22
wp-content/plugins/wordpress-seo/src/models/seo-links.php
Normal file
22
wp-content/plugins/wordpress-seo/src/models/seo-links.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* Model for the SEO Meta table.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Models
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Models;
|
||||
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Table definition for the SEO Meta table.
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $url
|
||||
* @property int $post_id
|
||||
* @property int $target_post_id
|
||||
* @property string $type
|
||||
*/
|
||||
class SEO_Links extends Yoast_Model {
|
||||
}
|
||||
27
wp-content/plugins/wordpress-seo/src/models/seo-meta.php
Normal file
27
wp-content/plugins/wordpress-seo/src/models/seo-meta.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Model for the SEO Meta table.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Models
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Models;
|
||||
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Table definition for the SEO Meta table.
|
||||
*
|
||||
* @property int $object_id
|
||||
* @property int $internal_link_count
|
||||
* @property int $incoming_link_count
|
||||
*/
|
||||
class SEO_Meta extends Yoast_Model {
|
||||
|
||||
/**
|
||||
* Overwrites the default ID column name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $id_column = 'object_id';
|
||||
}
|
||||
266
wp-content/plugins/wordpress-seo/src/oauth/client.php
Normal file
266
wp-content/plugins/wordpress-seo/src/oauth/client.php
Normal file
@@ -0,0 +1,266 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the Model class.
|
||||
*
|
||||
* @package Yoast\WP\SEO\Oauth
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Oauth;
|
||||
|
||||
use WPSEO_Options;
|
||||
use WPSEO_Utils;
|
||||
use YoastSEO_Vendor\League\OAuth2\Client\Provider\GenericProvider;
|
||||
use YoastSEO_Vendor\League\OAuth2\Client\Token\AccessToken;
|
||||
|
||||
/**
|
||||
* Represents the oAuth client.
|
||||
*/
|
||||
class Client {
|
||||
|
||||
/**
|
||||
* Contains the configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Contains the set access tokens.
|
||||
*
|
||||
* @var \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface[]
|
||||
*/
|
||||
private $access_tokens;
|
||||
|
||||
/**
|
||||
* Instance of this class.
|
||||
*
|
||||
* @var static
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Client constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct() {
|
||||
$oauth = $this->get_option();
|
||||
|
||||
$this->config = $oauth['config'];
|
||||
$this->access_tokens = $this->format_access_tokens( $oauth['access_tokens'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the instance of this class.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Oauth\Client Instance of this class.
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if ( static::$instance === null ) {
|
||||
static::$instance = new static();
|
||||
}
|
||||
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the configuration.
|
||||
*
|
||||
* @param array $config The configuration to use.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save_configuration( array $config ) {
|
||||
$allowed_config_keys = [ 'clientId', 'secret' ];
|
||||
foreach ( $allowed_config_keys as $allowed_config_key ) {
|
||||
if ( ! \array_key_exists( $allowed_config_key, $config ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->config[ $allowed_config_key ] = $config[ $allowed_config_key ];
|
||||
}
|
||||
$this->update_option();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the value of the config.
|
||||
*
|
||||
* @return array The config.
|
||||
*/
|
||||
public function get_configuration() {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the configuration is set correctly.
|
||||
*
|
||||
* @return bool True when clientId and secret are set.
|
||||
*/
|
||||
public function has_configuration() {
|
||||
if ( $this->config['clientId'] === null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $this->config['secret'] === null ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current configuration.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function clear_configuration() {
|
||||
$this->config = $this->get_default_option()['config'];
|
||||
|
||||
$this->update_option();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the access token for the given user.
|
||||
*
|
||||
* @param int $user_id User ID to receive token for.
|
||||
* @param \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface $access_token The access token to save.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save_access_token( $user_id, $access_token ) {
|
||||
$this->access_tokens[ $user_id ] = $access_token;
|
||||
$this->update_option();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an access token.
|
||||
*
|
||||
* @param null|int $user_id User ID to receive token for.
|
||||
*
|
||||
* @return bool|\YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface False if not found. Token when found.
|
||||
*/
|
||||
public function get_access_token( $user_id = null ) {
|
||||
if ( $user_id === null ) {
|
||||
return \reset( $this->access_tokens );
|
||||
}
|
||||
|
||||
if ( ! isset( $this->access_tokens[ $user_id ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->access_tokens[ $user_id ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an access token from the list of access token.
|
||||
*
|
||||
* @param int $user_id The user ID to remove the access token for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function remove_access_token( $user_id ) {
|
||||
if ( ! isset( $this->access_tokens[ $user_id ] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset( $this->access_tokens[ $user_id ] );
|
||||
|
||||
$this->update_option();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the oAuth provider.
|
||||
*
|
||||
* @return \YoastSEO_Vendor\League\OAuth2\Client\Provider\GenericProvider The provider.
|
||||
*/
|
||||
public function get_provider() {
|
||||
return new GenericProvider(
|
||||
[
|
||||
'clientId' => $this->config['clientId'],
|
||||
'clientSecret' => $this->config['secret'],
|
||||
'redirectUri' => ( WPSEO_Utils::is_plugin_network_active() ) ? \home_url( 'yoast/oauth/callback' ) : \network_home_url( 'yoast/oauth/callback' ),
|
||||
'urlAuthorize' => 'https://yoast.com/login/oauth/authorize',
|
||||
'urlAccessToken' => 'https://yoast.com/login/oauth/token',
|
||||
'urlResourceOwnerDetails' => 'https://my.yoast.com/api/sites/current',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the access tokens.
|
||||
*
|
||||
* @param array $access_tokens The access tokens to format.
|
||||
*
|
||||
* @return \YoastSEO_Vendor\League\OAuth2\Client\Token\AccessTokenInterface[] The formatted access tokens.
|
||||
*/
|
||||
protected function format_access_tokens( $access_tokens ) {
|
||||
if ( ! \is_array( $access_tokens ) || $access_tokens === [] ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$formatted_access_tokens = [];
|
||||
foreach ( $access_tokens as $user_id => $access_token ) {
|
||||
$formatted_access_tokens[ $user_id ] = new AccessToken( $access_token );
|
||||
}
|
||||
|
||||
return $formatted_access_tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the myyoast oauth value from the options.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_option() {
|
||||
$option_value = WPSEO_Options::get( 'myyoast_oauth', false );
|
||||
|
||||
if ( $option_value ) {
|
||||
return \wp_parse_args(
|
||||
\json_decode( $option_value, true ),
|
||||
$this->get_default_option()
|
||||
);
|
||||
}
|
||||
|
||||
return $this->get_default_option();
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the settings to the options.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function update_option() {
|
||||
WPSEO_Options::set(
|
||||
'myyoast_oauth',
|
||||
WPSEO_Utils::format_json_encode(
|
||||
[
|
||||
'config' => $this->config,
|
||||
'access_tokens' => $this->access_tokens,
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the default option value.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return array The default option value.
|
||||
*/
|
||||
protected function get_default_option() {
|
||||
return [
|
||||
'config' => [
|
||||
'clientId' => null,
|
||||
'secret' => null,
|
||||
],
|
||||
'access_tokens' => [],
|
||||
];
|
||||
}
|
||||
}
|
||||
709
wp-content/plugins/wordpress-seo/src/orm/yoast-model.php
Normal file
709
wp-content/plugins/wordpress-seo/src/orm/yoast-model.php
Normal file
@@ -0,0 +1,709 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the Model class.
|
||||
*
|
||||
* @package Yoast\YoastSEO\ORM
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\ORM;
|
||||
|
||||
use Yoast\WP\SEO\Exceptions\Missing_Method;
|
||||
|
||||
/**
|
||||
* Make Model compatible with WordPress.
|
||||
*
|
||||
* Model base class. Your model objects should extend
|
||||
* this class. A minimal subclass would look like:
|
||||
*
|
||||
* class Widget extends Model {
|
||||
* }
|
||||
*
|
||||
* The methods documented below are magic methods that conform to PSR-1.
|
||||
* This documentation exposes these methods to doc generators and IDEs.
|
||||
*
|
||||
* @link http://www.php-fig.org/psr/psr-1/
|
||||
*
|
||||
* @method void setOrm($orm)
|
||||
* @method $this setExpr($property, $value = null)
|
||||
* @method bool isDirty($property)
|
||||
* @method bool isNew()
|
||||
* @method Array asArray()
|
||||
*/
|
||||
class Yoast_Model {
|
||||
|
||||
/**
|
||||
* Default ID column for all models. Can be overridden by adding
|
||||
* a public static $id_column property to your model classes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DEFAULT_ID_COLUMN = 'id';
|
||||
|
||||
/**
|
||||
* Default foreign key suffix used by relationship methods.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const DEFAULT_FOREIGN_KEY_SUFFIX = '_id';
|
||||
|
||||
/**
|
||||
* Set a prefix for model names. This can be a namespace or any other
|
||||
* abitrary prefix such as the PEAR naming convention.
|
||||
*
|
||||
* @example Model::$auto_prefix_models = 'MyProject_MyModels_'; //PEAR
|
||||
* @example Model::$auto_prefix_models = '\MyProject\MyModels\'; //Namespaces
|
||||
*
|
||||
* @var string $auto_prefix_models
|
||||
*/
|
||||
public static $auto_prefix_models = '\Yoast\WP\SEO\Models\\';
|
||||
|
||||
/**
|
||||
* Set a logger to use for all models.
|
||||
*
|
||||
* @var \YoastSEO_Vendor\Psr\Log\LoggerInterface $logger
|
||||
*/
|
||||
public static $logger;
|
||||
|
||||
/**
|
||||
* Set true to to ignore namespace information when computing table names
|
||||
* from class names.
|
||||
*
|
||||
* @example Model::$short_table_names = true;
|
||||
* @example Model::$short_table_names = false; // default
|
||||
*
|
||||
* @var bool $short_table_names
|
||||
*/
|
||||
public static $short_table_names = false;
|
||||
|
||||
/**
|
||||
* The ORM instance used by this model instance to communicate with the database.
|
||||
*
|
||||
* @var \YoastSEO_Vendor\ORM $orm
|
||||
*/
|
||||
public $orm;
|
||||
|
||||
/**
|
||||
* The table name for the implemented Model.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $table;
|
||||
|
||||
/**
|
||||
* Whether or not this model uses timestamps.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $uses_timestamps = false;
|
||||
|
||||
/**
|
||||
* Hacks around the Model to provide WordPress prefix to tables.
|
||||
*
|
||||
* @param string $class_name Type of Model to load.
|
||||
* @param bool $yoast_prefix Optional. True to prefix the table name with the Yoast prefix.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper Wrapper to use.
|
||||
*/
|
||||
public static function of_type( $class_name, $yoast_prefix = true ) {
|
||||
// Prepend namespace to the class name.
|
||||
$class = static::$auto_prefix_models . $class_name;
|
||||
|
||||
// Set the class variable to the custom value based on the WPDB prefix.
|
||||
$class::$table = static::get_table_name( $class_name, $yoast_prefix );
|
||||
|
||||
return static::factory( $class_name, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a model without the Yoast prefix.
|
||||
*
|
||||
* @param string $class_name Type of Model to load.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper
|
||||
*/
|
||||
public static function of_wp_type( $class_name ) {
|
||||
return static::of_type( $class_name, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes method to get the table name to use.
|
||||
*
|
||||
* @param string $table_name Simple table name.
|
||||
* @param bool $yoast_prefix Optional. True to prefix the table name with the Yoast prefix.
|
||||
*
|
||||
* @return string Prepared full table name.
|
||||
*/
|
||||
public static function get_table_name( $table_name, $yoast_prefix = true ) {
|
||||
global $wpdb;
|
||||
|
||||
// Allow the use of WordPress internal tables.
|
||||
if ( $yoast_prefix ) {
|
||||
$table_name = 'yoast_' . $table_name;
|
||||
}
|
||||
|
||||
return $wpdb->prefix . \strtolower( $table_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the table name for the given class name.
|
||||
*
|
||||
* @param string $class_name The class to set the table name for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function set_table_name( $class_name ) {
|
||||
// Prepend namespace to the class name.
|
||||
$class = static::$auto_prefix_models . $class_name;
|
||||
|
||||
$class::$table = static::get_table_name( $class_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the value of a static property on a class. If the
|
||||
* class or the property does not exist, returns the default
|
||||
* value supplied as the third argument (which defaults to null).
|
||||
*
|
||||
* @param string $class_name The target class name.
|
||||
* @param string $property The property to get the value for.
|
||||
* @param null|string $default Default value when property does not exist.
|
||||
*
|
||||
* @return string The value of the property.
|
||||
*/
|
||||
protected static function get_static_property( $class_name, $property, $default = null ) {
|
||||
if ( ! \class_exists( $class_name ) || ! \property_exists( $class_name, $property ) ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$properties = \get_class_vars( $class_name );
|
||||
|
||||
return $properties[ $property ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Static method to get a table name given a class name.
|
||||
* If the supplied class has a public static property
|
||||
* named $table, the value of this property will be
|
||||
* returned.
|
||||
*
|
||||
* If not, the class name will be converted using
|
||||
* the class_name_to_table_name() method.
|
||||
*
|
||||
* If Model::$short_table_names == true or public static
|
||||
* property $table_use_short_name == true then $class_name passed
|
||||
* to class_name_to_table_name() is stripped of namespace information.
|
||||
*
|
||||
* @param string $class_name The class name to get the table name for.
|
||||
*
|
||||
* @return string The table name.
|
||||
*/
|
||||
protected static function get_table_name_for_class( $class_name ) {
|
||||
$specified_table_name = static::get_static_property( $class_name, 'table' );
|
||||
$use_short_class_name = static::use_short_table_name( $class_name );
|
||||
if ( $use_short_class_name ) {
|
||||
$exploded_class_name = \explode( '\\', $class_name );
|
||||
$class_name = \end( $exploded_class_name );
|
||||
}
|
||||
|
||||
if ( $specified_table_name === null ) {
|
||||
return static::class_name_to_table_name( $class_name );
|
||||
}
|
||||
|
||||
return $specified_table_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should short table names, disregarding class namespaces, be computed?
|
||||
*
|
||||
* $class_property overrides $global_option, unless $class_property is null.
|
||||
*
|
||||
* @param string $class_name The class name to get short name for.
|
||||
*
|
||||
* @return bool True when short table name should be used.
|
||||
*/
|
||||
protected static function use_short_table_name( $class_name ) {
|
||||
$class_property = static::get_static_property( $class_name, 'table_use_short_name' );
|
||||
|
||||
if ( $class_property === null ) {
|
||||
return static::$short_table_names;
|
||||
}
|
||||
|
||||
return $class_property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a namespace to the standard PEAR underscore format.
|
||||
*
|
||||
* Then convert a class name in CapWords to a table name in
|
||||
* lowercase_with_underscores.
|
||||
*
|
||||
* Finally strip doubled up underscores.
|
||||
*
|
||||
* For example, CarTyre would be converted to car_tyre. And
|
||||
* Project\Models\CarTyre would be project_models_car_tyre.
|
||||
*
|
||||
* @param string $class_name The class name to get the table name for.
|
||||
*
|
||||
* @return string The table name.
|
||||
*/
|
||||
protected static function class_name_to_table_name( $class_name ) {
|
||||
$find = [
|
||||
'/\\\\/',
|
||||
'/(?<=[a-z])([A-Z])/',
|
||||
'/__/',
|
||||
];
|
||||
$replacements = [
|
||||
'_',
|
||||
'_$1',
|
||||
'_',
|
||||
];
|
||||
|
||||
$class_name = \ltrim( $class_name, '\\' );
|
||||
$class_name = \preg_replace( $find, $replacements, $class_name );
|
||||
return \strtolower( $class_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ID column name to use for this class. If it is
|
||||
* not set on the class, returns null.
|
||||
*
|
||||
* @param string $class_name The class name to get the ID column for.
|
||||
*
|
||||
* @return string|null The ID column name.
|
||||
*/
|
||||
protected static function get_id_column_name( $class_name ) {
|
||||
return static::get_static_property( $class_name, 'id_column', static::DEFAULT_ID_COLUMN );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a foreign key based on a table name. If the first argument
|
||||
* (the specified foreign key column name) is null, returns the second
|
||||
* argument (the name of the table) with the default foreign key column
|
||||
* suffix appended.
|
||||
*
|
||||
* @param string $specified_foreign_key_name The keyname to build.
|
||||
* @param string $table_name The table name to build the key name for.
|
||||
*
|
||||
* @return string The built foreign key name.
|
||||
*/
|
||||
protected static function build_foreign_key_name( $specified_foreign_key_name, $table_name ) {
|
||||
if ( $specified_foreign_key_name !== null ) {
|
||||
return $specified_foreign_key_name;
|
||||
}
|
||||
|
||||
return $table_name . static::DEFAULT_FOREIGN_KEY_SUFFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method used to acquire instances of the given class.
|
||||
* The class name should be supplied as a string, and the class
|
||||
* should already have been loaded by PHP (or a suitable autoloader
|
||||
* should exist). This method actually returns a wrapped ORM object
|
||||
* which allows a database query to be built. The wrapped ORM object is
|
||||
* responsible for returning instances of the correct class when
|
||||
* its find_one or find_many methods are called.
|
||||
*
|
||||
* @param string $class_name The target class name.
|
||||
* @param null|string $connection_name The name of the connection.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM wrapper.
|
||||
*/
|
||||
public static function factory( $class_name, $connection_name = null ) {
|
||||
$class_name = static::$auto_prefix_models . $class_name;
|
||||
$table_name = static::get_table_name_for_class( $class_name );
|
||||
if ( $connection_name === null ) {
|
||||
$connection_name = static::get_static_property( $class_name, '_connection_name', ORMWrapper::DEFAULT_CONNECTION );
|
||||
}
|
||||
$wrapper = ORMWrapper::for_table( $table_name, $connection_name );
|
||||
$wrapper->set_class_name( $class_name );
|
||||
$wrapper->use_id_column( static::get_id_column_name( $class_name ) );
|
||||
|
||||
return $wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to construct the queries for both the has_one and
|
||||
* has_many methods. These two types of association are identical; the
|
||||
* only difference is whether find_one or find_many is used to complete
|
||||
* the method chain.
|
||||
*
|
||||
* @param string $associated_class_name The associated class name.
|
||||
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
||||
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
||||
* @param null|string $connection_name The name of the connection.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper
|
||||
* @throws \Exception When ID of current model has a null value.
|
||||
*/
|
||||
protected function has_one_or_many( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null, $connection_name = null ) {
|
||||
$base_table_name = static::get_table_name_for_class( \get_class( $this ) );
|
||||
$foreign_key_name = static::build_foreign_key_name( $foreign_key_name, $base_table_name );
|
||||
|
||||
/*
|
||||
* Value of foreign_table.{$foreign_key_name} we're looking for. Where foreign_table is the actual
|
||||
* database table in the associated model.
|
||||
*/
|
||||
if ( $foreign_key_name_in_current_models_table === null ) {
|
||||
// Matches foreign_table.{$foreign_key_name} with the value of "{$this->table}.{$this->id()}".
|
||||
$where_value = $this->id();
|
||||
}
|
||||
else {
|
||||
// Matches foreign_table.{$foreign_key_name} with "{$this->table}.{$foreign_key_name_in_current_models_table}".
|
||||
$where_value = $this->{$foreign_key_name_in_current_models_table};
|
||||
}
|
||||
|
||||
return static::factory( $associated_class_name, $connection_name )->where( $foreign_key_name, $where_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to manage one-to-one relations where the foreign
|
||||
* key is on the associated table.
|
||||
*
|
||||
* @param string $associated_class_name The associated class name.
|
||||
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
||||
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
||||
* @param null|string $connection_name The name of the connection.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM.
|
||||
* @throws \Exception When ID of current model has a null value.
|
||||
*/
|
||||
protected function has_one( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null, $connection_name = null ) {
|
||||
return $this->has_one_or_many( $associated_class_name, $foreign_key_name, $foreign_key_name_in_current_models_table, $connection_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to manage one-to-many relations where the foreign
|
||||
* key is on the associated table.
|
||||
*
|
||||
* @param string $associated_class_name The associated class name.
|
||||
* @param null|string $foreign_key_name The foreign key name in the associated table.
|
||||
* @param null|string $foreign_key_name_in_current_models_table The foreign key in the current models table.
|
||||
* @param null|string $connection_name The name of the connection.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM.
|
||||
* @throws \Exception When ID has a null value.
|
||||
*/
|
||||
protected function has_many( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_current_models_table = null, $connection_name = null ) {
|
||||
$this->set_table_name( $associated_class_name );
|
||||
|
||||
return $this->has_one_or_many( $associated_class_name, $foreign_key_name, $foreign_key_name_in_current_models_table, $connection_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to manage one-to-one and one-to-many relations where
|
||||
* the foreign key is on the base table.
|
||||
*
|
||||
* @param string $associated_class_name The associated class name.
|
||||
* @param null|string $foreign_key_name The foreign key in the current models table.
|
||||
* @param null|string $foreign_key_name_in_associated_models_table The foreign key in the associated table.
|
||||
* @param null|string $connection_name The name of the connection.
|
||||
*
|
||||
* @return $this|null Instance of the foreign model.
|
||||
*/
|
||||
protected function belongs_to( $associated_class_name, $foreign_key_name = null, $foreign_key_name_in_associated_models_table = null, $connection_name = null ) {
|
||||
$this->set_table_name( $associated_class_name );
|
||||
|
||||
$associated_table_name = static::get_table_name_for_class( static::$auto_prefix_models . $associated_class_name );
|
||||
$foreign_key_name = static::build_foreign_key_name( $foreign_key_name, $associated_table_name );
|
||||
$associated_object_id = $this->{$foreign_key_name};
|
||||
$desired_record = null;
|
||||
if ( $foreign_key_name_in_associated_models_table === null ) {
|
||||
/*
|
||||
* Comparison: "{$associated_table_name}.primary_key = {$associated_object_id}".
|
||||
*
|
||||
* NOTE: primary_key is a placeholder for the actual primary key column's name in $associated_table_name.
|
||||
*/
|
||||
return static::factory( $associated_class_name, $connection_name )->where_id_is( $associated_object_id );
|
||||
}
|
||||
|
||||
// Comparison: "{$associated_table_name}.{$foreign_key_name_in_associated_models_table} = {$associated_object_id}".
|
||||
return static::factory( $associated_class_name, $connection_name )->where( $foreign_key_name_in_associated_models_table, $associated_object_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to manage many-to-many relationships via an intermediate model. See
|
||||
* README for a full explanation of the parameters.
|
||||
*
|
||||
* @param string $associated_class_name The associated class name.
|
||||
* @param null|string $join_class_name The class name to join.
|
||||
* @param null|string $key_to_base_table The key to the the current models table.
|
||||
* @param null|string $key_to_associated_table The key to the associated table.
|
||||
* @param null|string $key_in_base_table The key in the current models table.
|
||||
* @param null|string $key_in_associated_table The key in the associated table.
|
||||
* @param null|string $connection_name The name of the connection.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM.
|
||||
*/
|
||||
protected function has_many_through( $associated_class_name, $join_class_name = null, $key_to_base_table = null, $key_to_associated_table = null, $key_in_base_table = null, $key_in_associated_table = null, $connection_name = null ) {
|
||||
$base_class_name = \get_class( $this );
|
||||
|
||||
/*
|
||||
* The class name of the join model, if not supplied, is formed by
|
||||
* concatenating the names of the base class and the associated class,
|
||||
* in alphabetical order.
|
||||
*/
|
||||
if ( $join_class_name === null ) {
|
||||
$base_model = \explode( '\\', $base_class_name );
|
||||
$base_model_name = \end( $base_model );
|
||||
if ( \strpos( $base_model_name, static::$auto_prefix_models ) === 0 ) {
|
||||
$base_model_name = \substr( $base_model_name, \strlen( static::$auto_prefix_models ), \strlen( $base_model_name ) );
|
||||
}
|
||||
// Paris wasn't checking the name settings for the associated class.
|
||||
$associated_model = \explode( '\\', $associated_class_name );
|
||||
$associated_model_name = \end( $associated_model );
|
||||
if ( \strpos( $associated_model_name, static::$auto_prefix_models ) === 0 ) {
|
||||
$associated_model_name = \substr( $associated_model_name, \strlen( static::$auto_prefix_models ), \strlen( $associated_model_name ) );
|
||||
}
|
||||
$class_names = [ $base_model_name, $associated_model_name ];
|
||||
\sort( $class_names, \SORT_STRING );
|
||||
$join_class_name = \implode( '', $class_names );
|
||||
}
|
||||
|
||||
// Get table names for each class.
|
||||
$base_table_name = static::get_table_name_for_class( $base_class_name );
|
||||
$associated_table_name = static::get_table_name_for_class( static::$auto_prefix_models . $associated_class_name );
|
||||
$join_table_name = static::get_table_name_for_class( static::$auto_prefix_models . $join_class_name );
|
||||
|
||||
// Get ID column names.
|
||||
$base_table_id_column = ( $key_in_base_table === null ) ? static::get_id_column_name( $base_class_name ) : $key_in_base_table;
|
||||
$associated_table_id_column = ( $key_in_associated_table === null ) ? static::get_id_column_name( static::$auto_prefix_models . $associated_class_name ) : $key_in_associated_table;
|
||||
|
||||
// Get the column names for each side of the join table.
|
||||
$key_to_base_table = static::build_foreign_key_name( $key_to_base_table, $base_table_name );
|
||||
$key_to_associated_table = static::build_foreign_key_name( $key_to_associated_table, $associated_table_name );
|
||||
|
||||
/*
|
||||
" SELECT {$associated_table_name}.*
|
||||
FROM {$associated_table_name} JOIN {$join_table_name}
|
||||
ON {$associated_table_name}.{$associated_table_id_column} = {$join_table_name}.{$key_to_associated_table}
|
||||
WHERE {$join_table_name}.{$key_to_base_table} = {$this->$base_table_id_column} ;"
|
||||
*/
|
||||
return static::factory( $associated_class_name, $connection_name )
|
||||
->select( "{$associated_table_name}.*" )
|
||||
->join(
|
||||
$join_table_name,
|
||||
[
|
||||
"{$associated_table_name}.{$associated_table_id_column}",
|
||||
'=',
|
||||
"{$join_table_name}.{$key_to_associated_table}",
|
||||
]
|
||||
)
|
||||
->where( "{$join_table_name}.{$key_to_base_table}", $this->{$base_table_id_column} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the wrapped ORM instance associated with this Model instance.
|
||||
*
|
||||
* @param \YoastSEO_Vendor\ORM $orm The ORM instance to set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_orm( $orm ) {
|
||||
$this->orm = $orm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter method, allows $model->property access to data.
|
||||
*
|
||||
* @param string $property The property to get.
|
||||
*
|
||||
* @return null|string The value of the property
|
||||
*/
|
||||
public function __get( $property ) {
|
||||
return $this->orm->get( $property );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic setter method, allows $model->property = 'value' access to data.
|
||||
*
|
||||
* @param string $property The property to set.
|
||||
* @param string $value The value to set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __set( $property, $value ) {
|
||||
$this->orm->set( $property, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic unset method, allows unset($model->property)
|
||||
*
|
||||
* @param string $property The property to unset.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __unset( $property ) {
|
||||
$this->orm->__unset( $property );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic isset method, allows isset($model->property) to work correctly.
|
||||
*
|
||||
* @param string $property The property to check.
|
||||
*
|
||||
* @return bool True when value is set.
|
||||
*/
|
||||
public function __isset( $property ) {
|
||||
return $this->orm->__isset( $property );
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter method, allows $model->get('property') access to data
|
||||
*
|
||||
* @param string $property The property to get.
|
||||
*
|
||||
* @return string The value of a property.
|
||||
*/
|
||||
public function get( $property ) {
|
||||
return $this->orm->get( $property );
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter method, allows $model->set('property', 'value') access to data.
|
||||
*
|
||||
* @param string|array $property The property to set.
|
||||
* @param string|null $value The value to give.
|
||||
*
|
||||
* @return static Current object.
|
||||
*/
|
||||
public function set( $property, $value = null ) {
|
||||
$this->orm->set( $property, $value );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter method, allows $model->set_expr('property', 'value') access to data.
|
||||
*
|
||||
* @param string|array $property The property to set.
|
||||
* @param string|null $value The value to give.
|
||||
*
|
||||
* @return static Current object.
|
||||
*/
|
||||
public function set_expr( $property, $value = null ) {
|
||||
$this->orm->set_expr( $property, $value );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given property has changed since the object was created or saved.
|
||||
*
|
||||
* @param string $property The property to check.
|
||||
*
|
||||
* @return bool True when field is changed.
|
||||
*/
|
||||
public function is_dirty( $property ) {
|
||||
return $this->orm->is_dirty( $property );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the model was the result of a call to create() or not.
|
||||
*
|
||||
* @return bool True when is new.
|
||||
*/
|
||||
public function is_new() {
|
||||
return $this->orm->is_new();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for Idiorm's as_array method.
|
||||
*
|
||||
* @return array The models data as array.
|
||||
*/
|
||||
public function as_array() {
|
||||
$args = \func_get_args();
|
||||
|
||||
return \call_user_func_array( [ $this->orm, 'as_array' ], $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the data associated with this model instance to the database.
|
||||
*
|
||||
* @return null Nothing.
|
||||
*/
|
||||
public function save() {
|
||||
if ( $this->uses_timestamps ) {
|
||||
if ( ! $this->created_at ) {
|
||||
$this->created_at = \gmdate( 'Y-m-d H:i:s' );
|
||||
}
|
||||
$this->updated_at = \gmdate( 'Y-m-d H:i:s' );
|
||||
}
|
||||
|
||||
return $this->orm->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the database row associated with this model instance.
|
||||
*
|
||||
* @return null Nothing.
|
||||
*/
|
||||
public function delete() {
|
||||
return $this->orm->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the database ID of this model instance.
|
||||
*
|
||||
* @return int The database ID of the models instance.
|
||||
* @throws \Exception When the ID is a null value.
|
||||
*/
|
||||
public function id() {
|
||||
return $this->orm->id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate this model instance with an associative array of data.
|
||||
* WARNING: The keys in the array MUST match with columns in the
|
||||
* corresponding database table. If any keys are supplied which
|
||||
* do not match up with columns, the database will throw an error.
|
||||
*
|
||||
* @param array $data The data to pass to the ORM.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function hydrate( $data ) {
|
||||
$this->orm->hydrate( $data )->force_all_dirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls static methods directly on the ORMWrapper
|
||||
*
|
||||
* @param string $method The method to call.
|
||||
* @param array $arguments The arguments to use.
|
||||
*
|
||||
* @return array Result of the static call.
|
||||
*/
|
||||
public static function __callStatic( $method, $arguments ) {
|
||||
if ( ! \function_exists( 'get_called_class' ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$model = static::factory( \get_called_class() );
|
||||
|
||||
return \call_user_func_array( [ $model, $method ], $arguments );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to capture calls to undefined class methods.
|
||||
* In this case we are attempting to convert camel case formatted
|
||||
* methods into underscore formatted methods.
|
||||
*
|
||||
* This allows us to call methods using camel case and remain
|
||||
* backwards compatible.
|
||||
*
|
||||
* @param string $name The method to call.
|
||||
* @param array $arguments The arguments to use.
|
||||
*
|
||||
* @throws \Yoast\WP\SEO\Exceptions\Missing_Method When the method does not exist.
|
||||
*
|
||||
* @return bool|\Yoast\WP\SEO\ORMWrapper Result of the call.
|
||||
*/
|
||||
public function __call( $name, $arguments ) {
|
||||
$method = \strtolower( \preg_replace( '/([a-z])([A-Z])/', '$1_$2', $name ) );
|
||||
if ( ! \method_exists( $this, $method ) ) {
|
||||
throw Missing_Method::for_class( \get_class( $this ), $name );
|
||||
}
|
||||
|
||||
return \call_user_func_array( [ $this, $method ], $arguments );
|
||||
}
|
||||
}
|
||||
165
wp-content/plugins/wordpress-seo/src/orm/yoast-orm-wrapper.php
Normal file
165
wp-content/plugins/wordpress-seo/src/orm/yoast-orm-wrapper.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the ORM class.
|
||||
*
|
||||
* @package Yoast\YoastSEO
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\ORM;
|
||||
|
||||
use YoastSEO_Vendor\ORM;
|
||||
|
||||
/**
|
||||
* Subclass of Idiorm's ORM class that supports
|
||||
* returning instances of a specified class rather
|
||||
* than raw instances of the ORM class.
|
||||
*
|
||||
* You shouldn't need to interact with this class
|
||||
* directly. It is used internally by the Model base
|
||||
* class.
|
||||
*
|
||||
* The methods documented below are magic methods that conform to PSR-1.
|
||||
* This documentation exposes these methods to doc generators and IDEs.
|
||||
*
|
||||
* @link http://www.php-fig.org/psr/psr-1/
|
||||
*
|
||||
* @method void setClassName($class_name)
|
||||
* @method static \Yoast\WP\SEO\ORM\ORMWrapper forTable($table_name, $connection_name = parent::DEFAULT_CONNECTION)
|
||||
* @method \Yoast\WP\SEO\ORM\\Model findOne($id=null)
|
||||
* @method Array|\IdiormResultSet findMany()
|
||||
*/
|
||||
class ORMWrapper extends ORM {
|
||||
|
||||
/**
|
||||
* Contains the repositories.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $repositories = [];
|
||||
|
||||
/**
|
||||
* The wrapped find_one and find_many classes will return an instance or
|
||||
* instances of this class.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $class_name;
|
||||
|
||||
/**
|
||||
* Set the name of the class which the wrapped methods should return
|
||||
* instances of.
|
||||
*
|
||||
* @param string $class_name The classname to set.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_class_name( $class_name ) {
|
||||
$this->class_name = $class_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom filter to the method chain specified on the model class.
|
||||
* This allows custom queries to be added to models. The filter should take
|
||||
* an instance of the ORM wrapper as its first argument and return an
|
||||
* instance of the ORM wrapper. Any arguments passed to this method after
|
||||
* the name of the filter will be passed to the called filter function as
|
||||
* arguments after the ORM class.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM wrapper.
|
||||
*/
|
||||
public function filter() {
|
||||
$args = \func_get_args();
|
||||
$filter_function = \array_shift( $args );
|
||||
\array_unshift( $args, $this );
|
||||
if ( \method_exists( $this->class_name, $filter_function ) ) {
|
||||
return \call_user_func_array( [ $this->class_name, $filter_function ], $args );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method, return an instance of this class bound to the supplied
|
||||
* table name.
|
||||
*
|
||||
* A repeat of content in parent::for_table, so that created class is
|
||||
* ORMWrapper, not ORM.
|
||||
*
|
||||
* @param string $table_name The table to create instance for.
|
||||
* @param string $connection_name The connection name.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\ORMWrapper Instance of the ORM wrapper.
|
||||
*/
|
||||
public static function for_table( $table_name, $connection_name = parent::DEFAULT_CONNECTION ) {
|
||||
static::_setup_db( $connection_name );
|
||||
|
||||
if ( self::$repositories[ $table_name ] ) {
|
||||
return new self::$repositories[ $table_name ]( $table_name, [], $connection_name );
|
||||
}
|
||||
|
||||
return new static( $table_name, [], $connection_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create an instance of the model class associated with this
|
||||
* wrapper and populate it with the supplied Idiorm instance.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\ORM\ORMWrapper|\YoastSEO_Vendor\ORM $orm The ORM used by model.
|
||||
*
|
||||
* @return bool|\Yoast\WP\SEO\ORM\Yoast_Model Instance of the model class.
|
||||
*/
|
||||
protected function create_model_instance( $orm ) {
|
||||
if ( $orm === false ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of Yoast_Model is being made.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\ORM\Yoast_Model $model
|
||||
*/
|
||||
$model = new $this->class_name();
|
||||
$model->set_orm( $orm );
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap Idiorm's find_one method to return an instance of the class
|
||||
* associated with this wrapper instead of the raw ORM class.
|
||||
*
|
||||
* @param null|integer $id The ID to lookup.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\Yoast_Model Instance of the model.
|
||||
*/
|
||||
public function find_one( $id = null ) {
|
||||
return $this->create_model_instance( parent::find_one( $id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap Idiorm's find_many method to return an array of instances of the
|
||||
* class associated with this wrapper instead of the raw ORM class.
|
||||
*
|
||||
* @return array The found results.
|
||||
*/
|
||||
public function find_many() {
|
||||
$results = parent::find_many();
|
||||
foreach ( $results as $key => $result ) {
|
||||
$results[ $key ] = $this->create_model_instance( $result );
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap Idiorm's create method to return an empty instance of the class
|
||||
* associated with this wrapper instead of the raw ORM class.
|
||||
*
|
||||
* @param null|mixed $data The data to pass.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\ORM\Yoast_Model|bool Instance of the ORM.
|
||||
*/
|
||||
public function create( $data = null ) {
|
||||
return $this->create_model_instance( parent::create( $data ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the Model class.
|
||||
*
|
||||
* @package Yoast\YoastSEO\ORM\Repositories
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Repositories;
|
||||
|
||||
use Yoast\WP\SEO\Builders\Indexable_Author_Builder;
|
||||
use Yoast\WP\SEO\Builders\Indexable_Post_Builder;
|
||||
use Yoast\WP\SEO\Builders\Indexable_Term_Builder;
|
||||
use Yoast\WP\SEO\Loggers\Logger;
|
||||
use Yoast\WP\SEO\ORM\ORMWrapper;
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Class Indexable_Repository
|
||||
*
|
||||
* @package Yoast\WP\SEO\ORM\Repositories
|
||||
*/
|
||||
class Indexable_Repository extends ORMWrapper {
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Builders\Indexable_Author_Builder
|
||||
*/
|
||||
protected $author_builder;
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Builders\Indexable_Post_Builder
|
||||
*/
|
||||
protected $post_builder;
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Builders\Indexable_Term_Builder
|
||||
*/
|
||||
protected $term_builder;
|
||||
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* Returns the instance of this class constructed through the ORM Wrapper.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Builders\Indexable_Author_Builder $author_builder The author builder for creating missing indexables.
|
||||
* @param \Yoast\WP\SEO\Builders\Indexable_Post_Builder $post_builder The post builder for creating missing indexables.
|
||||
* @param \Yoast\WP\SEO\Builders\Indexable_Term_Builder $term_builder The term builder for creating missing indexables.
|
||||
* @param \Yoast\WP\SEO\Loggers\Logger $logger The logger.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\Indexable_Repository
|
||||
*/
|
||||
public static function get_instance(
|
||||
Indexable_Author_Builder $author_builder,
|
||||
Indexable_Post_Builder $post_builder,
|
||||
Indexable_Term_Builder $term_builder,
|
||||
Logger $logger
|
||||
) {
|
||||
ORMWrapper::$repositories[ Yoast_Model::get_table_name( 'Indexable' ) ] = self::class;
|
||||
|
||||
/**
|
||||
* @var $instance self
|
||||
*/
|
||||
$instance = Yoast_Model::of_type( 'Indexable' );
|
||||
$instance->author_builder = $author_builder;
|
||||
$instance->post_builder = $post_builder;
|
||||
$instance->term_builder = $term_builder;
|
||||
$instance->logger = $logger;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an indexable by it's URL.
|
||||
*
|
||||
* @param string $url The indexable url.
|
||||
*/
|
||||
public function find_by_url( $url ) {
|
||||
$url = \trailingslashit( $url );
|
||||
$url_hash = \strlen( $url ) . ':' . \md5( $url );
|
||||
|
||||
// Find by both url_hash and url, url_hash is indexed so will be used first by the DB to optimize the query.
|
||||
return $this->where( 'url_hash', $url_hash )
|
||||
->where( 'url', $url )
|
||||
->find_one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an indexable by its ID and type.
|
||||
*
|
||||
* @param int $object_id The indexable object ID.
|
||||
* @param string $object_type The indexable object type.
|
||||
* @param bool $auto_create Optional. Create the indexable if it does not exist.
|
||||
*
|
||||
* @return bool|\Yoast\WP\SEO\Models\Indexable Instance of indexable.
|
||||
*/
|
||||
public function find_by_id_and_type( $object_id, $object_type, $auto_create = true ) {
|
||||
$indexable = $this->where( 'object_id', $object_id )
|
||||
->where( 'object_type', $object_type )
|
||||
->find_one();
|
||||
|
||||
if ( $auto_create && ! $indexable ) {
|
||||
$indexable = $this->create_for_id_and_type( $object_id, $object_type );
|
||||
}
|
||||
|
||||
return $indexable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves multiple indexables at once by their IDs and type.
|
||||
*
|
||||
* @param int[] $object_ids The array of indexable object IDs.
|
||||
* @param string $object_type The indexable object type.
|
||||
* @param bool $auto_create Optional. Create the indexable if it does not exist.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\Indexable[] An array of indexables.
|
||||
*/
|
||||
public function find_by_multiple_ids_and_type( $object_ids, $object_type, $auto_create = true ) {
|
||||
$indexables = $this
|
||||
->where_in( 'object_id', $object_ids )
|
||||
->where( 'object_type', $object_type )
|
||||
->find_many();
|
||||
|
||||
if ( $auto_create ) {
|
||||
$indexables_available = \array_column( $indexables, 'object_id' );
|
||||
$indexables_to_create = \array_diff( $object_ids, $indexables_available );
|
||||
|
||||
foreach ( $indexables_to_create as $indexable_to_create ) {
|
||||
$indexable = $this->create_for_id_and_type( $indexable_to_create, $object_type );
|
||||
$indexable->save();
|
||||
|
||||
$indexables[] = $indexable;
|
||||
}
|
||||
}
|
||||
|
||||
return $indexables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an indexable by its ID and type.
|
||||
*
|
||||
* @param int $object_id The indexable object ID.
|
||||
* @param string $object_type The indexable object type.
|
||||
*
|
||||
* @return bool|\Yoast\WP\SEO\Models\Indexable Instance of indexable.
|
||||
*/
|
||||
public function create_for_id_and_type( $object_id, $object_type ) {
|
||||
/**
|
||||
* Indexable instance.
|
||||
*
|
||||
* @var \Yoast\WP\SEO\Models\Indexable $indexable
|
||||
*/
|
||||
$indexable = $this->create();
|
||||
$indexable->object_id = $object_id;
|
||||
$indexable->object_type = $object_type;
|
||||
|
||||
switch ( $object_type ) {
|
||||
case 'post':
|
||||
$indexable = $this->post_builder->build( $object_id, $indexable );
|
||||
break;
|
||||
case 'user':
|
||||
$indexable = $this->author_builder->build( $object_id, $indexable );
|
||||
break;
|
||||
case 'term':
|
||||
$indexable = $this->term_builder->build( $object_id, $indexable );
|
||||
break;
|
||||
}
|
||||
|
||||
$this->logger->debug(
|
||||
\sprintf(
|
||||
/* translators: 1: object ID; 2: object type. */
|
||||
\__( 'Indexable created for object %1$s with type %2$s', 'wordpress-seo' ),
|
||||
$object_id,
|
||||
$object_type
|
||||
),
|
||||
\get_object_vars( $indexable )
|
||||
);
|
||||
|
||||
return $indexable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the Model class.
|
||||
*
|
||||
* @package Yoast\YoastSEO\ORM\Repositories
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Repositories;
|
||||
|
||||
use Yoast\WP\SEO\ORM\ORMWrapper;
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Class Primary_Term_Repository
|
||||
*
|
||||
* @package Yoast\WP\SEO\ORM\Repositories
|
||||
*/
|
||||
class Primary_Term_Repository extends ORMWrapper {
|
||||
|
||||
/**
|
||||
* Returns the instance of this class constructed through the ORM Wrapper.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\Primary_Term_Repository
|
||||
*/
|
||||
public static function get_instance() {
|
||||
ORMWrapper::$repositories[ Yoast_Model::get_table_name( 'Primary_Term' ) ] = self::class;
|
||||
|
||||
return Yoast_Model::of_type( 'Primary_Term' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an indexable by a post ID and taxonomy.
|
||||
*
|
||||
* @param int $post_id The post the indexable is based upon.
|
||||
* @param string $taxonomy The taxonomy the indexable belongs to.
|
||||
* @param bool $auto_create Optional. Creates an indexable if it does not exist yet.
|
||||
*
|
||||
* @return bool|\Yoast\WP\SEO\Models\Indexable Instance of indexable.
|
||||
*/
|
||||
public function find_by_postid_and_taxonomy( $post_id, $taxonomy, $auto_create = true ) {
|
||||
/** @var \Yoast\WP\SEO\Models\Primary_Term $primary_term */
|
||||
$primary_term = $this->where( 'post_id', $post_id )
|
||||
->where( 'taxonomy', $taxonomy )
|
||||
->find_one();
|
||||
|
||||
if ( $auto_create && ! $primary_term ) {
|
||||
$primary_term = $this->create();
|
||||
}
|
||||
|
||||
return $primary_term;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the Model class.
|
||||
*
|
||||
* @package Yoast\YoastSEO\ORM\Repositories
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Repositories;
|
||||
|
||||
use Yoast\WP\SEO\ORM\ORMWrapper;
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Class SEO_Links_Repository
|
||||
*
|
||||
* WARNING: This class merely exists for type hints and dependency injection.
|
||||
* Instances of this class will actually be instances of ORMWrapper and any functions and/or methods here will not be represented.
|
||||
*
|
||||
* @package Yoast\WP\SEO\ORM\Repositories
|
||||
*/
|
||||
class SEO_Links_Repository extends ORMWrapper {
|
||||
|
||||
/**
|
||||
* Returns the instance of this class constructed through the ORM Wrapper.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\SEO_Links_Repository
|
||||
*/
|
||||
public static function get_instance() {
|
||||
ORMWrapper::$repositories[ Yoast_Model::get_table_name( 'SEO_Links' ) ] = self::class;
|
||||
|
||||
return Yoast_Model::of_type( 'SEO_Links' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast extension of the Model class.
|
||||
*
|
||||
* @package Yoast\YoastSEO\ORM\Repositories
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Repositories;
|
||||
|
||||
use Yoast\WP\SEO\ORM\ORMWrapper;
|
||||
use Yoast\WP\SEO\ORM\Yoast_Model;
|
||||
|
||||
/**
|
||||
* Class SEO_Meta_Repository
|
||||
*
|
||||
* @package Yoast\WP\SEO\ORM\Repositories
|
||||
*/
|
||||
class SEO_Meta_Repository extends ORMWrapper {
|
||||
|
||||
/**
|
||||
* Returns the instance of this class constructed through the ORM Wrapper.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Repositories\SEO_Meta_Repository
|
||||
*/
|
||||
public static function get_instance() {
|
||||
ORMWrapper::$repositories[ Yoast_Model::get_table_name( 'SEO_Meta' ) ] = self::class;
|
||||
|
||||
return Yoast_Model::of_type( 'SEO_Meta' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the SEO meta for given post.
|
||||
*
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return \Yoast\WP\SEO\Models\SEO_Meta The SEO meta.
|
||||
*/
|
||||
public function find_by_post_id( $post_id ) {
|
||||
return $this->where( 'object_id', $post_id )
|
||||
->find_one();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* Author watcher to save the meta data to an Indexable.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Watchers
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Watchers;
|
||||
|
||||
use Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional;
|
||||
use Yoast\WP\SEO\Builders\Indexable_Author_Builder;
|
||||
use Yoast\WP\SEO\Repositories\Indexable_Repository;
|
||||
use Yoast\WP\SEO\WordPress\Integration;
|
||||
|
||||
/**
|
||||
* Watches an Author to save the meta information when updated.
|
||||
*/
|
||||
class Indexable_Author_Watcher implements Integration {
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Repositories\Indexable_Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Builders\Indexable_Author_Builder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Indexables_Feature_Flag_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexable_Author_Watcher constructor.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Repositories\Indexable_Repository $repository The repository to use.
|
||||
* @param \Yoast\WP\SEO\Builders\Indexable_Author_Builder $builder The post builder to use.
|
||||
*/
|
||||
public function __construct( Indexable_Repository $repository, Indexable_Author_Builder $builder ) {
|
||||
$this->repository = $repository;
|
||||
$this->builder = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function register_hooks() {
|
||||
\add_action( 'profile_update', [ $this, 'build_indexable' ], \PHP_INT_MAX );
|
||||
\add_action( 'deleted_user', [ $this, 'delete_indexable' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes user meta.
|
||||
*
|
||||
* @param int $user_id User ID to delete the metadata of.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_indexable( $user_id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $user_id, 'user', false );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$indexable->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves user meta.
|
||||
*
|
||||
* @param int $user_id User ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function build_indexable( $user_id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $user_id, 'user', false );
|
||||
|
||||
// If we haven't found an existing indexable, create it. Otherwise update it.
|
||||
$indexable = ( $indexable === false ) ? $this->repository->create_for_id_and_type( $user_id, 'user' ) : $this->builder->build( $user_id, $indexable );
|
||||
|
||||
$indexable->save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/**
|
||||
* WordPress Post watcher.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Watchers
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Watchers;
|
||||
|
||||
use Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional;
|
||||
use Yoast\WP\SEO\Builders\Indexable_Post_Builder;
|
||||
use Yoast\WP\SEO\Repositories\Indexable_Repository;
|
||||
use Yoast\WP\SEO\WordPress\Integration;
|
||||
|
||||
/**
|
||||
* Fills the Indexable according to Post data.
|
||||
*/
|
||||
class Indexable_Post_Watcher implements Integration {
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Repositories\Indexable_Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Builders\Indexable_Post_Builder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Indexables_Feature_Flag_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexable_Post_Watcher constructor.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Repositories\Indexable_Repository $repository The repository to use.
|
||||
* @param \Yoast\WP\SEO\Builders\Indexable_Post_Builder $builder The post builder to use.
|
||||
*/
|
||||
public function __construct( Indexable_Repository $repository, Indexable_Post_Builder $builder ) {
|
||||
$this->repository = $repository;
|
||||
$this->builder = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function register_hooks() {
|
||||
\add_action( 'wp_insert_post', [ $this, 'build_indexable' ], \PHP_INT_MAX );
|
||||
\add_action( 'delete_post', [ $this, 'delete_indexable' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the meta when a post is deleted.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_indexable( $post_id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $post_id, 'post', false );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$indexable->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves post meta.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function build_indexable( $post_id ) {
|
||||
if ( ! $this->is_post_indexable( $post_id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$indexable = $this->repository->find_by_id_and_type( $post_id, 'post', false );
|
||||
|
||||
// If we haven't found an existing indexable, create it. Otherwise update it.
|
||||
$indexable = ( $indexable === false ) ? $this->repository->create_for_id_and_type( $post_id, 'post' ) : $this->builder->build( $post_id, $indexable );
|
||||
|
||||
$indexable->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the post can be indexed.
|
||||
*
|
||||
* @param int $post_id Post ID to check.
|
||||
*
|
||||
* @return bool True if the post can be indexed.
|
||||
*/
|
||||
protected function is_post_indexable( $post_id ) {
|
||||
if ( \wp_is_post_revision( $post_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( \wp_is_post_autosave( $post_id ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
/**
|
||||
* Term/Taxonomy watcher to fill the related Indexable.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Watchers
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Watchers;
|
||||
|
||||
use Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional;
|
||||
use Yoast\WP\SEO\Builders\Indexable_Term_Builder;
|
||||
use Yoast\WP\SEO\Repositories\Indexable_Repository;
|
||||
use Yoast\WP\SEO\WordPress\Integration;
|
||||
|
||||
/**
|
||||
* Watcher for terms to fill the related Indexable.
|
||||
*/
|
||||
class Indexable_Term_Watcher implements Integration {
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Repositories\Indexable_Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Builders\Indexable_Term_Builder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Indexables_Feature_Flag_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexable_Term_Watcher constructor.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Repositories\Indexable_Repository $repository The repository to use.
|
||||
* @param \Yoast\WP\SEO\Builders\Indexable_Term_Builder $builder The post builder to use.
|
||||
*/
|
||||
public function __construct( Indexable_Repository $repository, Indexable_Term_Builder $builder ) {
|
||||
$this->repository = $repository;
|
||||
$this->builder = $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function register_hooks() {
|
||||
\add_action( 'edited_term', [ $this, 'build_indexable' ], \PHP_INT_MAX );
|
||||
\add_action( 'delete_term', [ $this, 'delete_indexable' ], \PHP_INT_MAX );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a term from the index.
|
||||
*
|
||||
* @param int $term_id The Term ID to delete.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_indexable( $term_id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $term_id, 'term', false );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$indexable->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the taxonomy meta data on save.
|
||||
*
|
||||
* Note: This method is missing functionality to update internal links and incoming links.
|
||||
* As this functionality is currently not available for terms, it has not been added in this
|
||||
* class yet.
|
||||
*
|
||||
* @param int $term_id ID of the term to save data for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function build_indexable( $term_id ) {
|
||||
$indexable = $this->repository->find_by_id_and_type( $term_id, 'term', false );
|
||||
|
||||
// If we haven't found an existing indexable, create it. Otherwise update it.
|
||||
$indexable = ( $indexable === false ) ? $this->repository->create_for_id_and_type( $term_id, 'term' ) : $this->builder->build( $term_id, $indexable );
|
||||
|
||||
$indexable->save();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
/**
|
||||
* Primary Term watcher.
|
||||
*
|
||||
* @package Yoast\YoastSEO\Watchers
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\Watchers;
|
||||
|
||||
use WPSEO_Meta;
|
||||
use Yoast\WP\SEO\Conditionals\Indexables_Feature_Flag_Conditional;
|
||||
use Yoast\WP\SEO\Repositories\Primary_Term_Repository;
|
||||
use Yoast\WP\SEO\WordPress\Integration;
|
||||
|
||||
/**
|
||||
* Watches Posts to save the primary term when set.
|
||||
*/
|
||||
class Primary_Term_Watcher implements Integration {
|
||||
|
||||
/**
|
||||
* @var \Yoast\WP\SEO\Repositories\Primary_Term_Repository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function get_conditionals() {
|
||||
return [ Indexables_Feature_Flag_Conditional::class ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary_Term_Watcher constructor.
|
||||
*
|
||||
* @param \Yoast\WP\SEO\Repositories\Primary_Term_Repository $repository The primary term repository.
|
||||
*/
|
||||
public function __construct( Primary_Term_Repository $repository ) {
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function register_hooks() {
|
||||
\add_action( 'save_post', [ $this, 'save_primary_terms' ] );
|
||||
\add_action( 'delete_post', [ $this, 'delete_primary_terms' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes primary terms for a post.
|
||||
*
|
||||
* @param int $post_id The post to delete the terms of.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function delete_primary_terms( $post_id ) {
|
||||
foreach ( $this->get_primary_term_taxonomies( $post_id ) as $taxonomy ) {
|
||||
$indexable = $this->repository->find_by_postid_and_taxonomy( $post_id, $taxonomy->name, false );
|
||||
|
||||
if ( ! $indexable ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$indexable->delete();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the primary terms for a post.
|
||||
*
|
||||
* @param int $post_id Post ID to save the primary terms for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save_primary_terms( $post_id ) {
|
||||
if ( ! $this->is_post_request() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $this->get_primary_term_taxonomies( $post_id ) as $taxonomy ) {
|
||||
$this->save_primary_term( $post_id, $taxonomy->name );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the primary term for a specific taxonomy.
|
||||
*
|
||||
* @param int $post_id Post ID to save primary term for.
|
||||
* @param string $taxonomy Taxonomy to save primary term for.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function save_primary_term( $post_id, $taxonomy ) {
|
||||
// This request must be valid.
|
||||
$term_id = $this->get_posted_term_id( $taxonomy );
|
||||
if ( $term_id && ! $this->is_referer_valid( $taxonomy ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$term_selected = ! empty( $term_id );
|
||||
$primary_term = $this->repository->find_by_postid_and_taxonomy( $post_id, $taxonomy, $term_selected );
|
||||
|
||||
// Removes the indexable when found.
|
||||
if ( ! $term_selected ) {
|
||||
if ( $primary_term ) {
|
||||
$primary_term->delete();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$primary_term->term_id = $term_id;
|
||||
$primary_term->post_id = $post_id;
|
||||
$primary_term->taxonomy = $taxonomy;
|
||||
$primary_term->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the taxonomies for which the primary term selection is enabled.
|
||||
*
|
||||
* @param int $post_id Default current post ID.
|
||||
*
|
||||
* @return array The taxonomies.
|
||||
*/
|
||||
protected function get_primary_term_taxonomies( $post_id = null ) {
|
||||
if ( $post_id === null ) {
|
||||
$post_id = \get_the_ID();
|
||||
}
|
||||
|
||||
$taxonomies = $this->generate_primary_term_taxonomies( $post_id );
|
||||
|
||||
return $taxonomies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the primary term taxonomies.
|
||||
*
|
||||
* @param int $post_id ID of the post.
|
||||
*
|
||||
* @return array The taxonomies.
|
||||
*/
|
||||
protected function generate_primary_term_taxonomies( $post_id ) {
|
||||
$post_type = \get_post_type( $post_id );
|
||||
$all_taxonomies = \get_object_taxonomies( $post_type, 'objects' );
|
||||
$all_taxonomies = \array_filter( $all_taxonomies, [ $this, 'filter_hierarchical_taxonomies' ] );
|
||||
|
||||
/**
|
||||
* Filters which taxonomies for which the user can choose the primary term.
|
||||
*
|
||||
* @api array $taxonomies An array of taxonomy objects that are primary_term enabled.
|
||||
*
|
||||
* @param string $post_type The post type for which to filter the taxonomies.
|
||||
* @param array $all_taxonomies All taxonomies for this post types, even ones that don't have primary term
|
||||
* enabled.
|
||||
*/
|
||||
$taxonomies = (array) \apply_filters( 'wpseo_primary_term_taxonomies', $all_taxonomies, $post_type, $all_taxonomies );
|
||||
|
||||
return $taxonomies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not a taxonomy is hierarchical
|
||||
*
|
||||
* @param \stdClass $taxonomy Taxonomy object.
|
||||
*
|
||||
* @return bool True for hierarchical taxonomy.
|
||||
*/
|
||||
protected function filter_hierarchical_taxonomies( $taxonomy ) {
|
||||
return (bool) $taxonomy->hierarchical;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the request is a post request.
|
||||
*
|
||||
* @return bool Whether the method is a post request.
|
||||
*/
|
||||
protected function is_post_request() {
|
||||
return isset( $_SERVER['REQUEST_METHOD'] ) && \strtolower( \wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) === 'post';
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the posted term ID based on the given taxonomy.
|
||||
*
|
||||
* @param string $taxonomy The taxonomy to check.
|
||||
*
|
||||
* @return int The term ID.
|
||||
*/
|
||||
protected function get_posted_term_id( $taxonomy ) {
|
||||
return \filter_input( \INPUT_POST, WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy . '_term', \FILTER_SANITIZE_NUMBER_INT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the referer is valid for given taxonomy.
|
||||
*
|
||||
* @param string $taxonomy The taxonomy to validate.
|
||||
*
|
||||
* @return bool Whether the referer is valid.
|
||||
*/
|
||||
protected function is_referer_valid( $taxonomy ) {
|
||||
return \check_admin_referer( 'save-primary-term', WPSEO_Meta::$form_prefix . 'primary_' . $taxonomy . '_nonce' );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration interface definition.
|
||||
*
|
||||
* @package Yoast\YoastSEO\WordPress
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\WordPress;
|
||||
|
||||
/**
|
||||
* An interface for registering integrations with WordPress
|
||||
*/
|
||||
interface Initializer extends Loadable {
|
||||
|
||||
/**
|
||||
* Runs this initializer.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initialize();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration interface definition.
|
||||
*
|
||||
* @package Yoast\YoastSEO\WordPress
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\WordPress;
|
||||
|
||||
/**
|
||||
* An interface for registering integrations with WordPress
|
||||
*/
|
||||
interface Integration extends Loadable {
|
||||
|
||||
/**
|
||||
* Initializes the integration.
|
||||
*
|
||||
* This is the place to register hooks and filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register_hooks();
|
||||
}
|
||||
21
wp-content/plugins/wordpress-seo/src/wordpress/loadable.php
Normal file
21
wp-content/plugins/wordpress-seo/src/wordpress/loadable.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/**
|
||||
* Integration interface definition.
|
||||
*
|
||||
* @package Yoast\YoastSEO\WordPress
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\WordPress;
|
||||
|
||||
/**
|
||||
* An interface for registering integrations with WordPress
|
||||
*/
|
||||
interface Loadable {
|
||||
|
||||
/**
|
||||
* Returns the conditionals based in which this loadable should be active.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_conditionals();
|
||||
}
|
||||
37
wp-content/plugins/wordpress-seo/src/wordpress/wrapper.php
Normal file
37
wp-content/plugins/wordpress-seo/src/wordpress/wrapper.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Yoast SEO Plugin File.
|
||||
*
|
||||
* @package Yoast\YoastSEO\WordPress
|
||||
*/
|
||||
|
||||
namespace Yoast\WP\SEO\WordPress;
|
||||
|
||||
/**
|
||||
* Wrapper class for WordPress globals.
|
||||
* This consists of factory functions to inject WP globals into the dependency container.
|
||||
*/
|
||||
class Wrapper {
|
||||
|
||||
/**
|
||||
* Wrapper method for returning the wpdb object for use in dependency injection.
|
||||
*
|
||||
* @return \wpdb The wpdb global.
|
||||
*/
|
||||
public static function get_wpdb() {
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper method for returning the wp_query object for use in dependency injection.
|
||||
*
|
||||
* @return \WP_Query The wp_query global.
|
||||
*/
|
||||
public static function get_wp_query() {
|
||||
global $wp_query;
|
||||
|
||||
return $wp_query;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user