PluginProbe
Elementor Website Builder – more than just a page builder / 3.26.0-dev4
Elementor Website Builder – more than just a page builder v3.26.0-dev4
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 4.0.7 All 451 releases
elementor / modules / atomic-widgets / base / atomic-widget-base.php

atomic-widget-base.php in Elementor Website Builder – more than just a page builder 3.26.0-dev4, at modules/atomic-widgets/base/atomic-widget-base.php

177 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Modules\AtomicWidgets\Base;
3
4 use Elementor\Modules\AtomicWidgets\Controls\Section;
5 use Elementor\Modules\AtomicWidgets\PropTypes\Contracts\Prop_Type;
6 use Elementor\Modules\AtomicWidgets\Styles\Style_Schema;
7 use Elementor\Modules\AtomicWidgets\Validators\Props_Validator;
8 use Elementor\Modules\AtomicWidgets\PropsResolver\Props_Resolver;
9 use Elementor\Modules\AtomicWidgets\Validators\Styles_Validator;
10 use Elementor\Utils;
11 use Elementor\Widget_Base;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16
17 abstract class Atomic_Widget_Base extends Widget_Base {
18 protected $version = '0.0';
19 protected $styles = [];
20
21 public function __construct( $data = [], $args = null ) {
22 parent::__construct( $data, $args );
23
24 $this->version = $data['version'] ?? '0.0';
25 $this->styles = $data['styles'] ?? [];
26 }
27
28 public function has_widget_inner_wrapper(): bool {
29 return false;
30 }
31
32 public function get_atomic_controls() {
33 $controls = $this->define_atomic_controls();
34 $schema = static::get_props_schema();
35
36 // Validate the schema only in the Editor.
37 static::validate_schema( $schema );
38
39 return $this->get_valid_controls( $schema, $controls );
40 }
41
42 private function get_valid_controls( array $schema, array $controls ): array {
43 $valid_controls = [];
44
45 foreach ( $controls as $control ) {
46 if ( $control instanceof Section ) {
47 $cloned_section = clone $control;
48
49 $cloned_section->set_items(
50 $this->get_valid_controls( $schema, $control->get_items() )
51 );
52
53 $valid_controls[] = $cloned_section;
54 continue;
55 }
56
57 if ( ! ( $control instanceof Atomic_Control_Base ) ) {
58 Utils::safe_throw( 'Control must be an instance of `Atomic_Control_Base`.' );
59 continue;
60 }
61
62 $prop_name = $control->get_bind();
63
64 if ( ! $prop_name ) {
65 Utils::safe_throw( 'Control is missing a bound prop from the schema.' );
66 continue;
67 }
68
69 if ( ! array_key_exists( $prop_name, $schema ) ) {
70 Utils::safe_throw( "Prop `{$prop_name}` is not defined in the schema of `{$this->get_name()}`." );
71 continue;
72 }
73
74 $valid_controls[] = $control;
75 }
76
77 return $valid_controls;
78 }
79
80 abstract protected function define_atomic_controls(): array;
81
82 final public function get_controls( $control_id = null ) {
83 if ( ! empty( $control_id ) ) {
84 return null;
85 }
86
87 return [];
88 }
89
90 final public function get_initial_config() {
91 $config = parent::get_initial_config();
92
93 $config['atomic_controls'] = $this->get_atomic_controls();
94 $config['atomic_props_schema'] = static::get_props_schema();
95 $config['version'] = $this->version;
96
97 return $config;
98 }
99
100 final public function get_data_for_save() {
101 $data = parent::get_data_for_save();
102
103 $data['version'] = $this->version;
104 $data['settings'] = $this->sanitize_atomic_settings( $data['settings'] );
105 $data['styles'] = $this->sanitize_atomic_styles( $data['styles'] );
106
107 return $data;
108 }
109
110 final public function get_raw_data( $with_html_content = false ) {
111 $raw_data = parent::get_raw_data( $with_html_content );
112
113 $raw_data['styles'] = $this->styles;
114
115 return $raw_data;
116 }
117
118 final public function get_stack( $with_common_controls = true ) {
119 return [
120 'controls' => [],
121 'tabs' => [],
122 ];
123 }
124
125 final public function get_atomic_settings(): array {
126 $schema = static::get_props_schema();
127 $props = $this->get_settings();
128
129 return Props_Resolver::for_settings()->resolve( $schema, $props );
130 }
131
132 public static function get_props_schema(): array {
133 return apply_filters(
134 'elementor/atomic-widgets/props-schema',
135 static::define_props_schema()
136 );
137 }
138
139 // TODO: Move to a `Schema_Validator` class?
140 private static function validate_schema( array $schema ) {
141 $widget_name = static::class;
142
143 foreach ( $schema as $key => $prop ) {
144 if ( ! ( $prop instanceof Prop_Type ) ) {
145 Utils::safe_throw( "Prop `$key` must be an instance of `Prop_Type` in `{$widget_name}`." );
146 }
147 }
148 }
149
150 private function sanitize_atomic_styles( array $styles ) {
151 [ , $validated, $errors ] = Styles_Validator::make( Style_Schema::get() )->validate( $styles );
152
153 if ( ! empty( $errors ) ) {
154 throw new \Exception( 'Styles validation failed. Invalid keys: ' . join( ', ', $errors ) );
155 }
156
157 return $validated;
158 }
159
160 private function sanitize_atomic_settings( array $settings ): array {
161 $schema = static::get_props_schema();
162
163 [ , $validated, $errors ] = Props_Validator::make( $schema )->validate( $settings );
164
165 if ( ! empty( $errors ) ) {
166 throw new \Exception( 'Settings validation failed. Invalid keys: ' . join( ', ', $errors ) );
167 }
168
169 return $validated;
170 }
171
172 /**
173 * @return array<string, Prop_Type>
174 */
175 abstract protected static function define_props_schema(): array;
176 }
177