=' ); } // Shared CSS sanitization helper (used by animation/custom CSS even without AI). require_once plugin_dir_path( __FILE__ ) . 'includes/class-security.php'; require_once plugin_dir_path( __FILE__ ) . 'includes/class-elementor-remote-media-controller.php'; require_once plugin_dir_path( __FILE__ ) . 'includes/class-elementor-svg-media-controller.php'; new \AdvancedAddons\Elementor_Remote_Media_Controller(); new \AdvancedAddons\Elementor_SVG_Media_Controller(); require_once plugin_dir_path( __FILE__ ) . 'includes/class-animation-presets-controller.php'; new \AdvancedAddons\Animation_Presets_Controller(); require_once plugin_dir_path( __FILE__ ) . 'includes/class-elementor-atomic-animation.php'; require_once plugin_dir_path( __FILE__ ) . 'includes/class-elementor-v4-inline-html.php'; require_once plugin_dir_path( __FILE__ ) . 'includes/class-elementor-marquee.php'; require_once plugin_dir_path( __FILE__ ) . 'includes/class-custom-javascript-block.php'; new \AdvancedAddons\Custom_Javascript_Block(); // Welcome / settings menu — load before AI modules so the parent admin page exists first. require_once plugin_dir_path( __FILE__ ) . 'includes/class-admin-components.php'; new WPAddons_Admin_Components(); require_once plugin_dir_path( __FILE__ ) . 'includes/class-admin-promo.php'; new WPAddons_Admin_Promo(); register_activation_hook( __FILE__, array( 'WPAddons_Admin_Promo', 'set_activation_redirect' ) ); // Optional AI Builder — WordPress 7.0+ only (AI Client / Connectors APIs). if ( advanced_addons_ai_supported() ) { require_once plugin_dir_path( __FILE__ ) . 'wp-ai-builder.php'; define( 'ADVANCED_ADDONS_AI_ENABLED', true ); } else { define( 'ADVANCED_ADDONS_AI_ENABLED', false ); } function wpaddons_enqueue_block_assets() { if ( is_admin() ) { $asset_file = include plugin_dir_path( __FILE__ ) . 'build/blockScript.asset.php'; wp_enqueue_script( 'block-scripts', plugins_url( 'build/blockScript.js', __FILE__ ), $asset_file['dependencies'], $asset_file['version'], true ); } } add_action( 'enqueue_block_assets', 'wpaddons_enqueue_block_assets' ); /** * Enqueue the Custom JavaScript block independently of the optional AI Builder. * * The block is discoverable for every editor, but executable code can only be * authorized by users with the administrator-level manage_options capability. */ function wpaddons_enqueue_custom_javascript_block_editor_assets() { $asset_path = plugin_dir_path( __FILE__ ) . 'build/custom-javascript-block.asset.php'; if ( ! file_exists( $asset_path ) ) { return; } $asset = include $asset_path; wp_enqueue_script( 'advanced-addons-custom-javascript', plugins_url( 'build/custom-javascript-block.js', __FILE__ ), $asset['dependencies'], $asset['version'], true ); wp_localize_script( 'advanced-addons-custom-javascript', 'AdvancedAddonsCustomJavaScript', array( 'canEditCustomJavaScript' => (bool) current_user_can( 'manage_options' ), 'version' => defined( 'ADVANCED_ADDONS_VERSION' ) ? ADVANCED_ADDONS_VERSION : '0.0.0', ) ); } add_action( 'enqueue_block_editor_assets', 'wpaddons_enqueue_custom_javascript_block_editor_assets', 20 ); function wpaddons_fe_script() { global $post; if ( ! $post instanceof WP_Post ) { return; } $post_id = $post->ID; $animation = get_post_meta( $post_id, '_advanced_animation_props', true ); $custom_css = get_post_meta( $post_id, '_advanced_custom_css', true ); $fe_script = require plugin_dir_path( __FILE__ ) . 'build/frontend.asset.php'; wp_enqueue_script( 'frontend-script', plugin_dir_url( __FILE__ ) . 'build/frontend.js', $fe_script['dependencies'], $fe_script['version'], true ); wp_localize_script( 'frontend-script', 'animationGlobal', array( 'props' => $animation ) ); wp_register_style( 'wp-addon-custom-style', false, array(), ADVANCED_ADDONS_VERSION ); wp_enqueue_style( 'wp-addon-custom-style' ); if ( is_string( $custom_css ) && '' !== $custom_css ) { $safe_css = class_exists( '\AdvancedAddons\Security' ) ? \AdvancedAddons\Security::sanitize_css( $custom_css ) : wp_strip_all_tags( $custom_css ); wp_add_inline_style( 'wp-addon-custom-style', $safe_css ); } } add_action( 'wp_enqueue_scripts', 'wpaddons_fe_script' ); function wpaddons_post_meta() { $types = array( 'post', 'page', 'wp_block' ); foreach ( $types as $type ) { register_post_meta( $type, '_advanced_animation_props', array( 'single' => true, 'type' => 'string', 'show_in_rest' => true, 'auth_callback' => function ( $allowed, $meta_key, $post_id ) { return current_user_can( 'edit_post', $post_id ); }, ) ); register_post_meta( $type, '_advanced_custom_css', array( 'single' => true, 'type' => 'string', 'show_in_rest' => true, 'auth_callback' => function ( $allowed, $meta_key, $post_id ) { return current_user_can( 'edit_post', $post_id ); }, ) ); } } add_action( 'init', 'wpaddons_post_meta' ); function wpaddons_render_block($block_content, $block){ if(!isset($block['attrs'])){ return $block_content; } $attrs = $block['attrs']; $class = ""; // Add animation class if(isset($attrs["animationSettings"]) && isset($attrs["animationSettings"]["classAnimation"]) && count($attrs["animationSettings"]["classAnimation"]) && !empty($attrs["animationSettings"]["id"])){ $animationId = $attrs["animationSettings"]["id"]; $class = $class ." animation-". $animationId; } // Add custom CSS class if(isset($attrs["customCSSSettings"]) && !empty($attrs["customCSSSettings"]["customCSSClass"])){ $customCSSClass = $attrs["customCSSSettings"]["customCSSClass"]; $class = $class ." ". $customCSSClass; } if(!empty($class)){ $class = trim($class); $pos = strpos($block_content, $class); $class = 'class="'. $class . " "; if($pos === false){ $pos = strpos($block_content, "class"); if ($pos !== false) { $block_content = substr_replace($block_content, $class, $pos, 7); } } } return $block_content; } add_filter( 'render_block', 'wpaddons_render_block', 10, 2); /** * Reusable function to register animation controls for Elementor elements */ function wpaddons_register_animation_controls($element) { $element->start_controls_section( 'advanced_animation_section', [ 'label' => __('Advanced Animation', 'advanced-animation'), 'tab' => \Elementor\Controls_Manager::TAB_ADVANCED, ] ); // Enable Animation $element->add_control( 'advanced_animation_enable', [ 'label' => __('Enable Animation', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => '', ] ); $element->add_control( 'advanced_animation_presets', [ 'type' => \Elementor\Controls_Manager::RAW_HTML, 'raw' => '
' . '' . '' . '' . '' . '' . '' . '

