=' );
}
// 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';
}
});