PluginProbe
Elementor Website Builder – more than just a page builder / trunk
Elementor Website Builder – more than just a page builder vtrunk
4.3.3 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 All 456 releases
← All changes | modules/mcp/abilities/appliers/element-config-applier.php +67 -0 4.3.1 → trunk View file →
@@ -11,8 +11,9 @@
11 11 use Elementor\Modules\Mcp\Abilities\Appliers\V3\V3_Non_Style_Allowlist;
12 12 use Elementor\Modules\Mcp\Abilities\Appliers\V3\V3_Settings_Validator;
13 13 use Elementor\Modules\Mcp\Abilities\Build_Composition\Widget_Type_Resolver;
14 14 use Elementor\Modules\Mcp\Abilities\Prop_Canonicalizer;
15 +use Elementor\Modules\Mcp\Abilities\Utils\Dropped_Plain_Keys_Finder;
15 16
16 17 if ( ! defined( 'ABSPATH' ) ) {
17 18 exit;
18 19 }
@@ -105,8 +106,17 @@
105 106 }
106 107
107 108 $outcome = $this->resolve_settings_against_schema( $settings, $schema, $tag, $config_id, $errors, $warnings, $warning_codes );
108 109
110 + $this->warn_dropped_object_sub_keys(
111 + $node['settings'] ?? [],
112 + $outcome['resolved'],
113 + $tag,
114 + $config_id,
115 + $warnings,
116 + $warning_codes
117 + );
118 +
109 119 $node['settings'] = array_merge( $node['settings'] ?? [], $outcome['resolved'] );
110 120
111 121 foreach ( $outcome['cleared'] as $cleared_key ) {
112 122 unset( $node['settings'][ $cleared_key ] );
@@ -210,8 +220,14 @@
210 220 );
211 221 continue;
212 222 }
213 223
224 + $dropped_paths = Dropped_Plain_Keys_Finder::find( $value, $resolved_value, $canonical );
225 +
226 + if ( ! empty( $dropped_paths ) ) {
227 + $this->warn_plain_keys_dropped( $dropped_paths, $canonical, $element_type, $config_id, $warnings, $warning_codes );
228 + }
229 +
214 230 $resolved[ $canonical ] = $resolved_value;
215 231 }
216 232
217 233 return [
@@ -217,8 +233,59 @@
217 233 return [
218 234 'resolved' => $resolved,
219 235 'cleared' => $cleared,
220 236 ];
237 + }
238 +
239 + private function warn_dropped_object_sub_keys( array $node_settings, array $resolved, string $element_type, string $config_id, array &$warnings, array &$warning_codes ): void {
240 + foreach ( $resolved as $key => $value ) {
241 + $stored = $node_settings[ $key ] ?? null;
242 +
243 + if (
244 + ! $this->is_object_prop_value( $stored )
245 + || ! $this->is_object_prop_value( $value )
246 + || $stored['$$type'] !== $value['$$type']
247 + ) {
248 + continue;
249 + }
250 +
251 + $stored_sub_values = array_filter( $stored['value'], fn( $sub_value ) => null !== $sub_value );
252 + $dropped_sub_keys = array_keys( array_diff_key( $stored_sub_values, $value['value'] ) );
253 +
254 + if ( empty( $dropped_sub_keys ) ) {
255 + continue;
256 + }
257 +
258 + $warnings[] = sprintf(
259 + '[%s] Property "%s" on "%s" was replaced as a whole, dropping its stored "%s". Send the full value (as returned by elementor/get-page-structure) to keep them. See elementor://widgets/schema/%s.',
260 + $config_id,
261 + $key,
262 + $element_type,
263 + implode( '", "', $dropped_sub_keys ),
264 + $element_type
265 + );
266 + $warning_codes[] = 'prop_subkeys_dropped';
267 + }
268 + }
269 +
270 + private function warn_plain_keys_dropped( array $dropped_paths, string $key, string $element_type, string $config_id, array &$warnings, array &$warning_codes ): void {
271 + $warnings[] = sprintf(
272 + '[%s] Property "%s" on "%s" was saved without "%s": each is either not a field of the prop or has a value that could not be resolved. Use the shape from elementor://widgets/schema/%s.',
273 + $config_id,
274 + $key,
275 + $element_type,
276 + implode( '", "', $dropped_paths ),
277 + $element_type
278 + );
279 + $warning_codes[] = 'prop_keys_dropped';
280 + }
281 +
282 + private function is_object_prop_value( $value ): bool {
283 + return is_array( $value )
284 + && isset( $value['$$type'] )
285 + && is_array( $value['value'] ?? null )
286 + && ! empty( $value['value'] )
287 + && ! wp_is_numeric_array( $value['value'] );
221 288 }
222 289
223 290 private function merge_with_clears( array $existing, array $incoming ): array {
224 291 $merged = $existing;