first commit
This commit is contained in:
145
wp-content/plugins/elementor/modules/interactions/module.php
Normal file
145
wp-content/plugins/elementor/modules/interactions/module.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
namespace Elementor\Modules\Interactions;
|
||||
|
||||
use Elementor\Core\Base\Module as BaseModule;
|
||||
use Elementor\Core\Experiments\Manager as Experiments_Manager;
|
||||
use Elementor\Modules\AtomicWidgets\Module as AtomicWidgetsModule;
|
||||
use Elementor\Plugin;
|
||||
use Elementor\Utils;
|
||||
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Module extends BaseModule {
|
||||
const MODULE_NAME = 'e-interactions';
|
||||
const EXPERIMENT_NAME = 'e_interactions';
|
||||
|
||||
public function get_name() {
|
||||
return self::MODULE_NAME;
|
||||
}
|
||||
|
||||
private $preset_animations;
|
||||
|
||||
private function get_presets() {
|
||||
if ( ! $this->preset_animations ) {
|
||||
$this->preset_animations = new Presets();
|
||||
}
|
||||
|
||||
return $this->preset_animations;
|
||||
}
|
||||
|
||||
public static function get_experimental_data() {
|
||||
return [
|
||||
'name' => self::EXPERIMENT_NAME,
|
||||
'title' => esc_html__( 'Interactions', 'elementor' ),
|
||||
'description' => esc_html__( 'Enable element interactions.', 'elementor' ),
|
||||
'hidden' => true,
|
||||
'default' => Experiments_Manager::STATE_ACTIVE,
|
||||
'release_status' => Experiments_Manager::RELEASE_STATUS_DEV,
|
||||
];
|
||||
}
|
||||
|
||||
public function is_experiment_active() {
|
||||
return Plugin::$instance->experiments->is_feature_active( self::EXPERIMENT_NAME )
|
||||
&& Plugin::$instance->experiments->is_feature_active( AtomicWidgetsModule::EXPERIMENT_NAME );
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
if ( ! $this->is_experiment_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'elementor/frontend/after_register_scripts', fn () => $this->register_frontend_scripts() );
|
||||
add_action( 'elementor/editor/before_enqueue_scripts', fn () => $this->enqueue_editor_scripts() );
|
||||
add_action( 'elementor/frontend/before_enqueue_scripts', fn () => $this->enqueue_interactions() );
|
||||
add_action( 'elementor/preview/enqueue_scripts', fn () => $this->enqueue_preview_scripts() );
|
||||
add_action( 'elementor/editor/after_enqueue_scripts', fn () => $this->enqueue_editor_scripts() );
|
||||
|
||||
add_filter( 'elementor/document/save/data',
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
function( $data, $document ) {
|
||||
$validation = new Validation();
|
||||
$document_after_sanitization = $validation->sanitize( $data );
|
||||
$validation->validate();
|
||||
|
||||
return $document_after_sanitization;
|
||||
},
|
||||
10, 2 );
|
||||
|
||||
add_filter( 'elementor/document/save/data', function( $data, $document ) {
|
||||
return ( new Parser( $document->get_main_id() ) )->assign_interaction_ids( $data );
|
||||
}, 11, 2 );
|
||||
}
|
||||
|
||||
private function get_config() {
|
||||
return [
|
||||
'constants' => $this->get_presets()->defaults(),
|
||||
'animationOptions' => $this->get_presets()->list(),
|
||||
];
|
||||
}
|
||||
|
||||
private function register_frontend_scripts() {
|
||||
$suffix = ( Utils::is_script_debug() || Utils::is_elementor_tests() ) ? '' : '.min';
|
||||
|
||||
wp_register_script(
|
||||
'motion-js',
|
||||
ELEMENTOR_ASSETS_URL . 'lib/motion/motion' . $suffix . '.js',
|
||||
[],
|
||||
'11.13.5',
|
||||
true
|
||||
);
|
||||
|
||||
wp_register_script(
|
||||
'elementor-interactions',
|
||||
$this->get_js_assets_url( 'interactions' ),
|
||||
[ 'motion-js' ],
|
||||
'1.0.0',
|
||||
true
|
||||
);
|
||||
|
||||
wp_register_script(
|
||||
'elementor-editor-interactions',
|
||||
$this->get_js_assets_url( 'editor-interactions' ),
|
||||
[ 'motion-js' ],
|
||||
'1.0.0',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function enqueue_interactions(): void {
|
||||
wp_enqueue_script( 'motion-js' );
|
||||
wp_enqueue_script( 'elementor-interactions' );
|
||||
|
||||
wp_localize_script(
|
||||
'elementor-interactions',
|
||||
'ElementorInteractionsConfig',
|
||||
$this->get_config()
|
||||
);
|
||||
}
|
||||
|
||||
public function enqueue_editor_scripts() {
|
||||
wp_add_inline_script(
|
||||
'elementor-common',
|
||||
'window.ElementorInteractionsConfig = ' . wp_json_encode( $this->get_config() ) . ';',
|
||||
'before'
|
||||
);
|
||||
}
|
||||
|
||||
public function enqueue_preview_scripts() {
|
||||
// Ensure motion-js and editor-interactions handler are available in preview iframe
|
||||
wp_enqueue_script( 'motion-js' );
|
||||
wp_enqueue_script( 'elementor-editor-interactions' );
|
||||
|
||||
wp_localize_script(
|
||||
'elementor-editor-interactions',
|
||||
'ElementorInteractionsConfig',
|
||||
$this->get_config()
|
||||
);
|
||||
}
|
||||
}
|
||||
107
wp-content/plugins/elementor/modules/interactions/parser.php
Normal file
107
wp-content/plugins/elementor/modules/interactions/parser.php
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Modules\Interactions;
|
||||
|
||||
use Elementor\Modules\AtomicWidgets\Utils\Utils;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Parser {
|
||||
protected $post_id;
|
||||
protected $ids_lookup = [];
|
||||
|
||||
public function __construct( $post_id ) {
|
||||
$this->post_id = $post_id;
|
||||
}
|
||||
|
||||
public function assign_interaction_ids( $data ) {
|
||||
if ( isset( $data['elements'] ) && is_array( $data['elements'] ) ) {
|
||||
$data['elements'] = $this->process_interactions_for( $data['elements'] );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function process_interactions_for( $elements ) {
|
||||
if ( ! is_array( $elements ) ) {
|
||||
return $elements;
|
||||
}
|
||||
|
||||
foreach ( $elements as &$element ) {
|
||||
if ( isset( $element['interactions'] ) ) {
|
||||
$element['interactions'] = $this->maybe_assign_interaction_ids( $element['interactions'], $element['id'] );
|
||||
}
|
||||
|
||||
if ( isset( $element['elements'] ) && is_array( $element['elements'] ) ) {
|
||||
$element['elements'] = $this->process_interactions_for( $element['elements'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
private function maybe_assign_interaction_ids( $interactions_json, $element_id ) {
|
||||
$interactions = $this->decode_interactions( $interactions_json );
|
||||
|
||||
if ( ! isset( $interactions['items'] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ( $interactions['items'] as &$interaction ) {
|
||||
if ( ! isset( $interaction['$$type'] ) || 'interaction-item' !== $interaction['$$type'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existing_id = null;
|
||||
if ( isset( $interaction['value']['interaction_id']['value'] ) ) {
|
||||
$existing_id = $interaction['value']['interaction_id']['value'];
|
||||
}
|
||||
|
||||
if ( $existing_id && $this->is_temp_id( $existing_id ) ) {
|
||||
$interaction['value']['interaction_id'] = [
|
||||
'$$type' => 'string',
|
||||
'value' => $this->get_next_interaction_id( $element_id ),
|
||||
];
|
||||
} elseif ( $existing_id ) {
|
||||
$this->ids_lookup[] = $existing_id;
|
||||
} else {
|
||||
$interaction['value']['interaction_id'] = [
|
||||
'$$type' => 'string',
|
||||
'value' => $this->get_next_interaction_id( $element_id ),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return wp_json_encode( $interactions );
|
||||
}
|
||||
|
||||
private function is_temp_id( $id ) {
|
||||
return is_string( $id ) && strpos( $id, 'temp-' ) === 0;
|
||||
}
|
||||
|
||||
private function decode_interactions( $interactions ) {
|
||||
if ( is_array( $interactions ) ) {
|
||||
return $interactions;
|
||||
}
|
||||
|
||||
if ( is_string( $interactions ) ) {
|
||||
$decoded = json_decode( $interactions, true );
|
||||
if ( json_last_error() === JSON_ERROR_NONE && is_array( $decoded ) ) {
|
||||
return $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'items' => [],
|
||||
'version' => 1,
|
||||
];
|
||||
}
|
||||
|
||||
protected function get_next_interaction_id( $prefix ) {
|
||||
$next_id = Utils::generate_id( "{$this->post_id}-{$prefix}-", $this->ids_lookup );
|
||||
$this->ids_lookup[] = $next_id;
|
||||
return $next_id;
|
||||
}
|
||||
}
|
||||
100
wp-content/plugins/elementor/modules/interactions/presets.php
Normal file
100
wp-content/plugins/elementor/modules/interactions/presets.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Modules\Interactions;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Presets {
|
||||
const DEFAULT_DURATION = 300;
|
||||
const DEFAULT_DELAY = 0;
|
||||
const DEFAULT_SLIDE_DISTANCE = 100;
|
||||
const DEFAULT_SCALE_START = 0;
|
||||
const DEFAULT_EASING = 'linear';
|
||||
|
||||
const TRIGGERS = [ 'load', 'scrollIn', 'scrollOn' ]; // 'scrollOut' is not supported yet.
|
||||
const EFFECTS = [ 'fade', 'slide', 'scale' ];
|
||||
const TYPES = [ 'in', 'out' ];
|
||||
const DIRECTIONS = [ 'left', 'right', 'top', 'bottom' ];
|
||||
const DURATIONS = [ 0, 100, 200, 300, 400, 500, 750, 1000, 1250, 1500 ];
|
||||
const DELAYS = [ 0, 100, 200, 300, 400, 500, 750, 1000, 1250, 1500 ];
|
||||
|
||||
public function list() {
|
||||
return $this->generate_animation_options();
|
||||
}
|
||||
|
||||
public function defaults() {
|
||||
return [
|
||||
'defaultDuration' => self::DEFAULT_DURATION,
|
||||
'defaultDelay' => self::DEFAULT_DELAY,
|
||||
'slideDistance' => self::DEFAULT_SLIDE_DISTANCE,
|
||||
'scaleStart' => self::DEFAULT_SCALE_START,
|
||||
'easing' => self::DEFAULT_EASING,
|
||||
];
|
||||
}
|
||||
|
||||
private function get_label( $key, $value ) {
|
||||
$special_labels = [
|
||||
'trigger' => [
|
||||
'load' => __( 'On page load', 'elementor' ),
|
||||
'scrollIn' => __( 'Scroll into view', 'elementor' ),
|
||||
'scrollOut' => __( 'Scroll out of view', 'elementor' ),
|
||||
],
|
||||
];
|
||||
|
||||
if ( isset( $special_labels[ $key ][ $value ] ) ) {
|
||||
return $special_labels[ $key ][ $value ];
|
||||
}
|
||||
|
||||
$label = ucwords( str_replace( '-', ' ', $value ) );
|
||||
|
||||
return esc_html( $label );
|
||||
}
|
||||
|
||||
private function generate_animation_options() {
|
||||
$options = [];
|
||||
|
||||
foreach ( self::TRIGGERS as $trigger ) {
|
||||
foreach ( self::EFFECTS as $effect ) {
|
||||
foreach ( self::TYPES as $type ) {
|
||||
foreach ( self::DIRECTIONS as $direction ) {
|
||||
foreach ( self::DURATIONS as $duration ) {
|
||||
foreach ( self::DELAYS as $delay ) {
|
||||
$value = "{$trigger}-{$effect}-{$type}-{$direction}-{$duration}-{$delay}";
|
||||
$label = sprintf(
|
||||
'%s: %s %s',
|
||||
$this->get_label( 'trigger', $trigger ),
|
||||
$this->get_label( 'effect', $effect ),
|
||||
$this->get_label( 'type', $type ),
|
||||
);
|
||||
$options[] = [
|
||||
'value' => $value,
|
||||
'label' => $label,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( self::DURATIONS as $duration ) {
|
||||
foreach ( self::DELAYS as $delay ) {
|
||||
$value = "{$trigger}-{$effect}-{$type}--{$duration}-{$delay}";
|
||||
$label = sprintf(
|
||||
'%s: %s %s',
|
||||
$this->get_label( 'trigger', $trigger ),
|
||||
$this->get_label( 'effect', $effect ),
|
||||
$this->get_label( 'type', $type ),
|
||||
);
|
||||
$options[] = [
|
||||
'value' => $value,
|
||||
'label' => $label,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
329
wp-content/plugins/elementor/modules/interactions/validation.php
Normal file
329
wp-content/plugins/elementor/modules/interactions/validation.php
Normal file
@@ -0,0 +1,329 @@
|
||||
<?php
|
||||
|
||||
namespace Elementor\Modules\Interactions;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
class Validation {
|
||||
private $elements_to_interactions_counter = [];
|
||||
private $max_number_of_interactions = 5;
|
||||
|
||||
private const VALID_TRIGGERS = [ 'load', 'scrollIn', 'scrollOut', 'scrollOn' ];
|
||||
private const VALID_EFFECTS = [ 'fade', 'slide', 'scale' ];
|
||||
private const VALID_TYPES = [ 'in', 'out' ];
|
||||
private const VALID_DIRECTIONS = [ '', 'left', 'right', 'top', 'bottom' ];
|
||||
|
||||
public function sanitize( $document ) {
|
||||
return $this->sanitize_document_data( $document );
|
||||
}
|
||||
|
||||
public function validate() {
|
||||
foreach ( $this->elements_to_interactions_counter as $element_id => $number_of_interactions ) {
|
||||
if ( $number_of_interactions > $this->max_number_of_interactions ) {
|
||||
throw new \Exception(
|
||||
sprintf(
|
||||
// translators: %1$s: element ID, %2$d: maximum number of interactions allowed.
|
||||
esc_html__( 'Element %1$s has more than %2$d interactions', 'elementor' ),
|
||||
esc_html( $element_id ),
|
||||
esc_html( $this->max_number_of_interactions )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function sanitize_document_data( $data ) {
|
||||
if ( isset( $data['elements'] ) && is_array( $data['elements'] ) ) {
|
||||
$data['elements'] = $this->sanitize_elements_interactions( $data['elements'] );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function sanitize_elements_interactions( $elements ) {
|
||||
if ( ! is_array( $elements ) ) {
|
||||
return $elements;
|
||||
}
|
||||
|
||||
foreach ( $elements as &$element ) {
|
||||
if ( isset( $element['interactions'] ) ) {
|
||||
$element['interactions'] = $this->sanitize_interactions( $element['interactions'], $element['id'] );
|
||||
}
|
||||
|
||||
if ( isset( $element['elements'] ) && is_array( $element['elements'] ) ) {
|
||||
$element['elements'] = $this->sanitize_elements_interactions( $element['elements'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
private function decode_interactions( $interactions ) {
|
||||
if ( is_array( $interactions ) ) {
|
||||
return isset( $interactions['items'] ) ? $interactions['items'] : [];
|
||||
}
|
||||
|
||||
if ( is_string( $interactions ) ) {
|
||||
$decoded = json_decode( $interactions, true );
|
||||
if ( json_last_error() === JSON_ERROR_NONE && is_array( $decoded ) ) {
|
||||
return isset( $decoded['items'] ) ? $decoded['items'] : [];
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private function increment_interactions_counter_for( $element_id ) {
|
||||
if ( ! array_key_exists( $element_id, $this->elements_to_interactions_counter ) ) {
|
||||
$this->elements_to_interactions_counter[ $element_id ] = 0;
|
||||
}
|
||||
|
||||
++$this->elements_to_interactions_counter[ $element_id ];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function sanitize_interactions( $interactions, $element_id ) {
|
||||
$sanitized = [
|
||||
'items' => [],
|
||||
'version' => 1,
|
||||
];
|
||||
|
||||
$list_of_interactions = $this->decode_interactions( $interactions );
|
||||
|
||||
foreach ( $list_of_interactions as $interaction ) {
|
||||
if ( $this->is_valid_interaction_item( $interaction ) ) {
|
||||
$sanitized['items'][] = $interaction;
|
||||
$this->increment_interactions_counter_for( $element_id );
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $sanitized['items'] ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return wp_json_encode( $sanitized );
|
||||
}
|
||||
|
||||
private function is_valid_interaction_item( $item ) {
|
||||
if ( ! is_array( $item ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate PropType format: { $$type: 'interaction-item', value: { ... } }
|
||||
if ( ! isset( $item['$$type'] ) || 'interaction-item' !== $item['$$type'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $item['value'] ) || ! is_array( $item['value'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = $item['value'];
|
||||
|
||||
// Validate required fields exist
|
||||
if ( isset( $value['interaction_id'] ) && ! $this->is_valid_string_prop( $value, 'interaction_id' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->is_valid_string_prop( $value, 'trigger', self::VALID_TRIGGERS ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->is_valid_animation_prop( $value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_valid_string_prop( $data, $key, $allowed_values = null ) {
|
||||
if ( ! isset( $data[ $key ] ) || ! is_array( $data[ $key ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prop = $data[ $key ];
|
||||
|
||||
if ( ! isset( $prop['$$type'] ) || 'string' !== $prop['$$type'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $prop['value'] ) || ! is_string( $prop['value'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( null !== $allowed_values && ! in_array( $prop['value'], $allowed_values, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_valid_boolean_prop( $data, $key ) {
|
||||
if ( ! isset( $data[ $key ] ) || ! is_array( $data[ $key ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prop = $data[ $key ];
|
||||
|
||||
if ( ! isset( $prop['$$type'] ) || 'boolean' !== $prop['$$type'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $prop['value'] ) || ! is_bool( $prop['value'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_valid_number_prop( $data, $key ) {
|
||||
if ( ! isset( $data[ $key ] ) || ! is_array( $data[ $key ] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prop = $data[ $key ];
|
||||
|
||||
if ( ! isset( $prop['$$type'] ) || 'number' !== $prop['$$type'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $prop['value'] ) || ! is_numeric( $prop['value'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_valid_number_prop_in_range( $data, $key, $min = null, $max = null ) {
|
||||
if ( ! $this->is_valid_number_prop( $data, $key ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$value = (float) $data[ $key ]['value'];
|
||||
|
||||
if ( null !== $min && $value < $min ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( null !== $max && $value > $max ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_valid_config_prop( $data ) {
|
||||
if ( ! isset( $data['config'] ) || ! is_array( $data['config'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = $data['config'];
|
||||
|
||||
if ( ! isset( $config['$$type'] ) || 'config' !== $config['$$type'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $config['value'] ) || ! is_array( $config['value'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$config_value = $config['value'];
|
||||
|
||||
if ( isset( $config_value['replay'] ) && ! $this->is_valid_boolean_prop( $config_value, 'replay' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $config_value['relativeTo'] ) && ! $this->is_valid_string_prop( $config_value, 'relativeTo' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $config_value['offsetTop'] ) && ! $this->is_valid_number_prop_in_range( $config_value, 'offsetTop', 0, 100 ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $config_value['offsetBottom'] ) && ! $this->is_valid_number_prop_in_range( $config_value, 'offsetBottom', 0, 100 ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_valid_animation_prop( $data ) {
|
||||
if ( ! isset( $data['animation'] ) || ! is_array( $data['animation'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$animation = $data['animation'];
|
||||
|
||||
if ( ! isset( $animation['$$type'] ) || 'animation-preset-props' !== $animation['$$type'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $animation['value'] ) || ! is_array( $animation['value'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$animation_value = $animation['value'];
|
||||
|
||||
// Validate effect
|
||||
if ( ! $this->is_valid_string_prop( $animation_value, 'effect', self::VALID_EFFECTS ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate type
|
||||
if ( ! $this->is_valid_string_prop( $animation_value, 'type', self::VALID_TYPES ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate direction (can be empty string)
|
||||
if ( ! $this->is_valid_string_prop( $animation_value, 'direction', self::VALID_DIRECTIONS ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate timing_config
|
||||
if ( ! $this->is_valid_timing_config( $animation_value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isset( $animation_value['config'] ) && ! $this->is_valid_config_prop( $animation_value ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function is_valid_timing_config( $data ) {
|
||||
if ( ! isset( $data['timing_config'] ) || ! is_array( $data['timing_config'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$timing = $data['timing_config'];
|
||||
|
||||
if ( ! isset( $timing['$$type'] ) || 'timing-config' !== $timing['$$type'] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! isset( $timing['value'] ) || ! is_array( $timing['value'] ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$timing_value = $timing['value'];
|
||||
|
||||
// Validate duration
|
||||
if ( ! $this->is_valid_number_prop( $timing_value, 'duration' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate delay
|
||||
if ( ! $this->is_valid_number_prop( $timing_value, 'delay' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user