���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC ‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT h25jguaT5*!importing-indexation-action-interface.php000066600000001445151734252610014654 0ustar00wpdb = $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. * * @param int $limit The maximum number of validations. */ $limit = \apply_filters( 'wpseo_aioseo_validation_limit', 25 ); if ( ! \is_int( $limit ) || $limit < 1 ) { $limit = 25; } return $limit; } } aioseo/abstract-aioseo-settings-importing-action.php000066600000024610151734252610016750 0ustar00import_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__import_cursor' - Allow filtering the value of the aioseo settings import cursor. * * @param int $import_cursor 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__indexation_limit' - Allow filtering the number of settings imported during each importing pass. * * @param int $max_posts 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/aioseo-posttype-defaults-settings-importing-action.php000066600000005540151734252610020642 0ustar00 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/aioseo-general-settings-importing-action.php000066600000013752151734252610016567 0ustar00image = $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'; } } } aioseo/aioseo-posts-importing-action.php000066600000055143151734252610014464 0ustar00>> */ 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 ); $this->indexable_helper->save_indexable( $indexable ); // 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. * * @param int $max_posts 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|false $limit The maximum number of unimported objects to be returned. * False for "no limit". * @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. * * @param int $import_cursor 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/aioseo-cleanup-action.php000066600000011025151734252610012724 0ustar00 */ 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. * * @param int $max_posts 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; } } aioseo/aioseo-default-archive-settings-importing-action.php000066600000005610151734252610020207 0ustar00aioseo_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/aioseo-taxonomy-settings-importing-action.php000066600000007645151734252610017034 0ustar00 '', // 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/aioseo-custom-archive-settings-importing-action.php000066600000007366151734252610020107 0ustar00post_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', ]; } } } } deactivate-conflicting-plugins-action.php000066600000010417151734252610014632 0ustar00conflicting_plugins = $conflicting_plugins_service; $this->detected_plugins = []; } /** * Get the total number of conflicting plugins. * * @return int */ public function get_total_unindexed() { return \count( $this->get_detected_plugins() ); } /** * Returns whether the updated importer framework is enabled. * * @return bool True if the updated importer framework is enabled. */ public function is_enabled() { $updated_importer_framework_conditional = \YoastSEO()->classes->get( Updated_Importer_Framework_Conditional::class ); return $updated_importer_framework_conditional->is_met(); } /** * Deactivate conflicting plugins. * * @return array */ public function index() { $detected_plugins = $this->get_detected_plugins(); $this->conflicting_plugins->deactivate_conflicting_plugins( $detected_plugins ); // We need to conform to the interface, so we report that no indexables were created. return []; } /** * {@inheritDoc} */ public function get_limit() { return \count( Conflicting_Plugins::all_plugins() ); } /** * Returns the total number of unindexed objects up to a limit. * * @param int $limit The maximum. * * @return int The total number of unindexed objects. */ public function get_limited_unindexed_count( $limit ) { $count = \count( $this->get_detected_plugins() ); return ( $count <= $limit ) ? $count : $limit; } /** * Returns all detected plugins. * * @return array The detected plugins. */ protected function get_detected_plugins() { // The active plugins won't change much. We can reuse the result for the duration of the request. if ( \count( $this->detected_plugins ) < 1 ) { $this->detected_plugins = $this->conflicting_plugins->detect_conflicting_plugins(); } return $this->detected_plugins; } }