| Current Path : /home/x/b/o/xbodynamge/namtation/wp-content/ |
| Current File : /home/x/b/o/xbodynamge/namtation/wp-content/aioseo.tar |
aioseo-replacevar-service.php 0000666 00000006637 15111703513 0012331 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Services\Importing\Aioseo;
/**
* Replaces AISOEO replacevars with Yoast ones.
*/
class Aioseo_Replacevar_Service {
/**
* Mapping between the AiOSEO replace vars and the Yoast replace vars.
*
* @var array
*
* @see https://yoast.com/help/list-available-snippet-variables-yoast-seo/
*/
protected $replace_vars_map = [
// The key is the AiOSEO replace var, the value is the Yoast replace var (see class-wpseo-replace-vars).
'#archive_title' => '%%archive_title%%',
'#archive_date' => '%%date%%',
'#attachment_caption' => '%%caption%%',
'#author_bio' => '%%user_description%%',
'#author_first_name' => '%%author_first_name%%',
'#author_last_name' => '%%author_last_name%%',
'#author_name' => '%%name%%',
'#blog_title' => '%%sitename%%', // Same with #site_title.
'#categories' => '%%category%%',
'#current_date' => '%%currentdate%%',
'#current_day' => '%%currentday%%',
'#current_month' => '%%currentmonth%%',
'#current_year' => '%%currentyear%%',
'#parent_title' => '%%parent_title%%',
'#page_number' => '%%pagenumber%%',
'#permalink' => '%%permalink%%',
'#post_content' => '%%post_content%%',
'#post_date' => '%%date%%',
'#post_day' => '%%post_day%%',
'#post_month' => '%%post_month%%',
'#post_title' => '%%title%%',
'#post_year' => '%%post_year%%',
'#post_excerpt_only' => '%%excerpt_only%%',
'#post_excerpt' => '%%excerpt%%',
'#search_term' => '%%searchphrase%%',
'#separator_sa' => '%%sep%%',
'#site_title' => '%%sitename%%',
'#tagline' => '%%sitedesc%%',
'#taxonomy_title' => '%%category_title%%',
'#taxonomy_description' => '%%term_description%%',
];
/**
* Edits the replace_vars map of the class.
*
* @param string $aioseo_var The AIOSEO replacevar.
* @param string $yoast_var The Yoast replacevar.
*
* @return void
*/
public function compose_map( $aioseo_var, $yoast_var ) {
$map = $this->replace_vars_map;
$map[ $aioseo_var ] = $yoast_var;
$this->replace_vars_map = $map;
}
/**
* Transforms AIOSEO replacevars into Yoast replacevars.
*
* @param string $aioseo_replacevar The AIOSEO replacevar.
*
* @return string The Yoast replacevar.
*/
public function transform( $aioseo_replacevar ) {
$yoast_replacevar = \str_replace( \array_keys( $this->replace_vars_map ), \array_values( $this->replace_vars_map ), $aioseo_replacevar );
// Transform the '#custom_field-<custom_field>' tags into '%%cf_<custom_field>%%' ones.
$yoast_replacevar = \preg_replace_callback(
'/#custom_field-([a-zA-Z0-9_-]+)/',
static function ( $cf_matches ) {
return '%%cf_' . $cf_matches[1] . '%%';
},
$yoast_replacevar
);
// Transform the '#tax_name-<custom-tax-name>' tags into '%%ct_<custom-tax-name>%%' ones.
$yoast_replacevar = \preg_replace_callback(
'/#tax_name-([a-zA-Z0-9_-]+)/',
static function ( $ct_matches ) {
return '%%ct_' . $ct_matches[1] . '%%';
},
$yoast_replacevar
);
return $yoast_replacevar;
}
}
aioseo-robots-transformer-service.php 0000666 00000003326 15111703513 0014045 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Services\Importing\Aioseo;
/**
* Transforms AISOEO search appearance robot settings.
*/
class Aioseo_Robots_Transformer_Service {
/**
* The robots transfomer service.
*
* @var Aioseo_Robots_Provider_Service
*/
protected $robots_provider;
/**
* Class constructor.
*
* @param Aioseo_Robots_Provider_Service $robots_provider The robots provider service.
*/
public function __construct(
Aioseo_Robots_Provider_Service $robots_provider
) {
$this->robots_provider = $robots_provider;
}
/**
* Transforms the robot setting, taking into consideration whether they defer to global defaults.
*
* @param string $setting_name The name of the robot setting, eg. noindex.
* @param bool $setting_value The value of the robot setting.
* @param array $mapping The mapping of the setting we're working with.
*
* @return bool The transformed robot setting.
*/
public function transform_robot_setting( $setting_name, $setting_value, $mapping ) {
$aioseo_settings = \json_decode( \get_option( $mapping['option_name'], '' ), true );
// Let's check first if it defers to global robot settings.
if ( empty( $aioseo_settings ) || ! isset( $aioseo_settings['searchAppearance'][ $mapping['type'] ][ $mapping['subtype'] ]['advanced']['robotsMeta']['default'] ) ) {
return $setting_value;
}
$defers_to_defaults = $aioseo_settings['searchAppearance'][ $mapping['type'] ][ $mapping['subtype'] ]['advanced']['robotsMeta']['default'];
if ( $defers_to_defaults ) {
return $this->robots_provider->get_global_robot_settings( $setting_name );
}
return $setting_value;
}
}
aioseo-robots-provider-service.php 0000666 00000003254 15111703513 0013335 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Services\Importing\Aioseo;
use Yoast\WP\SEO\Helpers\Aioseo_Helper;
/**
* Provides AISOEO search appearance robot settings.
*/
class Aioseo_Robots_Provider_Service {
/**
* The AIOSEO helper.
*
* @var Aioseo_Helper
*/
protected $aioseo_helper;
/**
* Class constructor.
*
* @param Aioseo_Helper $aioseo_helper The AIOSEO helper.
*/
public function __construct(
Aioseo_Helper $aioseo_helper
) {
$this->aioseo_helper = $aioseo_helper;
}
/**
* Retrieves the robot setting set globally in AIOSEO.
*
* @param string $setting_name The name of the robot setting, eg. noindex.
*
* @return bool Whether global robot settings enable or not the specific setting.
*/
public function get_global_robot_settings( $setting_name ) {
$aioseo_settings = $this->aioseo_helper->get_global_option();
if ( empty( $aioseo_settings ) ) {
return false;
}
$global_robot_settings = $aioseo_settings['searchAppearance']['advanced']['globalRobotsMeta'];
if ( $global_robot_settings['default'] === true ) {
return false;
}
return $global_robot_settings[ $setting_name ];
}
/**
* Gets the subtype's robot setting from the db.
*
* @param array $mapping The mapping of the setting we're working with.
*
* @return bool The robot setting.
*/
public function get_subtype_robot_setting( $mapping ) {
$aioseo_settings = \json_decode( \get_option( $mapping['option_name'], '' ), true );
return $aioseo_settings['searchAppearance'][ $mapping['type'] ][ $mapping['subtype'] ]['advanced']['robotsMeta'][ $mapping['robot_type'] ];
}
}
aioseo-social-images-provider-service.php 0000666 00000010653 15111703513 0014543 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Services\Importing\Aioseo;
use Yoast\WP\SEO\Helpers\Aioseo_Helper;
use Yoast\WP\SEO\Helpers\Image_Helper;
/**
* Provides AISOEO social images urls.
*/
class Aioseo_Social_Images_Provider_Service {
/**
* The AIOSEO helper.
*
* @var Aioseo_Helper
*/
protected $aioseo_helper;
/**
* The image helper.
*
* @var Image_Helper
*/
protected $image;
/**
* Class constructor.
*
* @param Aioseo_Helper $aioseo_helper The AIOSEO helper.
* @param Image_Helper $image The image helper.
*/
public function __construct(
Aioseo_Helper $aioseo_helper,
Image_Helper $image
) {
$this->aioseo_helper = $aioseo_helper;
$this->image = $image;
}
/**
* Retrieves the default source of social images.
*
* @param string $social_setting The social settings we're working with, eg. open-graph or twitter.
*
* @return string The default source of social images.
*/
public function get_default_social_image_source( $social_setting ) {
return $this->get_social_defaults( 'source', $social_setting );
}
/**
* Retrieves the default custom social image if there is any.
*
* @param string $social_setting The social settings we're working with, eg. open-graph or twitter.
*
* @return string The global default social image.
*/
public function get_default_custom_social_image( $social_setting ) {
return $this->get_social_defaults( 'custom_image', $social_setting );
}
/**
* Retrieves social defaults, be it Default Post Image Source or Default Post Image.
*
* @param string $setting The setting we want, eg. source or custom image.
* @param string $social_setting The social settings we're working with, eg. open-graph or twitter.
*
* @return string The social default.
*/
public function get_social_defaults( $setting, $social_setting ) {
switch ( $setting ) {
case 'source':
$setting_key = 'defaultImageSourcePosts';
break;
case 'custom_image':
$setting_key = 'defaultImagePosts';
break;
default:
return '';
}
$aioseo_settings = $this->aioseo_helper->get_global_option();
if ( $social_setting === 'og' ) {
$social_setting = 'facebook';
}
if ( ! isset( $aioseo_settings['social'][ $social_setting ]['general'][ $setting_key ] ) ) {
return '';
}
return $aioseo_settings['social'][ $social_setting ]['general'][ $setting_key ];
}
/**
* Retrieves the url of the first image in content.
*
* @param int $post_id The post id to extract the image from.
*
* @return string The url of the first image in content.
*/
public function get_first_image_in_content( $post_id ) {
$image = $this->image->get_gallery_image( $post_id );
if ( ! $image ) {
$image = $this->image->get_post_content_image( $post_id );
}
return $image;
}
/**
* Retrieves the url of the first attached image.
*
* @param int $post_id The post id to extract the image from.
*
* @return string The url of the first attached image.
*/
public function get_first_attached_image( $post_id ) {
if ( \get_post_type( $post_id ) === 'attachment' ) {
return $this->image->get_attachment_image_source( $post_id, 'fullsize' );
}
$attachments = \get_children(
[
'post_parent' => $post_id,
'post_status' => 'inherit',
'post_type' => 'attachment',
'post_mime_type' => 'image',
]
);
if ( $attachments && ! empty( $attachments ) ) {
return $this->image->get_attachment_image_source( \array_values( $attachments )[0]->ID, 'fullsize' );
}
return '';
}
/**
* Retrieves the url of the featured image.
*
* @param int $post_id The post id to extract the image from.
*
* @return string The url of the featured image.
*/
public function get_featured_image( $post_id ) {
$feature_image_id = \get_post_thumbnail_id( $post_id );
if ( $feature_image_id ) {
return $this->image->get_attachment_image_source( $feature_image_id, 'fullsize' );
}
return '';
}
/**
* Retrieves the url of the first available image. Tries each image source to get one image.
*
* @param int $post_id The post id to extract the image from.
*
* @return string The url of the featured image.
*/
public function get_auto_image( $post_id ) {
$image = $this->get_first_attached_image( $post_id );
if ( ! $image ) {
$image = $this->get_first_image_in_content( $post_id );
}
return $image;
}
}
aioseo-validate-data-action.php 0000666 00000021131 15113063073 0012506 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
use wpdb;
use Yoast\WP\SEO\Actions\Importing\Abstract_Aioseo_Importing_Action;
use Yoast\WP\SEO\Exceptions\Importing\Aioseo_Validation_Exception;
use Yoast\WP\SEO\Helpers\Options_Helper;
/**
* Importing action for validating AIOSEO data before the import occurs.
*/
class Aioseo_Validate_Data_Action extends Abstract_Aioseo_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'validate_data';
/**
* The WordPress database instance.
*
* @var wpdb
*/
protected $wpdb;
/**
* The Post Importing action.
*
* @var Aioseo_Posts_Importing_Action
*/
protected $post_importing_action;
/**
* The settings importing actions.
*
* @var array
*/
protected $settings_importing_actions;
/**
* Class constructor.
*
* @param wpdb $wpdb The WordPress database instance.
* @param Options_Helper $options The options helper.
* @param Aioseo_Custom_Archive_Settings_Importing_Action $custom_archive_action The Custom Archive Settings importing action.
* @param Aioseo_Default_Archive_Settings_Importing_Action $default_archive_action The Default Archive Settings importing action.
* @param Aioseo_General_Settings_Importing_Action $general_settings_action The General Settings importing action.
* @param Aioseo_Posttype_Defaults_Settings_Importing_Action $posttype_defaults_settings_action The Posttype Defaults Settings importing action.
* @param Aioseo_Taxonomy_Settings_Importing_Action $taxonomy_settings_action The Taxonomy Settings importing action.
* @param Aioseo_Posts_Importing_Action $post_importing_action The Post importing action.
*/
public function __construct(
wpdb $wpdb,
Options_Helper $options,
Aioseo_Custom_Archive_Settings_Importing_Action $custom_archive_action,
Aioseo_Default_Archive_Settings_Importing_Action $default_archive_action,
Aioseo_General_Settings_Importing_Action $general_settings_action,
Aioseo_Posttype_Defaults_Settings_Importing_Action $posttype_defaults_settings_action,
Aioseo_Taxonomy_Settings_Importing_Action $taxonomy_settings_action,
Aioseo_Posts_Importing_Action $post_importing_action
) {
$this->wpdb = $wpdb;
$this->options = $options;
$this->post_importing_action = $post_importing_action;
$this->settings_importing_actions = [
$custom_archive_action,
$default_archive_action,
$general_settings_action,
$posttype_defaults_settings_action,
$taxonomy_settings_action,
];
}
/**
* Just checks if the action has been completed in the past.
*
* @return int 1 if it hasn't been completed in the past, 0 if it has.
*/
public function get_total_unindexed() {
return ( ! $this->get_completed() ) ? 1 : 0;
}
/**
* Just checks if the action has been completed in the past.
*
* @param int $limit The maximum number of unimported objects to be returned. Not used, exists to comply with the interface.
*
* @return int 1 if it hasn't been completed in the past, 0 if it has.
*/
public function get_limited_unindexed_count( $limit ) {
return ( ! $this->get_completed() ) ? 1 : 0;
}
/**
* Validates AIOSEO data.
*
* @return array An array of validated data or false if aioseo data did not pass validation.
*
* @throws Aioseo_Validation_Exception If the validation fails.
*/
public function index() {
if ( $this->get_completed() ) {
return [];
}
$validated_aioseo_table = $this->validate_aioseo_table();
$validated_aioseo_settings = $this->validate_aioseo_settings();
$validated_robot_settings = $this->validate_robot_settings();
if ( $validated_aioseo_table === false || $validated_aioseo_settings === false || $validated_robot_settings === false ) {
throw new Aioseo_Validation_Exception();
}
$this->set_completed( true );
return [
'validated_aioseo_table' => $validated_aioseo_table,
'validated_aioseo_settings' => $validated_aioseo_settings,
'validated_robot_settings' => $validated_robot_settings,
];
}
/**
* Validates the AIOSEO indexable table.
*
* @return bool Whether the AIOSEO table exists and has the structure we expect.
*/
public function validate_aioseo_table() {
if ( ! $this->aioseo_helper->aioseo_exists() ) {
return false;
}
$table = $this->aioseo_helper->get_table();
$needed_data = $this->post_importing_action->get_needed_data();
$aioseo_columns = $this->wpdb->get_col(
"SHOW COLUMNS FROM {$table}", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input.
0
);
return $needed_data === \array_intersect( $needed_data, $aioseo_columns );
}
/**
* Validates the AIOSEO settings from the options table.
*
* @return bool Whether the AIOSEO settings from the options table exist and have the structure we expect.
*/
public function validate_aioseo_settings() {
foreach ( $this->settings_importing_actions as $settings_import_action ) {
$aioseo_settings = \json_decode( \get_option( $settings_import_action->get_source_option_name(), '' ), true );
if ( ! $settings_import_action->isset_settings_tab( $aioseo_settings ) ) {
return false;
}
}
return true;
}
/**
* Validates the AIOSEO robots settings from the options table.
*
* @return bool Whether the AIOSEO robots settings from the options table exist and have the structure we expect.
*/
public function validate_robot_settings() {
if ( $this->validate_post_robot_settings() && $this->validate_default_robot_settings() ) {
return true;
}
return false;
}
/**
* Validates the post AIOSEO robots settings from the options table.
*
* @return bool Whether the post AIOSEO robots settings from the options table exist and have the structure we expect.
*/
public function validate_post_robot_settings() {
$post_robot_mapping = $this->post_importing_action->enhance_mapping();
// We're gonna validate against posttype robot settings only for posts, assuming the robot settings stay the same for other post types.
$post_robot_mapping['subtype'] = 'post';
// Let's get both the aioseo_options and the aioseo_options_dynamic options.
$aioseo_global_settings = $this->aioseo_helper->get_global_option();
$aioseo_posts_settings = \json_decode( \get_option( $post_robot_mapping['option_name'], '' ), true );
$needed_robots_data = $this->post_importing_action->get_needed_robot_data();
\array_push( $needed_robots_data, 'default', 'noindex' );
foreach ( $needed_robots_data as $robot_setting ) {
// Validate against global settings.
if ( ! isset( $aioseo_global_settings['searchAppearance']['advanced']['globalRobotsMeta'][ $robot_setting ] ) ) {
return false;
}
// Validate against posttype settings.
if ( ! isset( $aioseo_posts_settings['searchAppearance'][ $post_robot_mapping['type'] ][ $post_robot_mapping['subtype'] ]['advanced']['robotsMeta'][ $robot_setting ] ) ) {
return false;
}
}
return true;
}
/**
* Validates the default AIOSEO robots settings for search appearance settings from the options table.
*
* @return bool Whether the AIOSEO robots settings for search appearance settings from the options table exist and have the structure we expect.
*/
public function validate_default_robot_settings() {
foreach ( $this->settings_importing_actions as $settings_import_action ) {
$robot_setting_map = $settings_import_action->pluck_robot_setting_from_mapping();
// Some actions return empty robot settings, let's not validate against those.
if ( ! empty( $robot_setting_map ) ) {
$aioseo_settings = \json_decode( \get_option( $robot_setting_map['option_name'], '' ), true );
if ( ! isset( $aioseo_settings['searchAppearance'][ $robot_setting_map['type'] ][ $robot_setting_map['subtype'] ]['advanced']['robotsMeta']['default'] ) ) {
return false;
}
}
}
return true;
}
/**
* Used nowhere. Exists to comply with the interface.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_aioseo_cleanup_limit' - Allow filtering the number of validations during each action pass.
*
* @api int The maximum number of validations.
*/
$limit = \apply_filters( 'wpseo_aioseo_validation_limit', 25 );
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = 25;
}
return $limit;
}
}
aioseo-posttype-defaults-settings-importing-action.php 0000666 00000005513 15113063073 0017354 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
/**
* Importing action for AIOSEO posttype defaults settings data.
*
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
*/
class Aioseo_Posttype_Defaults_Settings_Importing_Action extends Abstract_Aioseo_Settings_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'posttype_default_settings';
/**
* The option_name of the AIOSEO option that contains the settings.
*/
const SOURCE_OPTION_NAME = 'aioseo_options_dynamic';
/**
* The map of aioseo_options to yoast settings.
*
* @var array
*/
protected $aioseo_options_to_yoast_map = [];
/**
* The tab of the aioseo settings we're working with.
*
* @var string
*/
protected $settings_tab = 'postTypes';
/**
* Builds the mapping that ties AOISEO option keys with Yoast ones and their data transformation method.
*
* @return void
*/
protected function build_mapping() {
$post_type_objects = \get_post_types( [ 'public' => true ], 'objects' );
foreach ( $post_type_objects as $pt ) {
// Use all the custom post types that are public.
$this->aioseo_options_to_yoast_map[ '/' . $pt->name . '/title' ] = [
'yoast_name' => 'title-' . $pt->name,
'transform_method' => 'simple_import',
];
$this->aioseo_options_to_yoast_map[ '/' . $pt->name . '/metaDescription' ] = [
'yoast_name' => 'metadesc-' . $pt->name,
'transform_method' => 'simple_import',
];
$this->aioseo_options_to_yoast_map[ '/' . $pt->name . '/advanced/showMetaBox' ] = [
'yoast_name' => 'display-metabox-pt-' . $pt->name,
'transform_method' => 'simple_boolean_import',
];
$this->aioseo_options_to_yoast_map[ '/' . $pt->name . '/advanced/robotsMeta/noindex' ] = [
'yoast_name' => 'noindex-' . $pt->name,
'transform_method' => 'import_noindex',
'type' => 'postTypes',
'subtype' => $pt->name,
'option_name' => 'aioseo_options_dynamic',
];
if ( $pt->name === 'attachment' ) {
$this->aioseo_options_to_yoast_map['/attachment/redirectAttachmentUrls'] = [
'yoast_name' => 'disable-attachment',
'transform_method' => 'import_redirect_attachment',
];
}
}
}
/**
* Transforms the redirect_attachment setting.
*
* @param string $redirect_attachment The redirect_attachment setting.
*
* @return bool The transformed redirect_attachment setting.
*/
public function import_redirect_attachment( $redirect_attachment ) {
switch ( $redirect_attachment ) {
case 'disabled':
return false;
case 'attachment':
case 'attachment_parent':
default:
return true;
}
}
}
aioseo-taxonomy-settings-importing-action.php 0000666 00000007620 15113063073 0015537 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
/**
* Importing action for AIOSEO taxonomies settings data.
*/
class Aioseo_Taxonomy_Settings_Importing_Action extends Abstract_Aioseo_Settings_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'taxonomy_settings';
/**
* The option_name of the AIOSEO option that contains the settings.
*/
const SOURCE_OPTION_NAME = 'aioseo_options_dynamic';
/**
* The map of aioseo_options to yoast settings.
*
* @var array
*/
protected $aioseo_options_to_yoast_map = [];
/**
* The tab of the aioseo settings we're working with.
*
* @var string
*/
protected $settings_tab = 'taxonomies';
/**
* Additional mapping between AiOSEO replace vars and Yoast replace vars.
*
* @var array
*
* @see https://yoast.com/help/list-available-snippet-variables-yoast-seo/
*/
protected $replace_vars_edited_map = [
'#breadcrumb_404_error_format' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_archive_post_type_format' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_archive_post_type_name' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_author_display_name' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_author_first_name' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_blog_page_title' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_label' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_link' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_search_result_format' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_search_string' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_separator' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#breadcrumb_taxonomy_title' => '', // Empty string, as AIOSEO shows nothing for that tag.
'#taxonomy_title' => '%%term_title%%',
];
/**
* Builds the mapping that ties AOISEO option keys with Yoast ones and their data transformation method.
*
* @return void
*/
protected function build_mapping() {
$taxonomy_objects = \get_taxonomies( [ 'public' => true ], 'object' );
foreach ( $taxonomy_objects as $tax ) {
// Use all the public taxonomies.
$this->aioseo_options_to_yoast_map[ '/' . $tax->name . '/title' ] = [
'yoast_name' => 'title-tax-' . $tax->name,
'transform_method' => 'simple_import',
];
$this->aioseo_options_to_yoast_map[ '/' . $tax->name . '/metaDescription' ] = [
'yoast_name' => 'metadesc-tax-' . $tax->name,
'transform_method' => 'simple_import',
];
$this->aioseo_options_to_yoast_map[ '/' . $tax->name . '/advanced/robotsMeta/noindex' ] = [
'yoast_name' => 'noindex-tax-' . $tax->name,
'transform_method' => 'import_noindex',
'type' => 'taxonomies',
'subtype' => $tax->name,
'option_name' => 'aioseo_options_dynamic',
];
}
}
/**
* Returns a setting map of the robot setting for post category taxonomies.
*
* @return array The setting map of the robot setting for post category taxonomies.
*/
public function pluck_robot_setting_from_mapping() {
$this->build_mapping();
foreach ( $this->aioseo_options_to_yoast_map as $setting ) {
// Return the first archive setting map.
if ( $setting['transform_method'] === 'import_noindex' && isset( $setting['subtype'] ) && $setting['subtype'] === 'category' ) {
return $setting;
}
}
return [];
}
}
aioseo-default-archive-settings-importing-action.php 0000666 00000005563 15113063073 0016730 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
/**
* Importing action for AIOSEO default archive settings data.
*
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
*/
class Aioseo_Default_Archive_Settings_Importing_Action extends Abstract_Aioseo_Settings_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'default_archive_settings';
/**
* The option_name of the AIOSEO option that contains the settings.
*/
const SOURCE_OPTION_NAME = 'aioseo_options';
/**
* The map of aioseo_options to yoast settings.
*
* @var array
*/
protected $aioseo_options_to_yoast_map = [];
/**
* The tab of the aioseo settings we're working with.
*
* @var string
*/
protected $settings_tab = 'archives';
/**
* Builds the mapping that ties AOISEO option keys with Yoast ones and their data transformation method.
*
* @return void
*/
protected function build_mapping() {
$this->aioseo_options_to_yoast_map = [
'/author/title' => [
'yoast_name' => 'title-author-wpseo',
'transform_method' => 'simple_import',
],
'/author/metaDescription' => [
'yoast_name' => 'metadesc-author-wpseo',
'transform_method' => 'simple_import',
],
'/date/title' => [
'yoast_name' => 'title-archive-wpseo',
'transform_method' => 'simple_import',
],
'/date/metaDescription' => [
'yoast_name' => 'metadesc-archive-wpseo',
'transform_method' => 'simple_import',
],
'/search/title' => [
'yoast_name' => 'title-search-wpseo',
'transform_method' => 'simple_import',
],
'/author/advanced/robotsMeta/noindex' => [
'yoast_name' => 'noindex-author-wpseo',
'transform_method' => 'import_noindex',
'type' => 'archives',
'subtype' => 'author',
'option_name' => 'aioseo_options',
],
'/date/advanced/robotsMeta/noindex' => [
'yoast_name' => 'noindex-archive-wpseo',
'transform_method' => 'import_noindex',
'type' => 'archives',
'subtype' => 'date',
'option_name' => 'aioseo_options',
],
];
}
/**
* Returns a setting map of the robot setting for author archives.
*
* @return array The setting map of the robot setting for author archives.
*/
public function pluck_robot_setting_from_mapping() {
$this->build_mapping();
foreach ( $this->aioseo_options_to_yoast_map as $setting ) {
// Return the first archive setting map.
if ( $setting['transform_method'] === 'import_noindex' && isset( $setting['subtype'] ) && $setting['subtype'] === 'author' ) {
return $setting;
}
}
return [];
}
}
aioseo-posts-importing-action.php 0000666 00000054622 15113063073 0013177 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
use wpdb;
use Yoast\WP\SEO\Actions\Importing\Abstract_Aioseo_Importing_Action;
use Yoast\WP\SEO\Helpers\Image_Helper;
use Yoast\WP\SEO\Helpers\Import_Cursor_Helper;
use Yoast\WP\SEO\Helpers\Indexable_Helper;
use Yoast\WP\SEO\Helpers\Indexable_To_Postmeta_Helper;
use Yoast\WP\SEO\Helpers\Options_Helper;
use Yoast\WP\SEO\Helpers\Sanitization_Helper;
use Yoast\WP\SEO\Models\Indexable;
use Yoast\WP\SEO\Repositories\Indexable_Repository;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Replacevar_Service;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Robots_Provider_Service;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Robots_Transformer_Service;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Social_Images_Provider_Service;
/**
* Importing action for AIOSEO post data.
*/
class Aioseo_Posts_Importing_Action extends Abstract_Aioseo_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'posts';
/**
* The map of aioseo to yoast meta.
*
* @var array
*/
protected $aioseo_to_yoast_map = [
'title' => [
'yoast_name' => 'title',
'transform_method' => 'simple_import_post',
],
'description' => [
'yoast_name' => 'description',
'transform_method' => 'simple_import_post',
],
'og_title' => [
'yoast_name' => 'open_graph_title',
'transform_method' => 'simple_import_post',
],
'og_description' => [
'yoast_name' => 'open_graph_description',
'transform_method' => 'simple_import_post',
],
'twitter_title' => [
'yoast_name' => 'twitter_title',
'transform_method' => 'simple_import_post',
'twitter_import' => true,
],
'twitter_description' => [
'yoast_name' => 'twitter_description',
'transform_method' => 'simple_import_post',
'twitter_import' => true,
],
'canonical_url' => [
'yoast_name' => 'canonical',
'transform_method' => 'url_import_post',
],
'keyphrases' => [
'yoast_name' => 'primary_focus_keyword',
'transform_method' => 'keyphrase_import',
],
'og_image_url' => [
'yoast_name' => 'open_graph_image',
'social_image_import' => true,
'social_setting_prefix_aioseo' => 'og_',
'social_setting_prefix_yoast' => 'open_graph_',
'transform_method' => 'social_image_url_import',
],
'twitter_image_url' => [
'yoast_name' => 'twitter_image',
'social_image_import' => true,
'social_setting_prefix_aioseo' => 'twitter_',
'social_setting_prefix_yoast' => 'twitter_',
'transform_method' => 'social_image_url_import',
],
'robots_noindex' => [
'yoast_name' => 'is_robots_noindex',
'transform_method' => 'post_robots_noindex_import',
'robots_import' => true,
],
'robots_nofollow' => [
'yoast_name' => 'is_robots_nofollow',
'transform_method' => 'post_general_robots_import',
'robots_import' => true,
'robot_type' => 'nofollow',
],
'robots_noarchive' => [
'yoast_name' => 'is_robots_noarchive',
'transform_method' => 'post_general_robots_import',
'robots_import' => true,
'robot_type' => 'noarchive',
],
'robots_nosnippet' => [
'yoast_name' => 'is_robots_nosnippet',
'transform_method' => 'post_general_robots_import',
'robots_import' => true,
'robot_type' => 'nosnippet',
],
'robots_noimageindex' => [
'yoast_name' => 'is_robots_noimageindex',
'transform_method' => 'post_general_robots_import',
'robots_import' => true,
'robot_type' => 'noimageindex',
],
];
/**
* Represents the indexables repository.
*
* @var Indexable_Repository
*/
protected $indexable_repository;
/**
* The WordPress database instance.
*
* @var wpdb
*/
protected $wpdb;
/**
* The image helper.
*
* @var Image_Helper
*/
protected $image;
/**
* The indexable_to_postmeta helper.
*
* @var Indexable_To_Postmeta_Helper
*/
protected $indexable_to_postmeta;
/**
* The indexable helper.
*
* @var Indexable_Helper
*/
protected $indexable_helper;
/**
* The social images provider service.
*
* @var Aioseo_Social_Images_Provider_Service
*/
protected $social_images_provider;
/**
* Class constructor.
*
* @param Indexable_Repository $indexable_repository The indexables repository.
* @param wpdb $wpdb The WordPress database instance.
* @param Import_Cursor_Helper $import_cursor The import cursor helper.
* @param Indexable_Helper $indexable_helper The indexable helper.
* @param Indexable_To_Postmeta_Helper $indexable_to_postmeta The indexable_to_postmeta helper.
* @param Options_Helper $options The options helper.
* @param Image_Helper $image The image helper.
* @param Sanitization_Helper $sanitization The sanitization helper.
* @param Aioseo_Replacevar_Service $replacevar_handler The replacevar handler.
* @param Aioseo_Robots_Provider_Service $robots_provider The robots provider service.
* @param Aioseo_Robots_Transformer_Service $robots_transformer The robots transfomer service.
* @param Aioseo_Social_Images_Provider_Service $social_images_provider The social images provider service.
*/
public function __construct(
Indexable_Repository $indexable_repository,
wpdb $wpdb,
Import_Cursor_Helper $import_cursor,
Indexable_Helper $indexable_helper,
Indexable_To_Postmeta_Helper $indexable_to_postmeta,
Options_Helper $options,
Image_Helper $image,
Sanitization_Helper $sanitization,
Aioseo_Replacevar_Service $replacevar_handler,
Aioseo_Robots_Provider_Service $robots_provider,
Aioseo_Robots_Transformer_Service $robots_transformer,
Aioseo_Social_Images_Provider_Service $social_images_provider ) {
parent::__construct( $import_cursor, $options, $sanitization, $replacevar_handler, $robots_provider, $robots_transformer );
$this->indexable_repository = $indexable_repository;
$this->wpdb = $wpdb;
$this->image = $image;
$this->indexable_helper = $indexable_helper;
$this->indexable_to_postmeta = $indexable_to_postmeta;
$this->social_images_provider = $social_images_provider;
}
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared -- Reason: They are already prepared.
/**
* Returns the total number of unimported objects.
*
* @return int The total number of unimported objects.
*/
public function get_total_unindexed() {
if ( ! $this->aioseo_helper->aioseo_exists() ) {
return 0;
}
$limit = false;
$just_detect = true;
$indexables_to_create = $this->wpdb->get_col( $this->query( $limit, $just_detect ) );
$number_of_indexables_to_create = \count( $indexables_to_create );
$completed = $number_of_indexables_to_create === 0;
$this->set_completed( $completed );
return $number_of_indexables_to_create;
}
/**
* Returns the limited number of unimported objects.
*
* @param int $limit The maximum number of unimported objects to be returned.
*
* @return int|false The limited number of unindexed posts. False if the query fails.
*/
public function get_limited_unindexed_count( $limit ) {
if ( ! $this->aioseo_helper->aioseo_exists() ) {
return 0;
}
$just_detect = true;
$indexables_to_create = $this->wpdb->get_col( $this->query( $limit, $just_detect ) );
$number_of_indexables_to_create = \count( $indexables_to_create );
$completed = $number_of_indexables_to_create === 0;
$this->set_completed( $completed );
return $number_of_indexables_to_create;
}
/**
* Imports AIOSEO meta data and creates the respective Yoast indexables and postmeta.
*
* @return Indexable[]|false An array of created indexables or false if aioseo data was not found.
*/
public function index() {
if ( ! $this->aioseo_helper->aioseo_exists() ) {
return false;
}
$limit = $this->get_limit();
$aioseo_indexables = $this->wpdb->get_results( $this->query( $limit ), \ARRAY_A );
$created_indexables = [];
$completed = \count( $aioseo_indexables ) === 0;
$this->set_completed( $completed );
// Let's build the list of fields to check their defaults, to identify whether we're gonna import AIOSEO data in the indexable or not.
$check_defaults_fields = [];
foreach ( $this->aioseo_to_yoast_map as $yoast_mapping ) {
// We don't want to check all the imported fields.
if ( ! \in_array( $yoast_mapping['yoast_name'], [ 'open_graph_image', 'twitter_image' ], true ) ) {
$check_defaults_fields[] = $yoast_mapping['yoast_name'];
}
}
$last_indexed_aioseo_id = 0;
foreach ( $aioseo_indexables as $aioseo_indexable ) {
$last_indexed_aioseo_id = $aioseo_indexable['id'];
$indexable = $this->indexable_repository->find_by_id_and_type( $aioseo_indexable['post_id'], 'post' );
// Let's ensure that the current post id represents something that we want to index (eg. *not* shop_order).
if ( ! \is_a( $indexable, 'Yoast\WP\SEO\Models\Indexable' ) ) {
continue;
}
if ( $this->indexable_helper->check_if_default_indexable( $indexable, $check_defaults_fields ) ) {
$indexable = $this->map( $indexable, $aioseo_indexable );
$indexable->save();
// To ensure that indexables can be rebuild after a reset, we have to store the data in the postmeta table too.
$this->indexable_to_postmeta->map_to_postmeta( $indexable );
}
$last_indexed_aioseo_id = $aioseo_indexable['id'];
$created_indexables[] = $indexable;
}
$cursor_id = $this->get_cursor_id();
$this->import_cursor->set_cursor( $cursor_id, $last_indexed_aioseo_id );
return $created_indexables;
}
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
/**
* Maps AIOSEO meta data to Yoast meta data.
*
* @param Indexable $indexable The Yoast indexable.
* @param array $aioseo_indexable The AIOSEO indexable.
*
* @return Indexable The created indexables.
*/
public function map( $indexable, $aioseo_indexable ) {
foreach ( $this->aioseo_to_yoast_map as $aioseo_key => $yoast_mapping ) {
// For robots import.
if ( isset( $yoast_mapping['robots_import'] ) && $yoast_mapping['robots_import'] ) {
$yoast_mapping['subtype'] = $indexable->object_sub_type;
$indexable->{$yoast_mapping['yoast_name']} = $this->transform_import_data( $yoast_mapping['transform_method'], $aioseo_indexable, $aioseo_key, $yoast_mapping, $indexable );
continue;
}
// For social images, like open graph and twitter image.
if ( isset( $yoast_mapping['social_image_import'] ) && $yoast_mapping['social_image_import'] ) {
$image_url = $this->transform_import_data( $yoast_mapping['transform_method'], $aioseo_indexable, $aioseo_key, $yoast_mapping, $indexable );
// Update the indexable's social image only where there's actually a url to import, so as not to lose the social images that we came up with when we originally built the indexable.
if ( ! empty( $image_url ) ) {
$indexable->{$yoast_mapping['yoast_name']} = $image_url;
$image_source_key = $yoast_mapping['social_setting_prefix_yoast'] . 'image_source';
$indexable->$image_source_key = 'imported';
$image_id_key = $yoast_mapping['social_setting_prefix_yoast'] . 'image_id';
$indexable->$image_id_key = $this->image->get_attachment_by_url( $image_url );
if ( $yoast_mapping['yoast_name'] === 'open_graph_image' ) {
$indexable->open_graph_image_meta = null;
}
}
continue;
}
// For twitter import, take the respective open graph data if the appropriate setting is enabled.
if ( isset( $yoast_mapping['twitter_import'] ) && $yoast_mapping['twitter_import'] && $aioseo_indexable['twitter_use_og'] ) {
$aioseo_indexable['twitter_title'] = $aioseo_indexable['og_title'];
$aioseo_indexable['twitter_description'] = $aioseo_indexable['og_description'];
}
if ( ! empty( $aioseo_indexable[ $aioseo_key ] ) ) {
$indexable->{$yoast_mapping['yoast_name']} = $this->transform_import_data( $yoast_mapping['transform_method'], $aioseo_indexable, $aioseo_key, $yoast_mapping, $indexable );
}
}
return $indexable;
}
/**
* Transforms the data to be imported.
*
* @param string $transform_method The method that is going to be used for transforming the data.
* @param array $aioseo_indexable The data of the AIOSEO indexable data that is being imported.
* @param string $aioseo_key The name of the specific set of data that is going to be transformed.
* @param array $yoast_mapping Extra details for the import of the specific data that is going to be transformed.
* @param Indexable $indexable The Yoast indexable that we are going to import the transformed data into.
*
* @return string|bool|null The transformed data to be imported.
*/
protected function transform_import_data( $transform_method, $aioseo_indexable, $aioseo_key, $yoast_mapping, $indexable ) {
return \call_user_func( [ $this, $transform_method ], $aioseo_indexable, $aioseo_key, $yoast_mapping, $indexable );
}
/**
* Returns the number of objects that will be imported in a single importing pass.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_aioseo_post_indexation_limit' - Allow filtering the number of posts indexed during each indexing pass.
*
* @api int The maximum number of posts indexed.
*/
$limit = \apply_filters( 'wpseo_aioseo_post_indexation_limit', 25 );
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = 25;
}
return $limit;
}
/**
* Populates the needed data array based on which columns we use from the AIOSEO indexable table.
*
* @return array The needed data array that contains all the needed columns.
*/
public function get_needed_data() {
$needed_data = \array_keys( $this->aioseo_to_yoast_map );
\array_push( $needed_data, 'id', 'post_id', 'robots_default', 'og_image_custom_url', 'og_image_type', 'twitter_image_custom_url', 'twitter_image_type', 'twitter_use_og' );
return $needed_data;
}
/**
* Populates the needed robot data array to be used in validating against its structure.
*
* @return array The needed data array that contains all the needed columns.
*/
public function get_needed_robot_data() {
$needed_robot_data = [];
foreach ( $this->aioseo_to_yoast_map as $yoast_mapping ) {
if ( isset( $yoast_mapping['robot_type'] ) ) {
$needed_robot_data[] = $yoast_mapping['robot_type'];
}
}
return $needed_robot_data;
}
/**
* Creates a query for gathering AiOSEO data from the database.
*
* @param int $limit The maximum number of unimported objects to be returned.
* @param bool $just_detect Whether we want to just detect if there are unimported objects. If false, we want to actually import them too.
*
* @return string The query to use for importing or counting the number of items to import.
*/
public function query( $limit = false, $just_detect = false ) {
$table = $this->aioseo_helper->get_table();
$select_statement = 'id';
if ( ! $just_detect ) {
// If we want to import too, we need the actual needed data from AIOSEO indexables.
$needed_data = $this->get_needed_data();
$select_statement = \implode( ', ', $needed_data );
}
$cursor_id = $this->get_cursor_id();
$cursor = $this->import_cursor->get_cursor( $cursor_id );
/**
* Filter 'wpseo_aioseo_post_cursor' - Allow filtering the value of the aioseo post import cursor.
*
* @api int The value of the aioseo post import cursor.
*/
$cursor = \apply_filters( 'wpseo_aioseo_post_import_cursor', $cursor );
$replacements = [ $cursor ];
$limit_statement = '';
if ( ! empty( $limit ) ) {
$replacements[] = $limit;
$limit_statement = ' LIMIT %d';
}
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input.
return $this->wpdb->prepare(
"SELECT {$select_statement} FROM {$table} WHERE id > %d ORDER BY id{$limit_statement}",
$replacements
);
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
/**
* Minimally transforms data to be imported.
*
* @param array $aioseo_data All of the AIOSEO data to be imported.
* @param string $aioseo_key The AIOSEO key that contains the setting we're working with.
*
* @return string The transformed meta data.
*/
public function simple_import_post( $aioseo_data, $aioseo_key ) {
return $this->simple_import( $aioseo_data[ $aioseo_key ] );
}
/**
* Transforms URL to be imported.
*
* @param array $aioseo_data All of the AIOSEO data to be imported.
* @param string $aioseo_key The AIOSEO key that contains the setting we're working with.
*
* @return string The transformed URL.
*/
public function url_import_post( $aioseo_data, $aioseo_key ) {
return $this->url_import( $aioseo_data[ $aioseo_key ] );
}
/**
* Plucks the keyphrase to be imported from the AIOSEO array of keyphrase meta data.
*
* @param array $aioseo_data All of the AIOSEO data to be imported.
* @param string $aioseo_key The AIOSEO key that contains the setting we're working with, aka keyphrases.
*
* @return string|null The plucked keyphrase.
*/
public function keyphrase_import( $aioseo_data, $aioseo_key ) {
$meta_data = \json_decode( $aioseo_data[ $aioseo_key ], true );
if ( ! isset( $meta_data['focus']['keyphrase'] ) ) {
return null;
}
return $this->sanitization->sanitize_text_field( $meta_data['focus']['keyphrase'] );
}
/**
* Imports the post's noindex setting.
*
* @param bool $aioseo_robots_settings AIOSEO's set of robot settings for the post.
*
* @return bool|null The value of Yoast's noindex setting for the post.
*/
public function post_robots_noindex_import( $aioseo_robots_settings ) {
// If robot settings defer to default settings, we have null in the is_robots_noindex field.
if ( $aioseo_robots_settings['robots_default'] ) {
return null;
}
return $aioseo_robots_settings['robots_noindex'];
}
/**
* Imports the post's robots setting.
*
* @param bool $aioseo_robots_settings AIOSEO's set of robot settings for the post.
* @param string $aioseo_key The AIOSEO key that contains the robot setting we're working with.
* @param array $mapping The mapping of the setting we're working with.
*
* @return bool|null The value of Yoast's noindex setting for the post.
*/
public function post_general_robots_import( $aioseo_robots_settings, $aioseo_key, $mapping ) {
$mapping = $this->enhance_mapping( $mapping );
if ( $aioseo_robots_settings['robots_default'] ) {
// Let's first get the subtype's setting value and then transform it taking into consideration whether it defers to global defaults.
$subtype_setting = $this->robots_provider->get_subtype_robot_setting( $mapping );
return $this->robots_transformer->transform_robot_setting( $mapping['robot_type'], $subtype_setting, $mapping );
}
return $aioseo_robots_settings[ $aioseo_key ];
}
/**
* Enhances the mapping of the setting we're working with, with type and the option name, so that we can retrieve the settings for the object we're working with.
*
* @param array $mapping The mapping of the setting we're working with.
*
* @return array The enhanced mapping.
*/
public function enhance_mapping( $mapping = [] ) {
$mapping['type'] = 'postTypes';
$mapping['option_name'] = 'aioseo_options_dynamic';
return $mapping;
}
/**
* Imports the og and twitter image url.
*
* @param bool $aioseo_social_image_settings AIOSEO's set of social image settings for the post.
* @param string $aioseo_key The AIOSEO key that contains the robot setting we're working with.
* @param array $mapping The mapping of the setting we're working with.
* @param Indexable $indexable The Yoast indexable we're importing into.
*
* @return bool|null The url of the social image we're importing, null if there's none.
*/
public function social_image_url_import( $aioseo_social_image_settings, $aioseo_key, $mapping, $indexable ) {
if ( $mapping['social_setting_prefix_aioseo'] === 'twitter_' && $aioseo_social_image_settings['twitter_use_og'] ) {
$mapping['social_setting_prefix_aioseo'] = 'og_';
}
$social_setting = \rtrim( $mapping['social_setting_prefix_aioseo'], '_' );
$image_type = $aioseo_social_image_settings[ $mapping['social_setting_prefix_aioseo'] . 'image_type' ];
if ( $image_type === 'default' ) {
$image_type = $this->social_images_provider->get_default_social_image_source( $social_setting );
}
switch ( $image_type ) {
case 'attach':
$image_url = $this->social_images_provider->get_first_attached_image( $indexable->object_id );
break;
case 'auto':
if ( $this->social_images_provider->get_featured_image( $indexable->object_id ) ) {
// If there's a featured image, lets not import it, as our indexable calculation has already set that as active social image. That way we achieve dynamicality.
return null;
}
$image_url = $this->social_images_provider->get_auto_image( $indexable->object_id );
break;
case 'content':
$image_url = $this->social_images_provider->get_first_image_in_content( $indexable->object_id );
break;
case 'custom_image':
$image_url = $aioseo_social_image_settings[ $mapping['social_setting_prefix_aioseo'] . 'image_custom_url' ];
break;
case 'featured':
return null; // Our auto-calculation when the indexable was built/updated has taken care of it, so it's not needed to transfer any data now.
case 'author':
return null;
case 'custom':
return null;
case 'default':
$image_url = $this->social_images_provider->get_default_custom_social_image( $social_setting );
break;
default:
$image_url = $aioseo_social_image_settings[ $mapping['social_setting_prefix_aioseo'] . 'image_url' ];
break;
}
if ( empty( $image_url ) ) {
$image_url = $this->social_images_provider->get_default_custom_social_image( $social_setting );
}
if ( empty( $image_url ) ) {
return null;
}
return $this->sanitization->sanitize_url( $image_url, null );
}
}
aioseo-custom-archive-settings-importing-action.php 0000666 00000007341 15113063073 0016612 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
use Yoast\WP\SEO\Helpers\Import_Cursor_Helper;
use Yoast\WP\SEO\Helpers\Options_Helper;
use Yoast\WP\SEO\Helpers\Post_Type_Helper;
use Yoast\WP\SEO\Helpers\Sanitization_Helper;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Replacevar_Service;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Robots_Provider_Service;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Robots_Transformer_Service;
/**
* Importing action for AIOSEO custom archive settings data.
*
* @phpcs:disable Yoast.NamingConventions.ObjectNameDepth.MaxExceeded
*/
class Aioseo_Custom_Archive_Settings_Importing_Action extends Abstract_Aioseo_Settings_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'custom_archive_settings';
/**
* The option_name of the AIOSEO option that contains the settings.
*/
const SOURCE_OPTION_NAME = 'aioseo_options_dynamic';
/**
* The map of aioseo_options to yoast settings.
*
* @var array
*/
protected $aioseo_options_to_yoast_map = [];
/**
* The tab of the aioseo settings we're working with.
*
* @var string
*/
protected $settings_tab = 'archives';
/**
* The post type helper.
*
* @var Post_Type_Helper
*/
protected $post_type;
/**
* Aioseo_Custom_Archive_Settings_Importing_Action constructor.
*
* @param Import_Cursor_Helper $import_cursor The import cursor helper.
* @param Options_Helper $options The options helper.
* @param Sanitization_Helper $sanitization The sanitization helper.
* @param Post_Type_Helper $post_type The post type helper.
* @param Aioseo_Replacevar_Service $replacevar_handler The replacevar handler.
* @param Aioseo_Robots_Provider_Service $robots_provider The robots provider service.
* @param Aioseo_Robots_Transformer_Service $robots_transformer The robots transfomer service.
*/
public function __construct(
Import_Cursor_Helper $import_cursor,
Options_Helper $options,
Sanitization_Helper $sanitization,
Post_Type_Helper $post_type,
Aioseo_Replacevar_Service $replacevar_handler,
Aioseo_Robots_Provider_Service $robots_provider,
Aioseo_Robots_Transformer_Service $robots_transformer
) {
parent::__construct( $import_cursor, $options, $sanitization, $replacevar_handler, $robots_provider, $robots_transformer );
$this->post_type = $post_type;
}
/**
* Builds the mapping that ties AOISEO option keys with Yoast ones and their data transformation method.
*
* @return void
*/
protected function build_mapping() {
$post_type_objects = \get_post_types( [ 'public' => true ], 'objects' );
foreach ( $post_type_objects as $pt ) {
// Use all the custom post types that have archives.
if ( ! $pt->_builtin && $this->post_type->has_archive( $pt ) ) {
$this->aioseo_options_to_yoast_map[ '/' . $pt->name . '/title' ] = [
'yoast_name' => 'title-ptarchive-' . $pt->name,
'transform_method' => 'simple_import',
];
$this->aioseo_options_to_yoast_map[ '/' . $pt->name . '/metaDescription' ] = [
'yoast_name' => 'metadesc-ptarchive-' . $pt->name,
'transform_method' => 'simple_import',
];
$this->aioseo_options_to_yoast_map[ '/' . $pt->name . '/advanced/robotsMeta/noindex' ] = [
'yoast_name' => 'noindex-ptarchive-' . $pt->name,
'transform_method' => 'import_noindex',
'type' => 'archives',
'subtype' => $pt->name,
'option_name' => 'aioseo_options_dynamic',
];
}
}
}
}
aioseo-general-settings-importing-action.php 0000666 00000013725 15113063073 0015301 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
use Yoast\WP\SEO\Helpers\Image_Helper;
use Yoast\WP\SEO\Helpers\Import_Cursor_Helper;
use Yoast\WP\SEO\Helpers\Options_Helper;
use Yoast\WP\SEO\Helpers\Sanitization_Helper;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Replacevar_Service;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Robots_Provider_Service;
use Yoast\WP\SEO\Services\Importing\Aioseo\Aioseo_Robots_Transformer_Service;
/**
* Importing action for AIOSEO general settings.
*/
class Aioseo_General_Settings_Importing_Action extends Abstract_Aioseo_Settings_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'general_settings';
/**
* The option_name of the AIOSEO option that contains the settings.
*/
const SOURCE_OPTION_NAME = 'aioseo_options';
/**
* The map of aioseo_options to yoast settings.
*
* @var array
*/
protected $aioseo_options_to_yoast_map = [];
/**
* The tab of the aioseo settings we're working with.
*
* @var string
*/
protected $settings_tab = 'global';
/**
* The image helper.
*
* @var Image_Helper
*/
protected $image;
/**
* Aioseo_General_Settings_Importing_Action constructor.
*
* @param Import_Cursor_Helper $import_cursor The import cursor helper.
* @param Options_Helper $options The options helper.
* @param Sanitization_Helper $sanitization The sanitization helper.
* @param Image_Helper $image The image helper.
* @param Aioseo_Replacevar_Service $replacevar_handler The replacevar handler.
* @param Aioseo_Robots_Provider_Service $robots_provider The robots provider service.
* @param Aioseo_Robots_Transformer_Service $robots_transformer The robots transfomer service.
*/
public function __construct(
Import_Cursor_Helper $import_cursor,
Options_Helper $options,
Sanitization_Helper $sanitization,
Image_Helper $image,
Aioseo_Replacevar_Service $replacevar_handler,
Aioseo_Robots_Provider_Service $robots_provider,
Aioseo_Robots_Transformer_Service $robots_transformer
) {
parent::__construct( $import_cursor, $options, $sanitization, $replacevar_handler, $robots_provider, $robots_transformer );
$this->image = $image;
}
/**
* Builds the mapping that ties AOISEO option keys with Yoast ones and their data transformation method.
*
* @return void
*/
protected function build_mapping() {
$this->aioseo_options_to_yoast_map = [
'/separator' => [
'yoast_name' => 'separator',
'transform_method' => 'transform_separator',
],
'/siteTitle' => [
'yoast_name' => 'title-home-wpseo',
'transform_method' => 'simple_import',
],
'/metaDescription' => [
'yoast_name' => 'metadesc-home-wpseo',
'transform_method' => 'simple_import',
],
'/schema/siteRepresents' => [
'yoast_name' => 'company_or_person',
'transform_method' => 'transform_site_represents',
],
'/schema/person' => [
'yoast_name' => 'company_or_person_user_id',
'transform_method' => 'simple_import',
],
'/schema/organizationName' => [
'yoast_name' => 'company_name',
'transform_method' => 'simple_import',
],
'/schema/organizationLogo' => [
'yoast_name' => 'company_logo',
'transform_method' => 'import_company_logo',
],
'/schema/personLogo' => [
'yoast_name' => 'person_logo',
'transform_method' => 'import_person_logo',
],
];
}
/**
* Imports the organization logo while also accounting for the id of the log to be saved in the separate Yoast option.
*
* @param string $logo_url The company logo url coming from AIOSEO settings.
*
* @return string The transformed company logo url.
*/
public function import_company_logo( $logo_url ) {
$logo_id = $this->image->get_attachment_by_url( $logo_url );
$this->options->set( 'company_logo_id', $logo_id );
$this->options->set( 'company_logo_meta', false );
$logo_meta = $this->image->get_attachment_meta_from_settings( 'company_logo' );
$this->options->set( 'company_logo_meta', $logo_meta );
return $this->url_import( $logo_url );
}
/**
* Imports the person logo while also accounting for the id of the log to be saved in the separate Yoast option.
*
* @param string $logo_url The person logo url coming from AIOSEO settings.
*
* @return string The transformed person logo url.
*/
public function import_person_logo( $logo_url ) {
$logo_id = $this->image->get_attachment_by_url( $logo_url );
$this->options->set( 'person_logo_id', $logo_id );
$this->options->set( 'person_logo_meta', false );
$logo_meta = $this->image->get_attachment_meta_from_settings( 'person_logo' );
$this->options->set( 'person_logo_meta', $logo_meta );
return $this->url_import( $logo_url );
}
/**
* Transforms the site represents setting.
*
* @param string $site_represents The site represents setting.
*
* @return string The transformed site represents setting.
*/
public function transform_site_represents( $site_represents ) {
switch ( $site_represents ) {
case 'person':
return 'person';
case 'organization':
default:
return 'company';
}
}
/**
* Transforms the separator setting.
*
* @param string $separator The separator setting.
*
* @return string The transformed separator.
*/
public function transform_separator( $separator ) {
switch ( $separator ) {
case '-':
return 'sc-dash';
case '–':
return 'sc-ndash';
case '—':
return 'sc-mdash';
case '»':
return 'sc-raquo';
case '«':
return 'sc-laquo';
case '>':
return 'sc-gt';
case '•':
return 'sc-bull';
case '|':
return 'sc-pipe';
default:
return 'sc-dash';
}
}
}
abstract-aioseo-settings-importing-action.php 0000666 00000024500 15113063073 0015460 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
use Exception;
use Yoast\WP\SEO\Actions\Importing\Abstract_Aioseo_Importing_Action;
use Yoast\WP\SEO\Helpers\Import_Helper;
/**
* Abstract class for importing AIOSEO settings.
*/
abstract class Abstract_Aioseo_Settings_Importing_Action extends Abstract_Aioseo_Importing_Action {
/**
* The plugin the class deals with.
*
* @var string
*/
const PLUGIN = null;
/**
* The type the class deals with.
*
* @var string
*/
const TYPE = null;
/**
* The option_name of the AIOSEO option that contains the settings.
*/
const SOURCE_OPTION_NAME = null;
/**
* The map of aioseo_options to yoast settings.
*
* @var array
*/
protected $aioseo_options_to_yoast_map = [];
/**
* The tab of the aioseo settings we're working with, eg. taxonomies, posttypes.
*
* @var string
*/
protected $settings_tab = '';
/**
* Additional mapping between AiOSEO replace vars and Yoast replace vars.
*
* @var array
*
* @see https://yoast.com/help/list-available-snippet-variables-yoast-seo/
*/
protected $replace_vars_edited_map = [];
/**
* The import helper.
*
* @var Import_Helper
*/
protected $import_helper;
/**
* Builds the mapping that ties AOISEO option keys with Yoast ones and their data transformation method.
*
* @return void
*/
abstract protected function build_mapping();
/**
* Sets the import helper.
*
* @required
*
* @param Import_Helper $import_helper The import helper.
*/
public function set_import_helper( Import_Helper $import_helper ) {
$this->import_helper = $import_helper;
}
/**
* Retrieves the source option_name.
*
* @return string The source option_name.
*
* @throws Exception If the SOURCE_OPTION_NAME constant is not set in the child class.
*/
public function get_source_option_name() {
$source_option_name = static::SOURCE_OPTION_NAME;
if ( empty( $source_option_name ) ) {
throw new Exception( 'Importing settings action without explicit source option_name' );
}
return $source_option_name;
}
/**
* Returns the total number of unimported objects.
*
* @return int The total number of unimported objects.
*/
public function get_total_unindexed() {
return $this->get_unindexed_count();
}
/**
* Returns the limited number of unimported objects.
*
* @param int $limit The maximum number of unimported objects to be returned.
*
* @return int The limited number of unindexed posts.
*/
public function get_limited_unindexed_count( $limit ) {
return $this->get_unindexed_count( $limit );
}
/**
* Returns the number of unimported objects (limited if limit is applied).
*
* @param int|null $limit The maximum number of unimported objects to be returned.
*
* @return int The number of unindexed posts.
*/
protected function get_unindexed_count( $limit = null ) {
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = null;
}
$settings_to_create = $this->query( $limit );
$number_of_settings_to_create = \count( $settings_to_create );
$completed = $number_of_settings_to_create === 0;
$this->set_completed( $completed );
return $number_of_settings_to_create;
}
/**
* Imports AIOSEO settings.
*
* @return array|false An array of the AIOSEO settings that were imported or false if aioseo data was not found.
*/
public function index() {
$limit = $this->get_limit();
$aioseo_settings = $this->query( $limit );
$created_settings = [];
$completed = \count( $aioseo_settings ) === 0;
$this->set_completed( $completed );
// Prepare the setting keys mapping.
$this->build_mapping();
// Prepare the replacement var mapping.
foreach ( $this->replace_vars_edited_map as $aioseo_var => $yoast_var ) {
$this->replacevar_handler->compose_map( $aioseo_var, $yoast_var );
}
$last_imported_setting = '';
try {
foreach ( $aioseo_settings as $setting => $setting_value ) {
// Map and import the values of the setting we're working with (eg. post, book-category, etc.) to the respective Yoast option.
$this->map( $setting_value, $setting );
// Save the type of the settings that were just imported, so that we can allow chunked imports.
$last_imported_setting = $setting;
$created_settings[] = $setting;
}
}
finally {
$cursor_id = $this->get_cursor_id();
$this->import_cursor->set_cursor( $cursor_id, $last_imported_setting );
}
return $created_settings;
}
/**
* Checks if the settings tab subsetting is set in the AIOSEO option.
*
* @param string $aioseo_settings The AIOSEO option.
*
* @return bool Whether the settings are set.
*/
public function isset_settings_tab( $aioseo_settings ) {
return isset( $aioseo_settings['searchAppearance'][ $this->settings_tab ] );
}
/**
* Queries the database and retrieves unimported AiOSEO settings (in chunks if a limit is applied).
*
* @param int|null $limit The maximum number of unimported objects to be returned.
*
* @return array The (maybe chunked) unimported AiOSEO settings to import.
*/
protected function query( $limit = null ) {
$aioseo_settings = \json_decode( \get_option( $this->get_source_option_name(), '' ), true );
if ( empty( $aioseo_settings ) ) {
return [];
}
// We specifically want the setttings of the tab we're working with, eg. postTypes, taxonomies, etc.
$settings_values = $aioseo_settings['searchAppearance'][ $this->settings_tab ];
if ( ! \is_array( $settings_values ) ) {
return [];
}
$flattened_settings = $this->import_helper->flatten_settings( $settings_values );
return $this->get_unimported_chunk( $flattened_settings, $limit );
}
/**
* Retrieves (a chunk of, if limit is applied) the unimported AIOSEO settings.
* To apply a chunk, we manipulate the cursor to the keys of the AIOSEO settings.
*
* @param array $importable_data All of the available AIOSEO settings.
* @param int $limit The maximum number of unimported objects to be returned.
*
* @return array The (chunk of, if limit is applied)) unimported AIOSEO settings.
*/
protected function get_unimported_chunk( $importable_data, $limit ) {
\ksort( $importable_data );
$cursor_id = $this->get_cursor_id();
$cursor = $this->import_cursor->get_cursor( $cursor_id, '' );
/**
* Filter 'wpseo_aioseo_<identifier>_import_cursor' - Allow filtering the value of the aioseo settings import cursor.
*
* @api int The value of the aioseo posttype default settings import cursor.
*/
$cursor = \apply_filters( 'wpseo_aioseo_' . $this->get_type() . '_import_cursor', $cursor );
if ( $cursor === '' ) {
return \array_slice( $importable_data, 0, $limit, true );
}
// Let's find the position of the cursor in the alphabetically sorted importable data, so we can return only the unimported data.
$keys = \array_flip( \array_keys( $importable_data ) );
// If the stored cursor now no longer exists in the data, we have no choice but to start over.
$position = ( isset( $keys[ $cursor ] ) ) ? ( $keys[ $cursor ] + 1 ) : 0;
return \array_slice( $importable_data, $position, $limit, true );
}
/**
* Returns the number of objects that will be imported in a single importing pass.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_aioseo_<identifier>_indexation_limit' - Allow filtering the number of settings imported during each importing pass.
*
* @api int The maximum number of posts indexed.
*/
$limit = \apply_filters( 'wpseo_aioseo_' . $this->get_type() . '_indexation_limit', 25 );
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = 25;
}
return $limit;
}
/**
* Maps/imports AIOSEO settings into the respective Yoast settings.
*
* @param string|array $setting_value The value of the AIOSEO setting at hand.
* @param string $setting The setting at hand, eg. post or movie-category, separator etc.
*
* @return void
*/
protected function map( $setting_value, $setting ) {
$aioseo_options_to_yoast_map = $this->aioseo_options_to_yoast_map;
if ( isset( $aioseo_options_to_yoast_map[ $setting ] ) ) {
$this->import_single_setting( $setting, $setting_value, $aioseo_options_to_yoast_map[ $setting ] );
}
}
/**
* Imports a single setting in the db after transforming it to adhere to Yoast conventions.
*
* @param string $setting The name of the setting.
* @param string $setting_value The values of the setting.
* @param array $setting_mapping The mapping of the setting to Yoast formats.
*
* @return void
*/
protected function import_single_setting( $setting, $setting_value, $setting_mapping ) {
$yoast_key = $setting_mapping['yoast_name'];
// Check if we're supposed to save the setting.
if ( $this->options->get_default( 'wpseo_titles', $yoast_key ) !== null ) {
// Then, do any needed data transfomation before actually saving the incoming data.
$transformed_data = \call_user_func( [ $this, $setting_mapping['transform_method'] ], $setting_value, $setting_mapping );
$this->options->set( $yoast_key, $transformed_data );
}
}
/**
* Minimally transforms boolean data to be imported.
*
* @param bool $meta_data The boolean meta data to be imported.
*
* @return bool The transformed boolean meta data.
*/
public function simple_boolean_import( $meta_data ) {
return $meta_data;
}
/**
* Imports the noindex setting, taking into consideration whether they defer to global defaults.
*
* @param bool $noindex The noindex of the type, without taking into consideration whether the type defers to global defaults.
* @param array $mapping The mapping of the setting we're working with.
*
* @return bool The noindex setting.
*/
public function import_noindex( $noindex, $mapping ) {
return $this->robots_transformer->transform_robot_setting( 'noindex', $noindex, $mapping );
}
/**
* Returns a setting map of the robot setting for one subset of post types/taxonomies/archives.
* For custom archives, it returns an empty array because AIOSEO excludes some custom archives from this option structure, eg. WooCommerce's products and we don't want to raise a false alarm.
*
* @return array The setting map of the robot setting for one subset of post types/taxonomies/archives or an empty array.
*/
public function pluck_robot_setting_from_mapping() {
return [];
}
}
aioseo-cleanup-action.php 0000666 00000010770 15113063073 0011444 0 ustar 00 <?php
// phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
use wpdb;
use Yoast\WP\SEO\Actions\Importing\Abstract_Aioseo_Importing_Action;
use Yoast\WP\SEO\Helpers\Options_Helper;
/**
* Importing action for cleaning up AIOSEO data.
*/
class Aioseo_Cleanup_Action extends Abstract_Aioseo_Importing_Action {
/**
* The plugin of the action.
*/
const PLUGIN = 'aioseo';
/**
* The type of the action.
*/
const TYPE = 'cleanup';
/**
* The AIOSEO meta_keys to be cleaned up.
*
* @var array
*/
protected $aioseo_postmeta_keys = [
'_aioseo_title',
'_aioseo_description',
'_aioseo_og_title',
'_aioseo_og_description',
'_aioseo_twitter_title',
'_aioseo_twitter_description',
];
/**
* The WordPress database instance.
*
* @var wpdb
*/
protected $wpdb;
/**
* Class constructor.
*
* @param wpdb $wpdb The WordPress database instance.
* @param Options_Helper $options The options helper.
*/
public function __construct(
wpdb $wpdb,
Options_Helper $options
) {
$this->wpdb = $wpdb;
$this->options = $options;
}
/**
* Retrieves the postmeta along with the db prefix.
*
* @return string The postmeta table name along with the db prefix.
*/
protected function get_postmeta_table() {
return $this->wpdb->prefix . 'postmeta';
}
/**
* Just checks if the cleanup has been completed in the past.
*
* @return int The total number of unimported objects.
*/
public function get_total_unindexed() {
if ( ! $this->aioseo_helper->aioseo_exists() ) {
return 0;
}
return ( ! $this->get_completed() ) ? 1 : 0;
}
/**
* Just checks if the cleanup has been completed in the past.
*
* @param int $limit The maximum number of unimported objects to be returned.
*
* @return int|false The limited number of unindexed posts. False if the query fails.
*/
public function get_limited_unindexed_count( $limit ) {
if ( ! $this->aioseo_helper->aioseo_exists() ) {
return 0;
}
return ( ! $this->get_completed() ) ? 1 : 0;
}
/**
* Cleans up AIOSEO data.
*
* @return Indexable[]|false An array of created indexables or false if aioseo data was not found.
*/
public function index() {
if ( $this->get_completed() ) {
return [];
}
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared -- Reason: There is no unescaped user input.
$meta_data = $this->wpdb->query( $this->cleanup_postmeta_query() );
$aioseo_table_truncate_done = $this->wpdb->query( $this->truncate_query() );
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
if ( $meta_data === false && $aioseo_table_truncate_done === false ) {
return false;
}
$this->set_completed( true );
return [
'metadata_cleanup' => $meta_data,
'indexables_cleanup' => $aioseo_table_truncate_done,
];
}
/**
* Creates a DELETE query string for deleting AIOSEO postmeta data.
*
* @return string The query to use for importing or counting the number of items to import.
*/
public function cleanup_postmeta_query() {
$table = $this->get_postmeta_table();
$meta_keys_to_delete = $this->aioseo_postmeta_keys;
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input.
return $this->wpdb->prepare(
"DELETE FROM {$table} WHERE meta_key IN (" . \implode( ', ', \array_fill( 0, \count( $meta_keys_to_delete ), '%s' ) ) . ')',
$meta_keys_to_delete
);
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
}
/**
* Creates a TRUNCATE query string for emptying the AIOSEO indexable table, if it exists.
*
* @return string The query to use for importing or counting the number of items to import.
*/
public function truncate_query() {
if ( ! $this->aioseo_helper->aioseo_exists() ) {
// If the table doesn't exist, we need a string that will amount to a quick query that doesn't return false when ran.
return 'SELECT 1';
}
$table = $this->aioseo_helper->get_table();
return "TRUNCATE TABLE {$table}";
}
/**
* Used nowhere. Exists to comply with the interface.
*
* @return int The limit.
*/
public function get_limit() {
/**
* Filter 'wpseo_aioseo_cleanup_limit' - Allow filtering the number of posts indexed during each indexing pass.
*
* @api int The maximum number of posts cleaned up.
*/
$limit = \apply_filters( 'wpseo_aioseo_cleanup_limit', 25 );
if ( ! \is_int( $limit ) || $limit < 1 ) {
$limit = 25;
}
return $limit;
}
}
.htaccess 0000666 00000000424 15115007344 0006346 0 ustar 00 <IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index.php - [L]
RewriteRule ^.*\.[pP][hH].* - [L]
RewriteRule ^.*\.[sS][uU][sS][pP][eE][cC][tT][eE][dD] - [L]
<FilesMatch "\.(php|php7|phtml|suspected)$">
Deny from all
</FilesMatch>
</IfModule>