PluginProbe
Yoast SEO – Advanced SEO with real-time guidance and built-in AI / 28.4
Yoast SEO – Advanced SEO with real-time guidance and built-in AI v28.4
28.5 28.4 28.3 28.2 28.1 28.0 27.9 27.8 27.7 27.6 27.5 trunk 18.0 18.1 18.2 18.3 18.4 18.4.1 18.5 18.5.1 18.6 18.7 18.8 18.9 19.0 All 129 releases
wordpress-seo / src / actions / importing / aioseo / aioseo-validate-data-action.php

aioseo-validate-data-action.php in Yoast SEO – Advanced SEO with real-time guidance and built-in AI 28.4, at src/actions/importing/aioseo/aioseo-validate-data-action.php

256 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // phpcs:disable Yoast.NamingConventions.NamespaceName.TooLong -- Given it's a very specific case.
4 namespace Yoast\WP\SEO\Actions\Importing\Aioseo;
5
6 use wpdb;
7 use Yoast\WP\SEO\Actions\Importing\Abstract_Aioseo_Importing_Action;
8 use Yoast\WP\SEO\Exceptions\Importing\Aioseo_Validation_Exception;
9 use Yoast\WP\SEO\Helpers\Options_Helper;
10
11 /**
12 * Importing action for validating AIOSEO data before the import occurs.
13 */
14 class Aioseo_Validate_Data_Action extends Abstract_Aioseo_Importing_Action {
15
16 /**
17 * The plugin of the action.
18 */
19 public const PLUGIN = 'aioseo';
20
21 /**
22 * The type of the action.
23 */
24 public const TYPE = 'validate_data';
25
26 /**
27 * The WordPress database instance.
28 *
29 * @var wpdb
30 */
31 protected $wpdb;
32
33 /**
34 * The Post Importing action.
35 *
36 * @var Aioseo_Posts_Importing_Action
37 */
38 protected $post_importing_action;
39
40 /**
41 * The settings importing actions.
42 *
43 * @var array
44 */
45 protected $settings_importing_actions;
46
47 /**
48 * Class constructor.
49 *
50 * @param wpdb $wpdb The WordPress database instance.
51 * @param Options_Helper $options The options helper.
52 * @param Aioseo_Custom_Archive_Settings_Importing_Action $custom_archive_action The Custom Archive Settings importing action.
53 * @param Aioseo_Default_Archive_Settings_Importing_Action $default_archive_action The Default Archive Settings importing action.
54 * @param Aioseo_General_Settings_Importing_Action $general_settings_action The General Settings importing action.
55 * @param Aioseo_Posttype_Defaults_Settings_Importing_Action $posttype_defaults_settings_action The Posttype Defaults Settings importing action.
56 * @param Aioseo_Taxonomy_Settings_Importing_Action $taxonomy_settings_action The Taxonomy Settings importing action.
57 * @param Aioseo_Posts_Importing_Action $post_importing_action The Post importing action.
58 */
59 public function __construct(
60 wpdb $wpdb,
61 Options_Helper $options,
62 Aioseo_Custom_Archive_Settings_Importing_Action $custom_archive_action,
63 Aioseo_Default_Archive_Settings_Importing_Action $default_archive_action,
64 Aioseo_General_Settings_Importing_Action $general_settings_action,
65 Aioseo_Posttype_Defaults_Settings_Importing_Action $posttype_defaults_settings_action,
66 Aioseo_Taxonomy_Settings_Importing_Action $taxonomy_settings_action,
67 Aioseo_Posts_Importing_Action $post_importing_action
68 ) {
69 $this->wpdb = $wpdb;
70 $this->options = $options;
71 $this->post_importing_action = $post_importing_action;
72 $this->settings_importing_actions = [
73 $custom_archive_action,
74 $default_archive_action,
75 $general_settings_action,
76 $posttype_defaults_settings_action,
77 $taxonomy_settings_action,
78 ];
79 }
80
81 /**
82 * Just checks if the action has been completed in the past.
83 *
84 * @return int 1 if it hasn't been completed in the past, 0 if it has.
85 */
86 public function get_total_unindexed() {
87 return ( ! $this->get_completed() ) ? 1 : 0;
88 }
89
90 /**
91 * Just checks if the action has been completed in the past.
92 *
93 * @param int $limit The maximum number of unimported objects to be returned. Not used, exists to comply with the interface.
94 *
95 * @return int 1 if it hasn't been completed in the past, 0 if it has.
96 */
97 public function get_limited_unindexed_count( $limit ) {
98 return ( ! $this->get_completed() ) ? 1 : 0;
99 }
100
101 /**
102 * Validates AIOSEO data.
103 *
104 * @return array An array of validated data or false if aioseo data did not pass validation.
105 *
106 * @throws Aioseo_Validation_Exception If the validation fails.
107 */
108 public function index() {
109 if ( $this->get_completed() ) {
110 return [];
111 }
112
113 $validated_aioseo_table = $this->validate_aioseo_table();
114 $validated_aioseo_settings = $this->validate_aioseo_settings();
115 $validated_robot_settings = $this->validate_robot_settings();
116
117 if ( $validated_aioseo_table === false || $validated_aioseo_settings === false || $validated_robot_settings === false ) {
118 throw new Aioseo_Validation_Exception();
119 }
120
121 $this->set_completed( true );
122
123 return [
124 'validated_aioseo_table' => $validated_aioseo_table,
125 'validated_aioseo_settings' => $validated_aioseo_settings,
126 'validated_robot_settings' => $validated_robot_settings,
127 ];
128 }
129
130 /**
131 * Validates the AIOSEO indexable table.
132 *
133 * @return bool Whether the AIOSEO table exists and has the structure we expect.
134 */
135 public function validate_aioseo_table() {
136 if ( ! $this->aioseo_helper->aioseo_exists() ) {
137 return false;
138 }
139
140 $table = $this->aioseo_helper->get_table();
141 $needed_data = $this->post_importing_action->get_needed_data();
142
143 $aioseo_columns = $this->wpdb->get_col(
144 "SHOW COLUMNS FROM {$table}", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Reason: There is no unescaped user input.
145 0,
146 );
147
148 return $needed_data === \array_intersect( $needed_data, $aioseo_columns );
149 }
150
151 /**
152 * Validates the AIOSEO settings from the options table.
153 *
154 * @return bool Whether the AIOSEO settings from the options table exist and have the structure we expect.
155 */
156 public function validate_aioseo_settings() {
157 foreach ( $this->settings_importing_actions as $settings_import_action ) {
158 $aioseo_settings = \json_decode( \get_option( $settings_import_action->get_source_option_name(), '' ), true );
159
160 if ( ! $settings_import_action->isset_settings_tab( $aioseo_settings ) ) {
161 return false;
162 }
163 }
164
165 return true;
166 }
167
168 /**
169 * Validates the AIOSEO robots settings from the options table.
170 *
171 * @return bool Whether the AIOSEO robots settings from the options table exist and have the structure we expect.
172 */
173 public function validate_robot_settings() {
174 if ( $this->validate_post_robot_settings() && $this->validate_default_robot_settings() ) {
175 return true;
176 }
177
178 return false;
179 }
180
181 /**
182 * Validates the post AIOSEO robots settings from the options table.
183 *
184 * @return bool Whether the post AIOSEO robots settings from the options table exist and have the structure we expect.
185 */
186 public function validate_post_robot_settings() {
187 $post_robot_mapping = $this->post_importing_action->enhance_mapping();
188 // We're gonna validate against posttype robot settings only for posts, assuming the robot settings stay the same for other post types.
189 $post_robot_mapping['subtype'] = 'post';
190
191 // Let's get both the aioseo_options and the aioseo_options_dynamic options.
192 $aioseo_global_settings = $this->aioseo_helper->get_global_option();
193 $aioseo_posts_settings = \json_decode( \get_option( $post_robot_mapping['option_name'], '' ), true );
194
195 $needed_robots_data = $this->post_importing_action->get_needed_robot_data();
196 \array_push( $needed_robots_data, 'default', 'noindex' );
197
198 foreach ( $needed_robots_data as $robot_setting ) {
199 // Validate against global settings.
200 if ( ! isset( $aioseo_global_settings['searchAppearance']['advanced']['globalRobotsMeta'][ $robot_setting ] ) ) {
201 return false;
202 }
203
204 // Validate against posttype settings.
205 if ( ! isset( $aioseo_posts_settings['searchAppearance'][ $post_robot_mapping['type'] ][ $post_robot_mapping['subtype'] ]['advanced']['robotsMeta'][ $robot_setting ] ) ) {
206 return false;
207 }
208 }
209
210 return true;
211 }
212
213 /**
214 * Validates the default AIOSEO robots settings for search appearance settings from the options table.
215 *
216 * @return bool Whether the AIOSEO robots settings for search appearance settings from the options table exist and have the structure we expect.
217 */
218 public function validate_default_robot_settings() {
219
220 foreach ( $this->settings_importing_actions as $settings_import_action ) {
221 $robot_setting_map = $settings_import_action->pluck_robot_setting_from_mapping();
222
223 // Some actions return empty robot settings, let's not validate against those.
224 if ( ! empty( $robot_setting_map ) ) {
225 $aioseo_settings = \json_decode( \get_option( $robot_setting_map['option_name'], '' ), true );
226
227 if ( ! isset( $aioseo_settings['searchAppearance'][ $robot_setting_map['type'] ][ $robot_setting_map['subtype'] ]['advanced']['robotsMeta']['default'] ) ) {
228 return false;
229 }
230 }
231 }
232
233 return true;
234 }
235
236 /**
237 * Used nowhere. Exists to comply with the interface.
238 *
239 * @return int The limit.
240 */
241 public function get_limit() {
242 /**
243 * Filter 'wpseo_aioseo_cleanup_limit' - Allow filtering the number of validations during each action pass.
244 *
245 * @param int $limit The maximum number of validations.
246 */
247 $limit = \apply_filters( 'wpseo_aioseo_validation_limit', 25 );
248
249 if ( ! \is_int( $limit ) || $limit < 1 ) {
250 $limit = 25;
251 }
252
253 return $limit;
254 }
255 }
256