first commit
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\App\Modules\Onboarding\Validation;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
abstract class Base_Validator {
|
||||
|
||||
protected array $errors = [];
|
||||
|
||||
abstract protected function get_rules(): array;
|
||||
|
||||
public function validate( array $params ) {
|
||||
if ( ! is_array( $params ) ) {
|
||||
return new WP_Error( 'invalid_params', 'Parameters must be an array.', [ 'status' => 400 ] );
|
||||
}
|
||||
|
||||
$this->errors = [];
|
||||
$validated = [];
|
||||
|
||||
foreach ( $this->get_rules() as $field => $rule ) {
|
||||
if ( ! array_key_exists( $field, $params ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->validate_field( $field, $params[ $field ], $rule );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$validated[ $field ] = $result;
|
||||
}
|
||||
|
||||
return $validated;
|
||||
}
|
||||
|
||||
protected function validate_field( string $field, $value, array $rule ) {
|
||||
$type = $rule['type'] ?? 'string';
|
||||
$nullable = $rule['nullable'] ?? false;
|
||||
|
||||
if ( null === $value ) {
|
||||
if ( $nullable ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->error( $field, "{$field} cannot be null." );
|
||||
}
|
||||
|
||||
switch ( $type ) {
|
||||
case 'string':
|
||||
return $this->validate_string( $field, $value );
|
||||
case 'int':
|
||||
return $this->validate_int( $field, $value );
|
||||
case 'bool':
|
||||
return $this->validate_bool( $field, $value );
|
||||
case 'array':
|
||||
return $this->validate_array( $field, $value, $rule );
|
||||
case 'string_array':
|
||||
return $this->validate_string_array( $field, $value );
|
||||
case 'custom_data':
|
||||
return $this->validate_custom_data( $field, $value );
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
protected function validate_string( string $field, $value ) {
|
||||
if ( ! is_string( $value ) ) {
|
||||
return $this->error( $field, "{$field} must be a string." );
|
||||
}
|
||||
|
||||
return sanitize_text_field( $value );
|
||||
}
|
||||
|
||||
protected function validate_int( string $field, $value ) {
|
||||
if ( ! is_numeric( $value ) ) {
|
||||
return $this->error( $field, "{$field} must be a number." );
|
||||
}
|
||||
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
protected function validate_bool( string $field, $value ) {
|
||||
if ( ! is_bool( $value ) ) {
|
||||
return $this->error( $field, "{$field} must be a boolean." );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function validate_array( string $field, $value, array $rule ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $this->error( $field, "{$field} must be an array." );
|
||||
}
|
||||
|
||||
$allowed = $rule['allowed'] ?? null;
|
||||
|
||||
if ( $allowed && ! in_array( $value, $allowed, true ) ) {
|
||||
return $this->error( $field, "{$field} contains invalid value." );
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function validate_string_array( string $field, $value ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $this->error( $field, "{$field} must be an array." );
|
||||
}
|
||||
|
||||
return array_values(
|
||||
array_filter(
|
||||
array_map(
|
||||
static function ( $item ) {
|
||||
return is_string( $item ) ? sanitize_text_field( $item ) : null;
|
||||
},
|
||||
$value
|
||||
),
|
||||
static function ( $item ) {
|
||||
return null !== $item;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
protected function validate_custom_data( string $field, $value ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $this->error( $field, "{$field} must be an array." );
|
||||
}
|
||||
|
||||
return $this->sanitize_recursive( $value );
|
||||
}
|
||||
|
||||
protected function sanitize_recursive( array $data ): array {
|
||||
$sanitized = [];
|
||||
|
||||
foreach ( $data as $key => $value ) {
|
||||
$safe_key = sanitize_key( $key );
|
||||
|
||||
if ( is_string( $value ) ) {
|
||||
$sanitized[ $safe_key ] = sanitize_text_field( $value );
|
||||
} elseif ( is_array( $value ) ) {
|
||||
$sanitized[ $safe_key ] = $this->sanitize_recursive( $value );
|
||||
} elseif ( is_numeric( $value ) || is_bool( $value ) || null === $value ) {
|
||||
$sanitized[ $safe_key ] = $value;
|
||||
} else {
|
||||
$sanitized[ $safe_key ] = null;
|
||||
}
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
protected function error( string $field, string $message ): WP_Error {
|
||||
return new WP_Error(
|
||||
'invalid_' . $field,
|
||||
$message,
|
||||
[ 'status' => 400 ]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\App\Modules\Onboarding\Validation;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class User_Choices_Validator extends Base_Validator {
|
||||
|
||||
protected function get_rules(): array {
|
||||
return [
|
||||
'building_for' => [
|
||||
'type' => 'string',
|
||||
'nullable' => true,
|
||||
],
|
||||
|
||||
'site_about' => [
|
||||
'type' => 'string_array',
|
||||
],
|
||||
|
||||
'experience_level' => [
|
||||
'type' => 'string',
|
||||
'nullable' => true,
|
||||
],
|
||||
|
||||
'theme_selection' => [
|
||||
'type' => 'string',
|
||||
'nullable' => true,
|
||||
],
|
||||
|
||||
'site_features' => [
|
||||
'type' => 'string_array',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\App\Modules\Onboarding\Validation;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class User_Progress_Validator extends Base_Validator {
|
||||
|
||||
private const ALLOWED_EXIT_TYPES = [ 'user_exit', 'unexpected', null, '' ];
|
||||
|
||||
protected function get_rules(): array {
|
||||
return [
|
||||
'current_step' => [
|
||||
'type' => 'int',
|
||||
],
|
||||
'completed_steps' => [
|
||||
'type' => 'mixed_array',
|
||||
],
|
||||
'exit_type' => [
|
||||
'type' => 'exit_type',
|
||||
'nullable' => true,
|
||||
],
|
||||
'complete_step' => [
|
||||
'type' => 'string_or_int',
|
||||
],
|
||||
'skip_step' => [
|
||||
'type' => 'bool',
|
||||
],
|
||||
'step_index' => [
|
||||
'type' => 'int',
|
||||
],
|
||||
'total_steps' => [
|
||||
'type' => 'int',
|
||||
],
|
||||
'start' => [
|
||||
'type' => 'bool',
|
||||
],
|
||||
'complete' => [
|
||||
'type' => 'bool',
|
||||
],
|
||||
'user_exit' => [
|
||||
'type' => 'bool',
|
||||
],
|
||||
'starter_dismissed' => [
|
||||
'type' => 'bool',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function validate_field( string $field, $value, array $rule ) {
|
||||
$type = $rule['type'] ?? 'string';
|
||||
|
||||
switch ( $type ) {
|
||||
case 'exit_type':
|
||||
return $this->validate_exit_type( $value );
|
||||
case 'string_or_int':
|
||||
return $this->validate_string_or_int( $field, $value );
|
||||
case 'mixed_array':
|
||||
return $this->validate_mixed_array( $field, $value );
|
||||
default:
|
||||
return parent::validate_field( $field, $value, $rule );
|
||||
}
|
||||
}
|
||||
|
||||
private function validate_exit_type( $value ) {
|
||||
if ( ! in_array( $value, self::ALLOWED_EXIT_TYPES, true ) ) {
|
||||
return $this->error( 'exit_type', 'Exit type is invalid.' );
|
||||
}
|
||||
|
||||
return '' === $value ? null : $value;
|
||||
}
|
||||
|
||||
private function validate_string_or_int( string $field, $value ) {
|
||||
if ( is_numeric( $value ) ) {
|
||||
return (int) $value;
|
||||
}
|
||||
|
||||
if ( is_string( $value ) ) {
|
||||
return sanitize_text_field( $value );
|
||||
}
|
||||
|
||||
return $this->error( $field, "{$field} must be a number or string." );
|
||||
}
|
||||
|
||||
private function validate_mixed_array( string $field, $value ) {
|
||||
if ( ! is_array( $value ) ) {
|
||||
return $this->error( $field, "{$field} must be an array." );
|
||||
}
|
||||
|
||||
return array_values(
|
||||
array_filter(
|
||||
array_map(
|
||||
static function ( $item ) {
|
||||
if ( is_numeric( $item ) ) {
|
||||
return (int) $item;
|
||||
}
|
||||
|
||||
if ( is_string( $item ) ) {
|
||||
return sanitize_text_field( $item );
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
$value
|
||||
),
|
||||
static function ( $item ) {
|
||||
return null !== $item;
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user