PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.2
Elementor Website Builder – more than just a page builder v4.3.2
4.3.2 4.3.1 4.3.0 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 All 455 releases
← All changes | modules/mcp/abilities/utils/composition-compiler.php +84 -18 4.3.0-beta1 → 4.3.2 View file →
@@ -33,9 +33,8 @@
33 33 final class Composition_Compiler {
34 34
35 35 private const DEFAULT_PARENT_ID = 'document';
36 36 private const DOCUMENT_ROOT_WRAPPER = 'e-div-block';
37 - private const COMPONENT_INSTANCE_WIDGET_TYPE = 'e-component';
38 37
39 38 public const COMPONENT_PARENT_ID = 'component';
40 39
41 40 public static function make(): self {
@@ -64,22 +63,24 @@
64 63 if ( is_wp_error( $dom ) ) {
65 64 return $dom;
66 65 }
67 66
68 - $form_structure_error = ( new Form_Structure_Validator( $xml_parser ) )->validate(
67 + [
68 + 'configs' => $widget_configs,
69 + 'unknown_tag_errors' => $unknown_widget_tag_errors,
70 + ] = $type_resolver->collect_referenced_widget_configs( $dom );
71 +
72 + $validation_error = $this->validate_xml_before_apply(
69 73 $dom,
74 + $xml_parser,
70 75 $document_tree,
71 - $parent_id
76 + $parent_id,
77 + $unknown_widget_tag_errors
72 78 );
73 - if ( $form_structure_error ) {
74 - return $form_structure_error;
79 + if ( $validation_error ) {
80 + return $validation_error;
75 81 }
76 82
77 - $widget_configs = $type_resolver->collect_used( $dom );
78 - if ( is_wp_error( $widget_configs ) ) {
79 - return $widget_configs;
80 - }
81 -
82 83 $wrapping_result = $this->wrap_document_root_content( $dom, $widget_configs, $parent_id, $type_resolver, $xml_parser );
83 84 if ( is_wp_error( $wrapping_result ) ) {
84 85 return $wrapping_result;
85 86 }
@@ -85,11 +86,15 @@
85 86 }
86 87
87 88 $widget_configs = $wrapping_result['widget_configs'];
88 89
89 - $child_type_error = $type_resolver->validate_child_types( $dom, $widget_configs );
90 - if ( $child_type_error ) {
91 - return $child_type_error;
90 + $child_type_errors = $type_resolver->collect_child_type_and_required_child_errors( $dom, $widget_configs );
91 + if ( ! empty( $child_type_errors ) ) {
92 + return new \WP_Error(
93 + 'elementor_invalid_child_type',
94 + implode( ' ', $child_type_errors ),
95 + [ 'status' => \WP_Http::BAD_REQUEST ]
96 + );
92 97 }
93 98
94 99 $subtrees = $subtree_builder->build( $dom, $widget_configs );
95 100 if ( empty( $subtrees ) ) {
@@ -129,13 +134,72 @@
129 134
130 135 return [
131 136 'elements' => $subtrees,
132 137 'warnings' => array_merge( $wrapping_result['warnings'], $config_result['warnings'], $style_result['warnings'], $interactions_result['warnings'] ),
138 + 'warning_codes' => array_values( array_unique( array_merge(
139 + $wrapping_result['warning_codes'] ?? [],
140 + $config_result['warning_codes'] ?? [],
141 + $style_result['warning_codes'] ?? [],
142 + $interactions_result['warning_codes'] ?? []
143 + ) ) ),
133 144 'dom' => $dom,
134 145 'xml_parser' => $xml_parser,
135 146 ];
136 147 }
137 148
149 + /**
150 + * @param \DOMDocument $dom
151 + * @param Xml_Parser $xml_parser
152 + * @param array $document_tree
153 + * @param string $parent_id
154 + * @param string[] $unknown_widget_tag_errors
155 + *
156 + * @return \WP_Error|null
157 + */
158 + private function validate_xml_before_apply(
159 + \DOMDocument $dom,
160 + Xml_Parser $xml_parser,
161 + array $document_tree,
162 + string $parent_id,
163 + array $unknown_widget_tag_errors
164 + ) {
165 + $errors = array_merge(
166 + $this->tag_errors( 'elementor_duplicate_configuration_id', $xml_parser->collect_duplicate_configuration_id_errors( $dom ) ),
167 + $this->tag_errors( 'elementor_invalid_form_structure', ( new Form_Structure_Validator( $xml_parser ) )->collect_errors( $dom, $document_tree, $parent_id ) ),
168 + $this->tag_errors( 'elementor_unknown_type', $unknown_widget_tag_errors ),
169 + );
170 +
171 + if ( empty( $errors ) ) {
172 + return null;
173 + }
174 +
175 + $status = [ 'status' => \WP_Http::BAD_REQUEST ];
176 + $joined = implode( ' ', array_column( $errors, 'message' ) );
177 +
178 + $aggregated = new \WP_Error( $errors[0]['code'], $joined, $status );
179 + foreach ( array_slice( $errors, 1 ) as $error ) {
180 + $aggregated->add( $error['code'], $error['message'], $status );
181 + }
182 +
183 + return $aggregated;
184 + }
185 +
186 + /**
187 + * @param string $code Error code to tag each message with.
188 + * @param string[] $messages List of error messages.
189 + *
190 + * @return array<int, array{code: string, message: string}>
191 + */
192 + private function tag_errors( string $code, array $messages ): array {
193 + return array_map(
194 + fn ( $message ) => [
195 + 'code' => $code,
196 + 'message' => $message,
197 + ],
198 + $messages
199 + );
200 + }
201 +
138 202 private function wrap_document_root_content(
139 203 \DOMDocument $dom,
140 204 array $widget_configs,
141 205 string $parent_id,
@@ -145,8 +209,9 @@
145 209 if ( self::DEFAULT_PARENT_ID !== $parent_id ) {
146 210 return [
147 211 'widget_configs' => $widget_configs,
148 212 'warnings' => [],
213 + 'warning_codes' => [],
149 214 ];
150 215 }
151 216
152 217 $root = $xml_parser->get_root( $dom );
@@ -153,8 +218,9 @@
153 218 if ( ! $root ) {
154 219 return [
155 220 'widget_configs' => $widget_configs,
156 221 'warnings' => [],
222 + 'warning_codes' => [],
157 223 ];
158 224 }
159 225
160 226 $root_children = $xml_parser->get_child_elements( $root );
@@ -166,12 +232,8 @@
166 232 if ( 'widget' !== ( $config['elType'] ?? null ) ) {
167 233 continue;
168 234 }
169 235
170 - if ( self::COMPONENT_INSTANCE_WIDGET_TYPE === ( $config['widgetType'] ?? null ) ) {
171 - continue;
172 - }
173 -
174 236 $has_widget = true;
175 237 break;
176 238 }
177 239
@@ -178,8 +240,9 @@
178 240 if ( ! $has_widget ) {
179 241 return [
180 242 'widget_configs' => $widget_configs,
181 243 'warnings' => [],
244 + 'warning_codes' => [],
182 245 ];
183 246 }
184 247
185 248 $wrapper_config = $type_resolver->resolve_type_config( self::DOCUMENT_ROOT_WRAPPER );
@@ -198,8 +261,9 @@
198 261
199 262 return [
200 263 'widget_configs' => $widget_configs,
201 264 'warnings' => [ __( 'Direct document-root content was wrapped in an e-div-block element.', 'elementor' ) ],
265 + 'warning_codes' => [ 'root_auto_wrapped' ],
202 266 ];
203 267 }
204 268
205 269 private function as_map( $value ): array {
@@ -258,8 +322,9 @@
258 322 if ( empty( $interactions ) ) {
259 323 return [
260 324 'error' => null,
261 325 'warnings' => [],
326 + 'warning_codes' => [],
262 327 ];
263 328 }
264 329
265 330 if ( ! Plugin::$instance->experiments->is_feature_active( Interactions_Module::EXPERIMENT_NAME ) ) {
@@ -265,14 +330,15 @@
265 330 if ( ! Plugin::$instance->experiments->is_feature_active( Interactions_Module::EXPERIMENT_NAME ) ) {
266 331 return [
267 332 'error' => null,
268 333 'warnings' => [ __( 'Interactions experiment is not active. Interactions were not applied.', 'elementor' ) ],
334 + 'warning_codes' => [ 'interactions_experiment_off' ],
269 335 ];
270 336 }
271 337
272 338 $applier = new Interactions_Applier( $this->get_plain_values_resolver() );
273 339
274 - return $applier->apply( $index, $interactions );
340 + return $applier->apply( $index, $interactions ) + [ 'warning_codes' => [] ];
275 341 }
276 342
277 343 private function is_variables_active(): bool {
278 344 $experiments = Plugin::$instance->experiments;