class-adbc-automation-validator.php
7 months ago
class-adbc-common-validator.php
2 months ago
class-adbc-selected-items-validator.php
2 months ago
class-adbc-settings-validator.php
2 months ago
class-adbc-tables-validator.php
7 months ago
class-adbc-common-validator.php
577 lines
| 1 | <?php |
| 2 | |
| 3 | // Exit if accessed directly |
| 4 | if ( ! defined( 'ABSPATH' ) ) |
| 5 | exit; |
| 6 | |
| 7 | /** |
| 8 | * ADBC Common validator class. |
| 9 | * |
| 10 | * This class provides functions to validate and sanitize general data used in the plugin. |
| 11 | */ |
| 12 | class ADBC_Common_Validator { |
| 13 | |
| 14 | /** |
| 15 | * Sanitize the DataTable filters sent by the user. |
| 16 | * |
| 17 | * @param WP_REST_Request $filters_request The filters request. |
| 18 | * |
| 19 | * @return array The sanitized filters. |
| 20 | */ |
| 21 | public static function sanitize_filters( WP_REST_Request $filters_request ) { |
| 22 | |
| 23 | $sanitized_filters = [ |
| 24 | 'size' => sanitize_key( $filters_request->get_param( 'size' ) ), |
| 25 | 'size_unit' => sanitize_text_field( $filters_request->get_param( 'sizeUnit' ) ), // KB, MB, GB |
| 26 | 'table_status' => sanitize_key( $filters_request->get_param( 'tableStatus' ) ), |
| 27 | 'prefix_status' => sanitize_key( $filters_request->get_param( 'prefixStatus' ) ), |
| 28 | 'belongs_to' => sanitize_key( $filters_request->get_param( 'belongsTo' ) ), |
| 29 | 'current_page' => sanitize_key( $filters_request->get_param( 'currentPage' ) ), |
| 30 | 'items_per_page' => sanitize_key( $filters_request->get_param( 'itemsPerPage' ) ), |
| 31 | 'sort_by' => sanitize_text_field( $filters_request->get_param( 'sortBy' ) ), |
| 32 | 'sort_order' => sanitize_text_field( $filters_request->get_param( 'sortOrder' ) ), |
| 33 | 'items_type' => $filters_request->get_param( 'itemsType' ), |
| 34 | 'expired' => sanitize_key( $filters_request->get_param( 'expired' ) ), |
| 35 | 'duplicated' => sanitize_key( $filters_request->get_param( 'duplicated' ) ), |
| 36 | 'unused' => sanitize_key( $filters_request->get_param( 'unused' ) ), |
| 37 | 'has_action' => sanitize_key( $filters_request->get_param( 'hasAction' ) ), |
| 38 | 'search_for' => $filters_request->get_param( 'search' ), // Don't sanitize this to not break the search query. We assure security later. |
| 39 | 'search_in' => sanitize_key( $filters_request->get_param( 'searchIn' ) ), |
| 40 | 'site_id' => sanitize_key( $filters_request->get_param( 'site' ) ), |
| 41 | 'belongs_to_plugin_slug' => sanitize_text_field( $filters_request->get_param( 'belongsToPluginSlug' ) ), |
| 42 | 'belongs_to_theme_slug' => sanitize_text_field( $filters_request->get_param( 'belongsToThemeSlug' ) ), |
| 43 | 'show_manual_corrections_only' => $filters_request->get_param( 'showManualCorrectionsOnly' ), |
| 44 | 'autoload' => sanitize_key( $filters_request->get_param( 'autoload' ) ), |
| 45 | 'start_date' => $filters_request->get_param( 'startDate' ), |
| 46 | 'end_date' => $filters_request->get_param( 'endDate' ), |
| 47 | 'frequency' => sanitize_key( $filters_request->get_param( 'frequency' ) ), |
| 48 | 'interval' => $filters_request->get_param( 'interval' ), |
| 49 | 'post_types_posts_count' => sanitize_key( $filters_request->get_param( 'postTypesPostsCount' ) ), |
| 50 | 'post_types_visibility' => sanitize_key( $filters_request->get_param( 'postTypesVisibility' ) ), |
| 51 | ]; |
| 52 | |
| 53 | // Sanitize and validate common filters |
| 54 | $sanitized_filters['size'] = absint( $sanitized_filters['size'] ); |
| 55 | $sanitized_filters['size_unit'] = in_array( $sanitized_filters['size_unit'], [ 'B', 'KB', 'MB', 'GB' ] ) ? $sanitized_filters['size_unit'] : 'KB'; |
| 56 | $sanitized_filters['table_status'] = in_array( $sanitized_filters['table_status'], [ 'all', 'to_optimize', 'to_repair' ] ) ? $sanitized_filters['table_status'] : 'all'; |
| 57 | $sanitized_filters['prefix_status'] = in_array( $sanitized_filters['prefix_status'], [ 'all', 'valid_prefix', 'invalid_prefix' ] ) ? $sanitized_filters['prefix_status'] : 'all'; |
| 58 | $sanitized_filters['belongs_to'] = |
| 59 | in_array( $sanitized_filters['belongs_to'], [ 'all', 'not_scanned', 'plugins', 'themes', 'wordpress', 'orphans', 'unknown' ] ) ? $sanitized_filters['belongs_to'] : 'all'; |
| 60 | $sanitized_filters['current_page'] = self::sanitize_validate_current_page( $sanitized_filters['current_page'] ); |
| 61 | $sanitized_filters['items_per_page'] = self::sanitize_validate_limit( $sanitized_filters['items_per_page'] ); |
| 62 | // $sanitized_filters['sort_by'] SQL queries will check if the column exists. |
| 63 | $sanitized_filters['sort_order'] = in_array( $sanitized_filters['sort_order'], [ 'ASC', 'DESC' ] ) ? $sanitized_filters['sort_order'] : 'ASC'; |
| 64 | $sanitized_filters['items_type'] = self::sanitize_items_type( $sanitized_filters['items_type'] ); |
| 65 | $sanitized_filters['expired'] = in_array( $sanitized_filters['expired'], [ 'all', 'yes', 'no' ], true ) ? $sanitized_filters['expired'] : 'all'; |
| 66 | $sanitized_filters['duplicated'] = in_array( $sanitized_filters['duplicated'], [ 'all', 'yes', 'no' ], true ) ? $sanitized_filters['duplicated'] : 'all'; |
| 67 | $sanitized_filters['unused'] = in_array( $sanitized_filters['unused'], [ 'all', 'yes', 'no' ], true ) ? $sanitized_filters['unused'] : 'all'; |
| 68 | $sanitized_filters['has_action'] = in_array( $sanitized_filters['has_action'], [ 'all', 'yes', 'no' ], true ) ? $sanitized_filters['has_action'] : 'all'; |
| 69 | $sanitized_filters['autoload'] = in_array( $sanitized_filters['autoload'], [ 'all', 'yes', 'no' ] ) ? $sanitized_filters['autoload'] : 'all'; |
| 70 | |
| 71 | // In free set premium filters to default values since they are not supported in free version. |
| 72 | if ( ADBC_VERSION_TYPE === "FREE" ) { |
| 73 | $sanitized_filters['search_for'] = ''; |
| 74 | $sanitized_filters['search_in'] = 'name'; |
| 75 | $sanitized_filters['site_id'] = 'all'; |
| 76 | $sanitized_filters['belongs_to_plugin_slug'] = ''; |
| 77 | $sanitized_filters['belongs_to_theme_slug'] = ''; |
| 78 | $sanitized_filters['show_manual_corrections_only'] = false; |
| 79 | $sanitized_filters['start_date'] = null; |
| 80 | $sanitized_filters['end_date'] = null; |
| 81 | $sanitized_filters['frequency'] = 'all'; |
| 82 | $sanitized_filters['interval'] = 'all'; |
| 83 | $sanitized_filters['post_types_posts_count'] = 0; |
| 84 | $sanitized_filters['post_types_visibility'] = 'all'; |
| 85 | } else { |
| 86 | // In premium, sanitize the premium filters. |
| 87 | ADBC_Premium_Common_Validator::sanitize_filters( $sanitized_filters ); |
| 88 | } |
| 89 | |
| 90 | return $sanitized_filters; |
| 91 | |
| 92 | } |
| 93 | |
| 94 | /** |
| 95 | * Checks if the given value equals "0" or "1". |
| 96 | * |
| 97 | * @param string $key The key of the value to check (not used in this method). |
| 98 | * @param string $value The value to check. |
| 99 | * @return bool True if the value equals "0" or "1", false otherwise. |
| 100 | */ |
| 101 | public static function is_string_equals_0_or_1( $key, $value ) { |
| 102 | return ( $value === "0" || $value === "1" ); |
| 103 | } |
| 104 | |
| 105 | /** |
| 106 | * Checks if the given value is a valid number that is between the specified min and max values. |
| 107 | * |
| 108 | * @param string $value The value to check. |
| 109 | * @param int $min The minimum value. |
| 110 | * @param int $max The maximum value. |
| 111 | * @return bool True if the value is a number between min and max, false otherwise. |
| 112 | */ |
| 113 | public static function is_number_between_min_and_max( $value, $min, $max ) { |
| 114 | return ( is_numeric( $value ) && $value >= $min && $value <= $max ); |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Validates the action data for the given action and items type sent by the user. |
| 119 | * |
| 120 | * @param string $action The action to validate (e.g., 'optimize_tables', 'delete_options'...). |
| 121 | * @param string $items_type The type of items (e.g., 'tables', 'options'...). |
| 122 | * @param WP_REST_Request $request_data The request data containing the action and selected items, etc. sent by the user to the endpoint. |
| 123 | * @param bool $keep_prefix Whether to keep the prefix in the returned table names (used only for tables). |
| 124 | * |
| 125 | * @return array|string An array of valid items or an error message if validation fails. |
| 126 | */ |
| 127 | public static function validate_endpoint_action_data( $action, $items_type, $request_data, $keep_prefix = true ) { |
| 128 | |
| 129 | // Get params |
| 130 | $action_type = $request_data->get_param( 'actionType' ); |
| 131 | $selected_items = $request_data->get_param( 'selectedItems' ); |
| 132 | |
| 133 | // Check action is valid |
| 134 | if ( $action_type !== $action ) |
| 135 | return "Invalid action."; |
| 136 | |
| 137 | // Delete invalid items from the selected tables and return valid ones. |
| 138 | $selected_items = ADBC_Selected_Items_Validator::remove_invalid_selected_items( $items_type, $selected_items, $keep_prefix ); |
| 139 | |
| 140 | // Check empty. |
| 141 | if ( empty( $selected_items ) ) |
| 142 | return "No items to process"; |
| 143 | |
| 144 | return $selected_items; |
| 145 | } |
| 146 | |
| 147 | /** |
| 148 | * Validates the data sent by the user to get_column_value_from_table endpoint. |
| 149 | * |
| 150 | * @param string $items_type The type of items (e.g., 'options', 'transients'). |
| 151 | * @param int $site_id The site ID. |
| 152 | * @param int $row_id The row ID to get the value from. |
| 153 | * @param string $transient_found_in The transient found in, if applicable (e.g., 'options', 'sitemeta'). |
| 154 | * |
| 155 | * @return array|string An array with success status, message, and data or an error message if validation fails. |
| 156 | */ |
| 157 | public static function validate_get_column_value_endpoint_data( $items_type, $site_id, $row_id, $transient_found_in ) { |
| 158 | |
| 159 | $answer = [ "success" => false, "message" => "", "data" => []]; |
| 160 | |
| 161 | // Check items type is valid |
| 162 | if ( ! in_array( $items_type, [ 'options', 'transients', 'posts_meta', 'users_meta', 'revisions', 'auto_drafts', 'trashed_posts', 'unapproved_comments', 'spam_comments', 'trashed_comments', 'pingbacks', 'trackbacks', 'unused_postmeta', 'duplicated_postmeta', 'unused_commentmeta', 'duplicated_commentmeta', 'unused_usermeta', 'duplicated_usermeta', 'unused_termmeta', 'duplicated_termmeta', 'unused_relationships', 'expired_transients', 'oembed_caches', 'actionscheduler_completed_actions', 'actionscheduler_failed_actions', 'actionscheduler_canceled_actions', 'actionscheduler_completed_logs', 'actionscheduler_failed_logs', 'actionscheduler_canceled_logs', 'actionscheduler_orphan_logs' ], true ) ) |
| 163 | $answer['message'] = "Invalid items type."; |
| 164 | |
| 165 | // Check site ID is valid |
| 166 | if ( ! is_numeric( $site_id ) || $site_id < 0 ) |
| 167 | $answer['message'] = "Invalid site ID."; |
| 168 | |
| 169 | // Check row ID is valid |
| 170 | if ( ! is_numeric( $row_id ) || $row_id < 0 ) |
| 171 | $answer['message'] = "Invalid row ID."; |
| 172 | |
| 173 | // Check if transient_found_in is valid |
| 174 | if ( $items_type === 'expired_transients' && ! in_array( $transient_found_in, [ 'options', 'sitemeta' ], true ) ) |
| 175 | $answer['message'] = "Invalid transient_found_in parameter."; |
| 176 | |
| 177 | // Get the site prefix |
| 178 | $site_prefix = ADBC_Sites::instance()->get_prefix_from_site_id( $site_id ); |
| 179 | if ( $site_prefix === null ) |
| 180 | $answer['message'] = "Cannot find the site prefix."; |
| 181 | |
| 182 | // Check if there is an error |
| 183 | if ( ! empty( $answer['message'] ) ) |
| 184 | return $answer; |
| 185 | |
| 186 | // Prepare the table name and column names based on the items type |
| 187 | switch ( $items_type ) { |
| 188 | case 'options': |
| 189 | $answer['data'] = [ |
| 190 | 'table_name' => $site_prefix . 'options', |
| 191 | 'column_id' => "option_id", |
| 192 | 'column_name' => "option_value" |
| 193 | ]; |
| 194 | break; |
| 195 | |
| 196 | case 'posts_meta': |
| 197 | $answer['data'] = [ |
| 198 | 'table_name' => $site_prefix . 'postmeta', |
| 199 | 'column_id' => "meta_id", |
| 200 | 'column_name' => "meta_value" |
| 201 | ]; |
| 202 | break; |
| 203 | |
| 204 | case 'users_meta': |
| 205 | $answer['data'] = [ |
| 206 | 'table_name' => $site_prefix . 'usermeta', |
| 207 | 'column_id' => "umeta_id", |
| 208 | 'column_name' => "meta_value" |
| 209 | ]; |
| 210 | break; |
| 211 | |
| 212 | case 'revisions': |
| 213 | case 'auto_drafts': |
| 214 | case 'trashed_posts': |
| 215 | $answer['data'] = [ |
| 216 | 'table_name' => $site_prefix . 'posts', |
| 217 | 'column_id' => "ID", |
| 218 | 'column_name' => "post_content" |
| 219 | ]; |
| 220 | break; |
| 221 | |
| 222 | case 'unapproved_comments': |
| 223 | case 'spam_comments': |
| 224 | case 'trashed_comments': |
| 225 | case 'pingbacks': |
| 226 | case 'trackbacks': |
| 227 | $answer['data'] = [ |
| 228 | 'table_name' => $site_prefix . 'comments', |
| 229 | 'column_id' => "comment_ID", |
| 230 | 'column_name' => "comment_content" |
| 231 | ]; |
| 232 | break; |
| 233 | |
| 234 | case 'unused_postmeta': |
| 235 | case 'duplicated_postmeta': |
| 236 | case 'oembed_caches': |
| 237 | $answer['data'] = [ |
| 238 | 'table_name' => $site_prefix . 'postmeta', |
| 239 | 'column_id' => "meta_id", |
| 240 | 'column_name' => "meta_value" |
| 241 | ]; |
| 242 | break; |
| 243 | |
| 244 | case 'unused_commentmeta': |
| 245 | case 'duplicated_commentmeta': |
| 246 | $answer['data'] = [ |
| 247 | 'table_name' => $site_prefix . 'commentmeta', |
| 248 | 'column_id' => "meta_id", |
| 249 | 'column_name' => "meta_value" |
| 250 | ]; |
| 251 | break; |
| 252 | |
| 253 | case 'unused_termmeta': |
| 254 | case 'duplicated_termmeta': |
| 255 | $answer['data'] = [ |
| 256 | 'table_name' => $site_prefix . 'termmeta', |
| 257 | 'column_id' => "meta_id", |
| 258 | 'column_name' => "meta_value" |
| 259 | ]; |
| 260 | break; |
| 261 | |
| 262 | case 'unused_usermeta': |
| 263 | case 'duplicated_usermeta': |
| 264 | $answer['data'] = [ |
| 265 | 'table_name' => $site_prefix . 'usermeta', |
| 266 | 'column_id' => "umeta_id", |
| 267 | 'column_name' => "meta_value" |
| 268 | ]; |
| 269 | break; |
| 270 | |
| 271 | case 'unused_relationships': |
| 272 | $answer['data'] = [ |
| 273 | 'table_name' => $site_prefix . 'term_relationships', |
| 274 | 'column_id' => "object_id", |
| 275 | 'column_name' => "term_order" |
| 276 | ]; |
| 277 | break; |
| 278 | |
| 279 | case 'expired_transients': |
| 280 | case 'transients': |
| 281 | switch ( $transient_found_in ) { |
| 282 | case 'sitemeta': |
| 283 | $answer['data'] = [ |
| 284 | 'table_name' => $site_prefix . 'sitemeta', |
| 285 | 'column_id' => "meta_id", |
| 286 | 'column_name' => "meta_value" |
| 287 | ]; |
| 288 | break; |
| 289 | case 'options': |
| 290 | $answer['data'] = [ |
| 291 | 'table_name' => $site_prefix . 'options', |
| 292 | 'column_id' => "option_id", |
| 293 | 'column_name' => "option_value" |
| 294 | ]; |
| 295 | break; |
| 296 | } |
| 297 | break; |
| 298 | |
| 299 | case 'actionscheduler_completed_actions': |
| 300 | case 'actionscheduler_failed_actions': |
| 301 | case 'actionscheduler_canceled_actions': |
| 302 | $answer['data'] = [ |
| 303 | 'table_name' => $site_prefix . 'actionscheduler_actions', |
| 304 | 'column_id' => "action_id", |
| 305 | 'column_name' => "args" |
| 306 | ]; |
| 307 | break; |
| 308 | case 'actionscheduler_completed_logs': |
| 309 | case 'actionscheduler_failed_logs': |
| 310 | case 'actionscheduler_canceled_logs': |
| 311 | case 'actionscheduler_orphan_logs': |
| 312 | $answer['data'] = [ |
| 313 | 'table_name' => $site_prefix . 'actionscheduler_logs', |
| 314 | 'column_id' => "log_id", |
| 315 | 'column_name' => "message" |
| 316 | ]; |
| 317 | break; |
| 318 | } |
| 319 | |
| 320 | $answer['success'] = true; |
| 321 | return $answer; |
| 322 | } |
| 323 | |
| 324 | /** |
| 325 | * Validates two optional dates for use as REST filter parameters. |
| 326 | * |
| 327 | * If only one date is valid, it is returned while the other slot is `null`. |
| 328 | * If both dates are present they must be chronological and, when `$max_days` |
| 329 | * is > 0, their span must not exceed that limit. |
| 330 | * |
| 331 | * @param string|null $start_date The start date in the specified format. |
| 332 | * @param string|null $end_date The end date in the specified format. |
| 333 | * @param string $date_format The date format to use for parsing the dates. |
| 334 | * @param int $max_days The maximum number of days allowed between the start and end dates. |
| 335 | * |
| 336 | * @return array [ start|null, end|null ] |
| 337 | */ |
| 338 | public static function validate_filter_date_range( $start_date = null, $end_date = null, $date_format = 'Y-m-d', $max_days = 0 ) { |
| 339 | |
| 340 | $result = [ null, null ]; |
| 341 | $start_obj = null; |
| 342 | $end_obj = null; |
| 343 | |
| 344 | /*— individually validate ------------------------------------------------*/ |
| 345 | if ( ! empty( $start_date ) ) { |
| 346 | $start_obj = ADBC_Common_Utils::parse_date( $start_date, $date_format ); |
| 347 | if ( $start_obj ) { |
| 348 | $result[0] = $start_obj->format( $date_format ); |
| 349 | } |
| 350 | } |
| 351 | if ( ! empty( $end_date ) ) { |
| 352 | $end_obj = ADBC_Common_Utils::parse_date( $end_date, $date_format ); |
| 353 | if ( $end_obj ) { |
| 354 | $result[1] = $end_obj->format( $date_format ); |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | /*— both dates supplied? apply cross checks ------------------------------*/ |
| 359 | if ( $start_obj && $end_obj ) { |
| 360 | // chronology |
| 361 | if ( $start_obj > $end_obj ) { |
| 362 | return [ null, null ]; |
| 363 | } |
| 364 | // length restriction |
| 365 | if ( $max_days > 0 && $start_obj->diff( $end_obj )->days > $max_days ) { |
| 366 | return [ null, null ]; |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | return $result; |
| 371 | |
| 372 | } |
| 373 | |
| 374 | /** |
| 375 | * Validates a *complete* date range. Anything off → `[null, null]`. |
| 376 | * |
| 377 | * Use when the caller must provide both dates and (optionally) stay within |
| 378 | * `$max_days`. |
| 379 | * |
| 380 | * @param string $start_date The start date in the specified format. |
| 381 | * @param string $end_date The end date in the specified format. |
| 382 | * @param string $date_format The date format to use for parsing the dates. |
| 383 | * @param int $max_days The maximum number of days allowed between the start and end dates. |
| 384 | * |
| 385 | * @return array [ start|null, end|null ] |
| 386 | */ |
| 387 | public static function validate_strict_date_range( $start_date, $end_date, $date_format = 'Y-m-d', $max_days = 0 ) { |
| 388 | |
| 389 | $invalid = [ null, null ]; |
| 390 | |
| 391 | /*— both dates must be present ------------------------------------------*/ |
| 392 | if ( empty( $start_date ) || empty( $end_date ) ) { |
| 393 | return $invalid; |
| 394 | } |
| 395 | |
| 396 | $start_obj = ADBC_Common_Utils::parse_date( $start_date, $date_format ); |
| 397 | $end_obj = ADBC_Common_Utils::parse_date( $end_date, $date_format ); |
| 398 | |
| 399 | if ( ! $start_obj || ! $end_obj ) { |
| 400 | return $invalid; |
| 401 | } |
| 402 | |
| 403 | /*— chronology and (optional) length ------------------------------------*/ |
| 404 | if ( $start_obj > $end_obj ) { |
| 405 | return $invalid; |
| 406 | } |
| 407 | if ( $max_days > 0 && $start_obj->diff( $end_obj )->days > $max_days ) { |
| 408 | return $invalid; |
| 409 | } |
| 410 | |
| 411 | return [ |
| 412 | $start_obj->format( $date_format ), |
| 413 | $end_obj->format( $date_format ), |
| 414 | ]; |
| 415 | |
| 416 | } |
| 417 | |
| 418 | /** |
| 419 | * Sanitize the items type sent by the user. |
| 420 | * |
| 421 | * @param string $items_type The items type. |
| 422 | * |
| 423 | * @return string The sanitized items type, empty string if invalid. |
| 424 | */ |
| 425 | public static function sanitize_items_type( $items_type ) { |
| 426 | |
| 427 | $items_type = sanitize_key( $items_type ); |
| 428 | |
| 429 | $valid_items = array_merge( |
| 430 | [ |
| 431 | 'options', |
| 432 | 'tables', |
| 433 | 'cron_jobs', |
| 434 | 'transients', |
| 435 | 'posts_meta', |
| 436 | 'users_meta', |
| 437 | 'post_types', |
| 438 | ], |
| 439 | ADBC_Cleanup_Type_Registry::get_all_items_type() |
| 440 | ); |
| 441 | |
| 442 | $valid_items_type = in_array( $items_type, $valid_items, true ); |
| 443 | |
| 444 | return $valid_items_type ? $items_type : ''; |
| 445 | |
| 446 | } |
| 447 | |
| 448 | /** |
| 449 | * Sanitize an array of items types sent by the user. |
| 450 | * |
| 451 | * @param array $items_types The array of items types. |
| 452 | * |
| 453 | * @return array The sanitized array of items types, empty array if all invalid. |
| 454 | */ |
| 455 | public static function sanitize_items_types( $items_types ) { |
| 456 | |
| 457 | if ( ! is_array( $items_types ) ) { |
| 458 | return []; |
| 459 | } |
| 460 | |
| 461 | $validated_items_types = []; |
| 462 | |
| 463 | foreach ( $items_types as $item_type ) { |
| 464 | $sanitized = self::sanitize_items_type( $item_type ); |
| 465 | if ( $sanitized !== '' ) { |
| 466 | $validated_items_types[] = $sanitized; |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | return $validated_items_types; |
| 471 | |
| 472 | } |
| 473 | |
| 474 | /** |
| 475 | * Validate the manual categorization sent by the user. |
| 476 | * |
| 477 | * @param string $manual_categorization The manual categorization. |
| 478 | * @return string|bool The error message if the manual categorization is invalid, true otherwise. |
| 479 | */ |
| 480 | public static function is_manual_categorization_valid( $manual_categorization ) { |
| 481 | |
| 482 | $generic_error_msg = "Invalid manual correction."; |
| 483 | |
| 484 | // Check if three keys exist in the manual categorization associative array: type, slug and send_to_server |
| 485 | if ( ! is_array( $manual_categorization ) || |
| 486 | ! key_exists( 'type', $manual_categorization ) || |
| 487 | ! key_exists( 'slug', $manual_categorization ) || |
| 488 | ! key_exists( 'send_to_server', $manual_categorization ) ) |
| 489 | return $generic_error_msg . ' #1'; |
| 490 | |
| 491 | $correction_category = $manual_categorization['type']; |
| 492 | if ( ! in_array( $correction_category, [ 'p', 't', 'w', 'o', 'u' ] ) ) |
| 493 | return $generic_error_msg . ' #2'; |
| 494 | |
| 495 | $slug = $manual_categorization['slug']; |
| 496 | |
| 497 | if ( in_array( $correction_category, [ 'w', 'o', 'u' ] ) && ! in_array( $slug, [ 'w', 'o', 'u' ] ) ) |
| 498 | return $generic_error_msg . ' #3'; |
| 499 | |
| 500 | if ( $correction_category === 'p' && ! ADBC_Plugins::instance()->is_plugin_slug_currently_installed( $slug ) ) |
| 501 | return $generic_error_msg . ' #4'; |
| 502 | |
| 503 | if ( $correction_category === 't' && ! ADBC_Themes::instance()->is_theme_slug_currently_installed( $slug ) ) |
| 504 | return $generic_error_msg . ' #5'; |
| 505 | |
| 506 | $send_correction_to_server = $manual_categorization['send_to_server']; |
| 507 | |
| 508 | if ( ! in_array( $send_correction_to_server, [ '0', '1' ] ) ) |
| 509 | return $generic_error_msg . ' #6'; |
| 510 | |
| 511 | return true; |
| 512 | } |
| 513 | |
| 514 | /** |
| 515 | * Validate the offset sent by the user. |
| 516 | * |
| 517 | * @param int $offset The offset. |
| 518 | * |
| 519 | * @return int The sanitized offset, 0 if invalid. |
| 520 | */ |
| 521 | public static function sanitize_validate_offset( $offset ) { |
| 522 | |
| 523 | // Sanitize the offset |
| 524 | $offset = absint( $offset ); |
| 525 | |
| 526 | if ( $offset < 0 ) |
| 527 | return 0; |
| 528 | |
| 529 | return $offset; |
| 530 | |
| 531 | } |
| 532 | |
| 533 | /** |
| 534 | * Validate the limit sent by the user. |
| 535 | * |
| 536 | * @param int $limit The limit. |
| 537 | * |
| 538 | * @return int The sanitized limit, 50 if invalid and 1000 max. |
| 539 | */ |
| 540 | public static function sanitize_validate_limit( $limit ) { |
| 541 | |
| 542 | // Sanitize the limit |
| 543 | $limit = absint( $limit ); |
| 544 | |
| 545 | // Limit the limit to 50 if less than 1 |
| 546 | if ( $limit < 1 ) |
| 547 | return 50; |
| 548 | |
| 549 | // Limit the limit to 1000 |
| 550 | if ( $limit > 1000 ) |
| 551 | return 1000; |
| 552 | |
| 553 | return $limit; |
| 554 | |
| 555 | } |
| 556 | |
| 557 | /** |
| 558 | * Sanitize and validate the current page sent by the user. |
| 559 | * |
| 560 | * @param int $current_page The current page. |
| 561 | * |
| 562 | * @return int The sanitized current page, 1 if invalid. |
| 563 | */ |
| 564 | public static function sanitize_validate_current_page( $current_page ) { |
| 565 | |
| 566 | // Sanitize the current page |
| 567 | $current_page = absint( $current_page ); |
| 568 | |
| 569 | // If current page is less than 1, set it to 1 |
| 570 | if ( $current_page < 1 ) |
| 571 | return 1; |
| 572 | |
| 573 | return $current_page; |
| 574 | |
| 575 | } |
| 576 | |
| 577 | } |