← All changes
|
modules/mcp/abilities/appliers/element-config-applier.php
+67
-0
4.3.0-beta3
→
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; |