'major.minor' (patch is ignored during comparison). * * @var array */ private const NEW_ATOMIC_ELEMENTS = [ 'e-background-video' => '4.3', 'e-accordion' => '4.3', 'e-list' => '4.3', ]; protected $version = '0.0'; protected $styles = []; protected $interactions = []; protected $editor_settings = []; protected $origin_id = null; public static $widget_description = null; public function __construct( $data = [], $args = null ) { parent::__construct( $data, $args ); $this->version = $data['version'] ?? '0.0'; $this->styles = $data['styles'] ?? []; $this->interactions = $this->parse_atomic_interactions( $data['interactions'] ?? [] ); $this->editor_settings = $data['editor_settings'] ?? []; if ( static::$widget_description ) { $this->description( static::$widget_description ); } $this->origin_id = $data['origin_id'] ?? null; } private function parse_atomic_interactions( $interactions ) { if ( empty( $interactions ) ) { return []; } if ( is_string( $interactions ) ) { $decoded = json_decode( $interactions, true ); if ( json_last_error() === JSON_ERROR_NONE && is_array( $decoded ) ) { $interactions = $decoded; } } if ( ! is_array( $interactions ) ) { return []; } return $interactions; } abstract protected function define_atomic_controls(): array; protected function define_atomic_style_states(): array { return []; } protected function define_atomic_pseudo_states(): array { return []; } public function get_global_scripts() { return []; } protected function get_initial_config() { $config = parent::get_initial_config(); $props_schema = static::get_props_schema(); $config['atomic'] = true; $config['atomic_controls'] = $this->get_atomic_controls(); $config['atomic_props_schema'] = $props_schema; $config['atomic_style_states'] = $this->define_atomic_style_states(); $config['atomic_pseudo_states'] = $this->define_atomic_pseudo_states(); $config['dependencies_per_target_mapping'] = Dependency_Manager::get_source_to_dependents( $props_schema ); $config['base_styles'] = $this->get_base_styles(); $config['base_settings'] = $this->get_base_settings(); $config['version'] = $this->version; $config['show_in_panel'] = $this->should_show_in_panel(); $config['categories'] = $this->define_panel_categories(); $config['hide_on_search'] = false; $config['controls'] = []; $config['keywords'] = $this->get_keywords(); $config['default_children'] = $this->define_default_children(); $config['children_dependencies'] = $this->get_children_dependencies_config(); $config['initial_attributes'] = $this->define_initial_attributes(); $config['include_in_widgets_config'] = true; $config['default_html_tag'] = static::get_computed_html_tag( [] ); $config['html_tag_follows_link'] = static::html_tag_follows_link(); $config['meta'] = $this->get_meta(); $config['allowed_child_types'] = $this->define_allowed_child_types(); $config['new_until_version'] = self::NEW_ATOMIC_ELEMENTS[ $this->get_name() ] ?? ''; return $config; } protected function should_show_in_panel() { return true; } protected function define_panel_categories(): array { return [ 'v4-elements' ]; } protected function define_default_children() { return []; } /** * Declare settings→children reconcile rules for this element. * * Each rule ties a `Dependency_Manager` condition on this element's * settings to the presence of a specific child element type. The generic * client-side reconciler (`@elementor/editor-elements/children-dependencies`) * attaches / detaches the child at the model layer as the condition flips, * without per-widget v1 hooks. * * @return Child_Dependency[] */ protected function define_children_dependencies(): array { return []; } private function get_children_dependencies_config(): array { $config = []; foreach ( $this->define_children_dependencies() as $dependency ) { if ( ! $dependency instanceof Child_Dependency ) { throw new \InvalidArgumentException( esc_html( static::class . '::define_children_dependencies() must return Child_Dependency instances.' ) ); } $config[] = $dependency->build(); } return $config; } protected function define_initial_attributes() { return []; } protected function define_allowed_child_types() { return []; } protected function get_interaction_id() { return $this->origin_id ?? $this->get_id(); } protected function add_render_attributes() { parent::add_render_attributes(); $this->add_render_attribute( '_wrapper', 'data-interaction-id', $this->get_interaction_id() ); } /** * Get Element keywords. * * Retrieve the element keywords. * * @since 3.29 * @access public * * @return array Element keywords. */ public function get_keywords() { return []; } /** * @return array */ abstract protected static function define_props_schema(): array; /** * Get the HTML tag for rendering. * * @return string */ protected function get_html_tag(): string { return static::get_computed_html_tag( $this->get_atomic_settings() ); } /** * Print safe HTML tag for the element based on the element settings. * * @return void */ protected function print_html_tag() { $html_tag = $this->get_html_tag(); Utils::print_validated_html_tag( $html_tag ); } /** * Print custom attributes if they exist. * * @return void */ protected function print_custom_attributes() { $settings = $this->get_atomic_settings(); $attributes = $settings['attributes'] ?? ''; if ( isset( $settings['link']['attributes'] ) ) { $attributes .= ' ' . ( $settings['link']['attributes'] ?? '' ); } if ( ! empty( $attributes ) && is_string( $attributes ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo ' ' . $attributes; } } /** * Get default child type for container elements. * * @param array $element_data * @return mixed */ protected function _get_default_child_type( array $element_data ) { $el_types = array_keys( Plugin::$instance->elements_manager->get_element_types() ); if ( in_array( $element_data['elType'], $el_types, true ) ) { return Plugin::$instance->elements_manager->get_element_types( $element_data['elType'] ); } if ( ! isset( $element_data['widgetType'] ) ) { return null; } return Plugin::$instance->widgets_manager->get_widget_types( $element_data['widgetType'] ); } /** * Default before render for container elements. * * @return void */ public function before_render() { ?> <print_html_tag(); ?> print_render_attribute_string( '_wrapper' ); $this->print_custom_attributes(); ?>> print_html_tag(); ?>>