', ] ); foreach ( [ 'advanced_animation_disable_tablet' => __( 'Disable on Tablet', 'advanced-animation' ), 'advanced_animation_disable_mobile' => __( 'Disable on Mobile', 'advanced-animation' ), ] as $name => $label ) { $element->add_control( $name, [ 'label' => $label, 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => '', 'condition' => [ 'advanced_animation_enable' => 'yes' ], ] ); } // Animation Settings (above keyframes) $element->add_control( 'advanced_animation_trigger_type', [ 'label' => __('Trigger Type', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'onVisible' => __('On Visible', 'advanced-animation'), 'onScroll' => __('On Scroll', 'advanced-animation'), ], 'default' => 'onVisible', 'condition' => [ 'advanced_animation_enable' => 'yes', ], ] ); $element->add_control( 'advanced_animation_trigger_once', [ 'label' => __('Run Once', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SWITCHER, 'default' => 'yes', 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_trigger_type' => 'onVisible', ], ] ); $element->add_control( 'advanced_animation_trigger_start', [ 'type' => \Elementor\Controls_Manager::HIDDEN, 'options' => [ 'start end' => __('Top of target at screen bottom', 'advanced-animation'), 'start start' => __('Top of target at screen top', 'advanced-animation'), 'start center' => __('Top of target at screen center', 'advanced-animation'), 'center center' => __('Center of target at screen center', 'advanced-animation'), 'end end' => __('Bottom of target at screen bottom', 'advanced-animation'), 'end start' => __('Bottom of target at screen top', 'advanced-animation'), 'end center' => __('Bottom of target at screen center', 'advanced-animation'), ], 'default' => 'start start', 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_trigger_type' => 'onScroll', ], ] ); $element->add_control( 'advanced_animation_trigger_end', [ 'type' => \Elementor\Controls_Manager::HIDDEN, 'options' => [ 'end start' => __('Bottom of target at screen top', 'advanced-animation'), 'end end' => __('Bottom of target at screen bottom', 'advanced-animation'), 'end center' => __('Bottom of target at screen center', 'advanced-animation'), 'center center' => __('Center of target at screen center', 'advanced-animation'), 'start start' => __('Top of target at screen top', 'advanced-animation'), 'start end' => __('Top of target at screen bottom', 'advanced-animation'), 'start center' => __('Top of target at screen center', 'advanced-animation'), ], 'default' => 'end end', 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_trigger_type' => 'onScroll', ], ] ); $element->add_control( 'advanced_animation_scroll_position', [ 'label' => __('Scroll Viewport Position', 'advanced-animation'), 'label_block' => true, 'type' => \Elementor\Controls_Manager::CHOOSE, 'options' => [ 'top' => [ 'title' => __('Top', 'advanced-animation'), 'icon' => 'aa-scroll-position-icon aa-scroll-position-icon--top' ], 'center' => [ 'title' => __('Center', 'advanced-animation'), 'icon' => 'aa-scroll-position-icon aa-scroll-position-icon--center' ], 'bottom' => [ 'title' => __('Bottom', 'advanced-animation'), 'icon' => 'aa-scroll-position-icon aa-scroll-position-icon--bottom' ], ], 'default' => '', 'toggle' => false, 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_trigger_type' => 'onScroll', ], ] ); $element->add_control( 'advanced_animation_custom_trigger', [ 'label' => __('Custom Scroll Trigger Element', 'advanced-animation'), 'label_block' => true, 'type' => \Elementor\Controls_Manager::TEXT, 'default' => '', 'placeholder' => __('#element-id or .class-name', 'advanced-animation'), 'description' => __('Enter a CSS selector (ID or class) for the element to use as scroll trigger reference. Leave empty to use the animated element itself.', 'advanced-animation'), 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_trigger_type' => 'onScroll', ], ] ); $element->add_control( 'advanced_animation_duration', [ 'label' => __('Duration (seconds)', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::NUMBER, 'default' => 0.5, 'step' => 0.1, 'description' => __('Used for On Visible easing and time-based Spring. Scroll controls playback progress; Spring Time shapes the spring curve.', 'advanced-animation'), 'conditions' => [ 'terms' => [ [ 'name' => 'advanced_animation_enable', 'value' => 'yes' ], [ 'relation' => 'or', 'terms' => [ [ 'terms' => [ [ 'name' => 'advanced_animation_trigger_type', 'value' => 'onVisible' ], [ 'name' => 'advanced_animation_easing', 'operator' => '!==', 'value' => 'spring' ], ], ], [ 'terms' => [ [ 'name' => 'advanced_animation_easing', 'value' => 'spring' ], [ 'name' => 'advanced_animation_spring_mode', 'value' => 'time' ], ], ], ], ], ], ], ] ); $element->add_control( 'advanced_animation_delay', [ 'label' => __('Delay (seconds)', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::NUMBER, 'default' => 0, 'step' => 0.1, 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_trigger_type' => 'onVisible', ], ] ); $element->add_control( 'advanced_animation_iteration_count', [ 'label' => __('Playing Iterations', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 1 => __('One time', 'advanced-animation'), 'infinite' => __('Infinite', 'advanced-animation'), ], 'default' => 1, 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_trigger_type' => 'onVisible', ], ] ); $element->add_control( 'advanced_animation_direction', [ 'label' => __('Direction', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'normal' => __('Normal', 'advanced-animation'), 'reverse' => __('Reverse', 'advanced-animation'), 'alternate' => __('Alternate', 'advanced-animation'), 'alternate-reverse' => __('Alternate Reverse', 'advanced-animation'), ], 'default' => 'normal', 'condition' => [ 'advanced_animation_enable' => 'yes', ], ] ); $element->add_control( 'advanced_animation_easing', [ 'label' => __('Easing', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'linear' => __('Linear', 'advanced-animation'), 'easeInOut' => __('Ease In Out', 'advanced-animation'), 'easeIn' => __('Ease In', 'advanced-animation'), 'easeOut' => __('Ease Out', 'advanced-animation'), 'spring' => __('Spring', 'advanced-animation'), 'backInOut' => __('Back In Out', 'advanced-animation'), 'backIn' => __('Back In', 'advanced-animation'), 'backOut' => __('Back Out', 'advanced-animation'), 'circInOut' => __('Circ In Out', 'advanced-animation'), 'circIn' => __('Circ In', 'advanced-animation'), 'circOut' => __('Circ Out', 'advanced-animation'), // Add more as needed ], 'default' => 'easeOut', 'condition' => [ 'advanced_animation_enable' => 'yes', ], ] ); $element->add_control( 'advanced_animation_spring_mode', [ 'label' => __('Based On', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SELECT, 'options' => [ 'time' => __('Time', 'advanced-animation'), 'physics' => __('Physics', 'advanced-animation'), ], 'default' => 'time', 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_easing' => 'spring', ], ] ); $element->add_control( 'advanced_animation_spring_bounce', [ 'label' => __('Bounce', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::NUMBER, 'default' => 0.3, 'min' => 0, 'max' => 1, 'step' => 0.05, 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_easing' => 'spring', 'advanced_animation_spring_mode' => 'time', ], ] ); foreach ( [ 'stiffness' => [ __('Stiffness', 'advanced-animation'), 100, 1 ], 'damping' => [ __('Damping', 'advanced-animation'), 10, 1 ], 'mass' => [ __('Mass', 'advanced-animation'), 1, 0.1 ], ] as $name => $control ) { $element->add_control( 'advanced_animation_spring_' . $name, [ 'label' => $control[0], 'type' => \Elementor\Controls_Manager::NUMBER, 'default' => $control[1], 'min' => 0.01, 'step' => $control[2], 'condition' => [ 'advanced_animation_enable' => 'yes', 'advanced_animation_easing' => 'spring', 'advanced_animation_spring_mode' => 'physics', ], ] ); } // --- Dynamic Keyframe Controls --- $repeater = new \Elementor\Repeater(); $repeater->add_control( 'property', [ 'label' => __('Property', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::SELECT, 'default' => 'x', 'options' => [ 'x' => __('Translate X', 'advanced-animation'), 'y' => __('Translate Y', 'advanced-animation'), 'opacity' => __('Opacity', 'advanced-animation'), 'scale' => __('Scale', 'advanced-animation'), 'rotate' => __('Rotate', 'advanced-animation'), 'rotateX' => __('Rotate X', 'advanced-animation'), 'rotateY' => __('Rotate Y', 'advanced-animation'), 'transformPerspective' => __('Perspective', 'advanced-animation'), 'skewX' => __('Skew X', 'advanced-animation'), 'skewY' => __('Skew Y', 'advanced-animation'), 'scaleX' => __('Scale X', 'advanced-animation'), 'scaleY' => __('Scale Y', 'advanced-animation'), ], ] ); $repeater->add_control( 'start_value', [ 'label' => __('Start Value', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::NUMBER, 'default' => 0, 'step' => 1, ] ); $repeater->add_control( 'end_value', [ 'label' => __('End Value', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::NUMBER, 'default' => 1, 'step' => 1, ] ); $element->add_control( 'advanced_animation_keyframes', [ 'label' => __('Keyframe Properties', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::REPEATER, 'fields' => $repeater->get_controls(), 'default' => [ [ 'property' => 'opacity', 'start_value' => 0, 'end_value' => 1, ], ], 'title_field' => '{{{ property }}} : {{{ start_value }}} → {{{ end_value }}}', 'condition' => [ 'advanced_animation_enable' => 'yes', ], ] ); // Custom Keyframes JSON $element->add_control( 'advanced_animation_custom_keyframes', [ 'label' => __('Custom Keyframes (JSON)', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::TEXTAREA, 'default' => '', 'description' => __('Add custom keyframe attributes as JSON. Example: { "backgroundColor": { "start": "#fff", "end": "#000" } }', 'advanced-animation'), 'condition' => [ 'advanced_animation_enable' => 'yes', ], ] ); // Editor-only controls: raw HTML has no Elementor setting to save. $element->add_control( 'advanced_animation_static_preview', [ 'type' => \Elementor\Controls_Manager::RAW_HTML, 'raw' => '
' . '' . '
', 'condition' => [ 'advanced_animation_enable' => 'yes', ], ] ); // Play Animation Button $element->add_control( 'advanced_animation_play_button', [ 'label' => __('Preview Animation', 'advanced-animation'), 'type' => \Elementor\Controls_Manager::BUTTON, 'text' => __('Play Animation', 'advanced-animation'), 'event' => 'advanced_animation:play', 'condition' => [ 'advanced_animation_enable' => 'yes', ], ] ); $element->end_controls_section(); } /** * Build animation attributes from Elementor settings */ function wpaddons_build_animation_attributes($settings) { $settings = array_merge( array( 'advanced_animation_trigger_type' => 'onVisible', 'advanced_animation_trigger_once' => 'yes', 'advanced_animation_trigger_start' => 'start start', 'advanced_animation_trigger_end' => 'end end', 'advanced_animation_scroll_position' => '', 'advanced_animation_duration' => 0.5, 'advanced_animation_delay' => 0, 'advanced_animation_iteration_count' => 1, 'advanced_animation_direction' => 'normal', 'advanced_animation_easing' => 'easeOut', 'advanced_animation_spring_mode' => 'time', 'advanced_animation_spring_bounce' => 0.3, 'advanced_animation_spring_stiffness' => 100, 'advanced_animation_spring_damping' => 10, 'advanced_animation_spring_mass' => 1, 'advanced_animation_disable_tablet' => '', 'advanced_animation_disable_mobile' => '', 'advanced_animation_keyframes' => array( array( 'property' => 'opacity', 'start_value' => 0, 'end_value' => 1 ) ), ), is_array( $settings ) ? $settings : array() ); $keyframes = []; // Build keyframes from repeater data if (is_array($settings['advanced_animation_keyframes'])) { foreach ($settings['advanced_animation_keyframes'] as $item) { if (is_array($item) && !empty($item['property']) && is_string($item['property'])) { $keyframes[$item['property']] = [ 'start' => $item['start_value'] ?? 0, 'end' => $item['end_value'] ?? 1, ]; } } } // Merge custom keyframes JSON if present if (!empty($settings['advanced_animation_custom_keyframes']) && is_string($settings['advanced_animation_custom_keyframes'])) { $json = json_decode($settings['advanced_animation_custom_keyframes'], true); if (is_array($json) && is_object(json_decode($settings['advanced_animation_custom_keyframes']))) { $keyframes = array_merge($keyframes, $json); } } $scroll_positions = array( 'top' => array( 'start start', 'end start' ), 'center' => array( 'start center', 'end center' ), 'bottom' => array( 'start end', 'end end' ), ); $scroll_position = $settings['advanced_animation_scroll_position']; if ( is_string( $scroll_position ) && isset( $scroll_positions[ $scroll_position ] ) ) { $settings['advanced_animation_trigger_start'] = $scroll_positions[ $scroll_position ][0]; $settings['advanced_animation_trigger_end'] = $scroll_positions[ $scroll_position ][1]; } return [ 'triggerType' => $settings['advanced_animation_trigger_type'], 'triggerOnce' => $settings['advanced_animation_trigger_once'], 'triggerStart' => $settings['advanced_animation_trigger_start'], 'triggerEnd' => $settings['advanced_animation_trigger_end'], 'customTrigger' => !empty($settings['advanced_animation_custom_trigger']) ? $settings['advanced_animation_custom_trigger'] : '', 'duration' => $settings['advanced_animation_duration'], 'delay' => $settings['advanced_animation_delay'], 'iterationCount' => $settings['advanced_animation_iteration_count'], 'direction' => $settings['advanced_animation_direction'], 'easing' => $settings['advanced_animation_easing'], 'springMode' => $settings['advanced_animation_spring_mode'], 'springBounce' => $settings['advanced_animation_spring_bounce'], 'springStiffness' => $settings['advanced_animation_spring_stiffness'], 'springDamping' => $settings['advanced_animation_spring_damping'], 'springMass' => $settings['advanced_animation_spring_mass'], 'disableOnTablet' => in_array( $settings['advanced_animation_disable_tablet'], array( 'yes', true, 1 ), true ), 'disableOnMobile' => in_array( $settings['advanced_animation_disable_mobile'], array( 'yes', true, 1 ), true ), 'keyframes' => $keyframes, ]; } // Elementor: Register Animation Controls for Widgets add_action('elementor/element/common/_section_style/after_section_end', function($element, $args) { wpaddons_register_animation_controls($element); }, 10, 2); // Add animation attributes to Elementor widget wrapper add_filter('elementor/frontend/widget/should_render', function($should_render, $widget) { $settings = $widget->get_settings_for_display(); if (!empty($settings['advanced_animation_enable'])) { $animation_settings = wpaddons_build_animation_attributes($settings); $widget->add_render_attribute('_wrapper', [ 'data-advanced-animation' => 'yes', 'data-animation-settings' => htmlspecialchars(json_encode($animation_settings), ENT_QUOTES, 'UTF-8'), ]); } return $should_render; }, 10, 2); // Elementor: Register Animation Controls for Containers add_action('elementor/element/container/section_layout/after_section_end', function($element, $args) { wpaddons_register_animation_controls($element); }, 10, 2); // Add animation attributes to Elementor container wrapper add_filter('elementor/frontend/container/should_render', function($should_render, $container) { $settings = $container->get_settings_for_display(); if (!empty($settings['advanced_animation_enable'])) { $animation_settings = wpaddons_build_animation_attributes($settings); $container->add_render_attribute('_wrapper', [ 'data-advanced-animation' => 'yes', 'data-animation-settings' => htmlspecialchars(json_encode($animation_settings), ENT_QUOTES, 'UTF-8'), ]); } return $should_render; }, 10, 2); /** * Whether Elementor's Atomic Widgets editor experiment is active. * * AI Builder UI depends on this; do not hard-depend on its script handle when off. */ function wpaddons_is_elementor_atomic_editor_active() { return class_exists( '\\Elementor\\Modules\\AtomicWidgets\\Module' ) && \Elementor\Modules\AtomicWidgets\Module::is_active(); } /** Return the status of Elementor's official server-side MCP endpoint. */ function wpaddons_get_elementor_mcp_status() { $active = false; if ( class_exists( '\\Elementor\\Modules\\Mcp\\Module' ) && method_exists( '\\Elementor\\Modules\\Mcp\\Module', 'is_active' ) ) { try { $active = (bool) \Elementor\Modules\Mcp\Module::is_active(); } catch ( \Throwable $error ) { $active = false; } } return array( 'active' => $active, 'endpoint' => rest_url( 'elementor/mcp' ), 'message' => $active ? __( 'Elementor official MCP server is active.', 'advanced-animation' ) : __( 'Elementor editor MCP tools will be detected automatically. For external clients, enable Elementor MCP in Elementor when that experiment is required by your version.', 'advanced-animation' ), ); } /** * Enqueue Elementor editor animation preview scripts */ function wpaddons_enqueue_elementor_editor_scripts() { $elementor_editor_asset = include(plugin_dir_path(__FILE__) . 'build/elementor-editor.asset.php'); $atomic_active = wpaddons_is_elementor_atomic_editor_active(); $deps = array( 'jquery' ); if ( wp_script_is( 'elementor-editor', 'registered' ) ) { $deps[] = 'elementor-editor'; } if ( $atomic_active ) { foreach ( array( 'elementor-atomic-widgets-editor', 'elementor-v2-editor-editing-panel', 'elementor-v2-editor-controls', 'elementor-v2-editor-props' ) as $handle ) { if ( wp_script_is( $handle, 'registered' ) ) { $deps[] = $handle; } } if ( wp_script_is( 'elementor-v2-editor-mcp', 'registered' ) ) { $deps[] = 'elementor-v2-editor-mcp'; } if ( wp_script_is( 'elementor-v2-schema', 'registered' ) ) { $deps[] = 'elementor-v2-schema'; } } wp_enqueue_script( 'wpaddons-elementor-editor', plugins_url('build/elementor-editor.js', __FILE__), array_merge( $deps, $elementor_editor_asset['dependencies'] ), $elementor_editor_asset['version'], true ); wp_localize_script( 'wpaddons-elementor-editor', 'AdvancedAnimationPresetApi', array( 'url' => rest_url( 'advanced-animation/v1/presets' ), 'nonce' => wp_create_nonce( 'wp_rest' ), ) ); // The scroll-position control is used in both classic and atomic editors. $elementor_editor_style = plugin_dir_path(__FILE__) . 'build/elementor-editor.css'; if ( file_exists( $elementor_editor_style ) ) { wp_enqueue_style( 'wpaddons-elementor-editor', plugins_url('build/elementor-editor.css', __FILE__), array(), (string) filemtime( $elementor_editor_style ) ); } $wpaib_data = array( 'elementorMediaImportUrl' => rest_url( 'advanced-animation/v1/elementor/import-media' ), 'elementorMediaUploadUrl' => rest_url( 'wp/v2/media' ), 'elementorSvgMediaUrl' => rest_url( 'wp-ai-builder/v1/elementor/svg-media' ), 'elementorRestRoot' => rest_url(), 'nonce' => wp_create_nonce( 'wp_rest' ), ); // AI chat panel config — WP 7.0+ and Atomic Widgets editor required. if ( $atomic_active && defined( 'ADVANCED_ADDONS_AI_ENABLED' ) && ADVANCED_ADDONS_AI_ENABLED ) { $wpaib_data = array_merge( $wpaib_data, array( 'restUrl' => rest_url( 'wp-ai-builder/v1/generate' ), 'elementorRestUrl' => rest_url( 'wp-ai-builder/v1/elementor/generate' ), 'modelsUrl' => rest_url( 'wp-ai-builder/v1/models' ), 'selectionUrl' => rest_url( 'wp-ai-builder/v1/selection' ), 'userId' => get_current_user_id(), 'aiEnabled' => true, 'elementorMcp' => wpaddons_get_elementor_mcp_status(), ) ); if ( class_exists( '\\AdvancedAddons\\Tailwind_Theme_Settings' ) ) { $wpaib_data['tailwindTheme'] = \AdvancedAddons\Tailwind_Theme_Settings::get_theme(); } } wp_localize_script( 'wpaddons-elementor-editor', 'WPAIBuilder', $wpaib_data ); } add_action('elementor/editor/after_enqueue_scripts', 'wpaddons_enqueue_elementor_editor_scripts'); //include custom css file with the plugin or theme add_action('elementor/init', function () { if (defined('ELEMENTOR_VERSION')) { require_once plugin_dir_path(__FILE__) . 'elementor-custom-css.php'; } });