PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
elementor / modules / atomic-widgets / elements / base / atomic-element-base.php

atomic-element-base.php in Elementor Website Builder – more than just a page builder 4.3.0-beta3, at modules/atomic-widgets/elements/base/atomic-element-base.php

296 lines 7.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\AtomicWidgets\Elements\Base;
4
5 use Elementor\Element_Base;
6 use Elementor\Modules\AtomicWidgets\ChildrenDependencies\Child_Dependency;
7 use Elementor\Modules\AtomicWidgets\PropDependencies\Manager as Dependency_Manager;
8 use Elementor\Modules\AtomicWidgets\PropTypes\Contracts\Prop_Type;
9 use Elementor\Modules\AtomicWidgets\PropTypes\Concerns\Has_Meta;
10 use Elementor\Plugin;
11 use Elementor\Utils;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16
17 abstract class Atomic_Element_Base extends Element_Base {
18 use Has_Atomic_Base;
19 use Has_Meta;
20
21 /**
22 * Maps atomic element type → the minor version when the "New" badge expires.
23 * Format: 'element-type' => 'major.minor' (patch is ignored during comparison).
24 *
25 * @var array<string, string>
26 */
27 private const NEW_ATOMIC_ELEMENTS = [
28 'e-background-video' => '4.3',
29 'e-accordion' => '4.3',
30 'e-list' => '4.3',
31 ];
32
33 protected $version = '0.0';
34 protected $styles = [];
35 protected $interactions = [];
36 protected $editor_settings = [];
37 protected $origin_id = null;
38
39 public static $widget_description = null;
40
41
42 public function __construct( $data = [], $args = null ) {
43 parent::__construct( $data, $args );
44
45 $this->version = $data['version'] ?? '0.0';
46 $this->styles = $data['styles'] ?? [];
47 $this->interactions = $this->parse_atomic_interactions( $data['interactions'] ?? [] );
48 $this->editor_settings = $data['editor_settings'] ?? [];
49
50 if ( static::$widget_description ) {
51 $this->description( static::$widget_description );
52 }
53
54 $this->origin_id = $data['origin_id'] ?? null;
55 }
56
57 private function parse_atomic_interactions( $interactions ) {
58 if ( empty( $interactions ) ) {
59 return [];
60 }
61
62 if ( is_string( $interactions ) ) {
63 $decoded = json_decode( $interactions, true );
64 if ( json_last_error() === JSON_ERROR_NONE && is_array( $decoded ) ) {
65 $interactions = $decoded;
66 }
67 }
68
69 if ( ! is_array( $interactions ) ) {
70 return [];
71 }
72
73 return $interactions;
74 }
75
76 abstract protected function define_atomic_controls(): array;
77
78 protected function define_atomic_style_states(): array {
79 return [];
80 }
81
82 protected function define_atomic_pseudo_states(): array {
83 return [];
84 }
85
86 public function get_global_scripts() {
87 return [];
88 }
89
90 protected function get_initial_config() {
91 $config = parent::get_initial_config();
92 $props_schema = static::get_props_schema();
93
94 $config['atomic'] = true;
95 $config['atomic_controls'] = $this->get_atomic_controls();
96 $config['atomic_props_schema'] = $props_schema;
97 $config['atomic_style_states'] = $this->define_atomic_style_states();
98 $config['atomic_pseudo_states'] = $this->define_atomic_pseudo_states();
99 $config['dependencies_per_target_mapping'] = Dependency_Manager::get_source_to_dependents( $props_schema );
100 $config['base_styles'] = $this->get_base_styles();
101 $config['base_settings'] = $this->get_base_settings();
102 $config['version'] = $this->version;
103 $config['show_in_panel'] = $this->should_show_in_panel();
104 $config['categories'] = $this->define_panel_categories();
105 $config['hide_on_search'] = false;
106 $config['controls'] = [];
107 $config['keywords'] = $this->get_keywords();
108 $config['default_children'] = $this->define_default_children();
109 $config['children_dependencies'] = $this->get_children_dependencies_config();
110 $config['initial_attributes'] = $this->define_initial_attributes();
111 $config['include_in_widgets_config'] = true;
112 $config['default_html_tag'] = static::get_computed_html_tag( [] );
113 $config['html_tag_follows_link'] = static::html_tag_follows_link();
114 $config['meta'] = $this->get_meta();
115 $config['allowed_child_types'] = $this->define_allowed_child_types();
116 $config['new_until_version'] = self::NEW_ATOMIC_ELEMENTS[ $this->get_name() ] ?? '';
117
118 return $config;
119 }
120
121 protected function should_show_in_panel() {
122 return true;
123 }
124
125 protected function define_panel_categories(): array {
126 return [ 'v4-elements' ];
127 }
128
129 protected function define_default_children() {
130 return [];
131 }
132
133 /**
134 * Declare settings→children reconcile rules for this element.
135 *
136 * Each rule ties a `Dependency_Manager` condition on this element's
137 * settings to the presence of a specific child element type. The generic
138 * client-side reconciler (`@elementor/editor-elements/children-dependencies`)
139 * attaches / detaches the child at the model layer as the condition flips,
140 * without per-widget v1 hooks.
141 *
142 * @return Child_Dependency[]
143 */
144 protected function define_children_dependencies(): array {
145 return [];
146 }
147
148 private function get_children_dependencies_config(): array {
149 $config = [];
150
151 foreach ( $this->define_children_dependencies() as $dependency ) {
152 if ( ! $dependency instanceof Child_Dependency ) {
153 throw new \InvalidArgumentException(
154 esc_html( static::class . '::define_children_dependencies() must return Child_Dependency instances.' )
155 );
156 }
157
158 $config[] = $dependency->build();
159 }
160
161 return $config;
162 }
163
164 protected function define_initial_attributes() {
165 return [];
166 }
167
168 protected function define_allowed_child_types() {
169 return [];
170 }
171
172 protected function get_interaction_id() {
173 return $this->origin_id ?? $this->get_id();
174 }
175
176 protected function add_render_attributes() {
177 parent::add_render_attributes();
178
179 $this->add_render_attribute( '_wrapper', 'data-interaction-id', $this->get_interaction_id() );
180 }
181
182 /**
183 * Get Element keywords.
184 *
185 * Retrieve the element keywords.
186 *
187 * @since 3.29
188 * @access public
189 *
190 * @return array Element keywords.
191 */
192 public function get_keywords() {
193 return [];
194 }
195
196 /**
197 * @return array<string, Prop_Type>
198 */
199 abstract protected static function define_props_schema(): array;
200
201 /**
202 * Get the HTML tag for rendering.
203 *
204 * @return string
205 */
206 protected function get_html_tag(): string {
207 return static::get_computed_html_tag( $this->get_atomic_settings() );
208 }
209
210 /**
211 * Print safe HTML tag for the element based on the element settings.
212 *
213 * @return void
214 */
215 protected function print_html_tag() {
216 $html_tag = $this->get_html_tag();
217 Utils::print_validated_html_tag( $html_tag );
218 }
219
220 /**
221 * Print custom attributes if they exist.
222 *
223 * @return void
224 */
225 protected function print_custom_attributes() {
226 $settings = $this->get_atomic_settings();
227 $attributes = $settings['attributes'] ?? '';
228
229 if ( isset( $settings['link']['attributes'] ) ) {
230 $attributes .= ' ' . ( $settings['link']['attributes'] ?? '' );
231 }
232
233 if ( ! empty( $attributes ) && is_string( $attributes ) ) {
234 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
235 echo ' ' . $attributes;
236 }
237 }
238
239 /**
240 * Get default child type for container elements.
241 *
242 * @param array $element_data
243 * @return mixed
244 */
245 protected function _get_default_child_type( array $element_data ) {
246 $el_types = array_keys( Plugin::$instance->elements_manager->get_element_types() );
247
248 if ( in_array( $element_data['elType'], $el_types, true ) ) {
249 return Plugin::$instance->elements_manager->get_element_types( $element_data['elType'] );
250 }
251
252 if ( ! isset( $element_data['widgetType'] ) ) {
253 return null;
254 }
255
256 return Plugin::$instance->widgets_manager->get_widget_types( $element_data['widgetType'] );
257 }
258
259 /**
260 * Default before render for container elements.
261 *
262 * @return void
263 */
264 public function before_render() {
265 ?>
266 <<?php $this->print_html_tag(); ?> <?php $this->print_render_attribute_string( '_wrapper' );
267 $this->print_custom_attributes(); ?>>
268 <?php
269 }
270
271 /**
272 * Default after render for container elements.
273 *
274 * @return void
275 */
276 public function after_render() {
277 ?>
278 </<?php $this->print_html_tag(); ?>>
279 <?php
280 }
281
282 /**
283 * Default content template - can be overridden by elements that need custom templates.
284 *
285 * @return void
286 */
287 protected function content_template() {
288 ?>
289 <?php
290 }
291
292 public static function generate() {
293 return Element_Builder::make( static::get_type() );
294 }
295 }
296