PluginProbe
Elementor Website Builder – more than just a page builder / 3.35.3
Elementor Website Builder – more than just a page builder v3.35.3
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 / components / overridable-props / component-overridable-props-parser.php

component-overridable-props-parser.php in Elementor Website Builder – more than just a page builder 3.35.3, at modules/components/overridable-props/component-overridable-props-parser.php

196 lines 5.0 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\Components\OverridableProps;
4
5 use Elementor\Core\Utils\Api\Parse_Result;
6 use Elementor\Modules\Components\Utils\Parsing_Utils;
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Validates and sanitizes component overridable props object.
14 *
15 * Valid input example:
16 * ```
17 * [
18 * 'props' => [
19 * 'prop1_UUID' => [
20 * 'overrideKey' => 'prop1_UUID',
21 * 'label' => 'User Name',
22 * 'elementId' => '90d25e3',
23 * 'propKey' => 'title',
24 * 'elType' => 'widget',
25 * 'widgetType' => 'e-heading',
26 * 'originValue' => [
27 * '$$type' => 'html',
28 * 'value' => 'Jane Smith',
29 * ],
30 * 'groupId' => 'group1_UUID',
31 * ],
32 * ],
33 * 'groups' => [
34 * 'items' => [
35 * 'group1_UUID' => [
36 * 'id' => 'group1_UUID',
37 * 'label' => 'User Info',
38 * 'props' => [ 'prop1_UUID' ],
39 * ],
40 * ],
41 * 'order' => [ 'group1_UUID' ],
42 * ],
43 * ];
44 * ```
45 */
46 class Component_Overridable_Props_Parser {
47 private Overridable_Props_Parser $props_parser;
48 private Overridable_Groups_Parser $groups_parser;
49
50 public function __construct(
51 Overridable_Props_Parser $props_parser,
52 Overridable_Groups_Parser $groups_parser
53 ) {
54 $this->props_parser = $props_parser;
55 $this->groups_parser = $groups_parser;
56 }
57
58 public static function make(): self {
59 return new static(
60 Overridable_Props_Parser::make(),
61 Overridable_Groups_Parser::make()
62 );
63 }
64
65 /**
66 * @param array $data
67 *
68 * @return Parse_Result
69 */
70 public function parse( array $data ): Parse_Result {
71 $result = Parse_Result::make();
72
73 if ( empty( $data ) ) {
74 return $result->wrap( [] );
75 }
76
77 $inner_fields_structure_result = $this->validate_inner_fields_structure( $data );
78
79 if ( ! $inner_fields_structure_result->is_valid() ) {
80 $result->errors()->merge( $inner_fields_structure_result->errors() );
81
82 return $result;
83 }
84
85 if ( empty( $data['props'] ) && empty( $data['groups'] ) ) {
86 return $result->wrap( [] );
87 }
88
89 $props_result = $this->props_parser->parse( $data['props'] );
90
91 if ( ! $props_result->is_valid() ) {
92 $result->errors()->merge( $props_result->errors() );
93
94 return $result;
95 }
96
97 $groups_result = $this->groups_parser->parse( $data['groups'] );
98
99 if ( ! $groups_result->is_valid() ) {
100 $result->errors()->merge( $groups_result->errors() );
101
102 return $result;
103 }
104
105 $parsed_props = $props_result->unwrap();
106 $parsed_groups = $groups_result->unwrap();
107
108 $validation_result = $this->validate( $parsed_props, $parsed_groups );
109
110 if ( ! $validation_result->is_valid() ) {
111 $result->errors()->merge( $validation_result->errors() );
112
113 return $result;
114 }
115
116 return $this->sanitize( $parsed_props, $parsed_groups );
117 }
118
119 private function validate_inner_fields_structure( array $data ): Parse_Result {
120 $result = Parse_Result::make();
121
122 $inner_fields = [ 'props', 'groups' ];
123
124 foreach ( $inner_fields as $inner_field ) {
125 if ( ! isset( $data[ $inner_field ] ) ) {
126 $result->errors()->add( $inner_field, 'missing' );
127
128 return $result;
129 }
130
131 if ( ! is_array( $data[ $inner_field ] ) ) {
132 $result->errors()->add( $inner_field, 'invalid_structure' );
133
134 return $result;
135 }
136 }
137
138 return $result;
139 }
140
141 private function validate( array $props, array $groups ): Parse_Result {
142 $result = Parse_Result::make();
143
144 $group_items = $groups['items'];
145
146 $props_in_groups = [];
147
148 foreach ( $group_items as $group_id => $group ) {
149 foreach ( $group['props'] as $prop_id ) {
150 if ( ! isset( $props[ $prop_id ] ) ) {
151 $result->errors()->add( "groups.items.$group_id.props.$prop_id", 'prop_not_found_in_props' );
152 } else {
153 $props_in_groups[ $prop_id ] = $group_id;
154 }
155 }
156 }
157
158 foreach ( $props as $prop_id => $prop ) {
159 if ( ! isset( $props_in_groups[ $prop_id ] ) || $prop['groupId'] !== $props_in_groups[ $prop_id ] ) {
160 $result->errors()->add( "props.$prop_id.groupId", 'mismatching_value_with_groups.items.props' );
161 }
162 }
163
164 $duplicate_labels_result = $this->check_duplicate_labels_within_groups( $group_items, $props );
165
166 if ( ! $duplicate_labels_result->is_valid() ) {
167 $result->errors()->merge( $duplicate_labels_result->errors(), 'groups.items' );
168 }
169
170 return $result;
171 }
172
173 private function sanitize( array $props, array $groups ): Parse_Result {
174 return Parse_Result::make()->wrap( [
175 'props' => $props,
176 'groups' => $groups,
177 ] );
178 }
179
180 private function check_duplicate_labels_within_groups( array $groups, array $props ): Parse_Result {
181 $result = Parse_Result::make();
182
183 foreach ( $groups as $group_id => $group ) {
184 $group_props = $group['props'];
185 $labels = array_map( fn( $prop_id ) => $props[ $prop_id ]['label'], $group_props );
186 $duplicate_labels = Parsing_Utils::get_duplicates( $labels );
187
188 if ( ! empty( $duplicate_labels ) ) {
189 $result->errors()->add( "$group_id.props", 'duplicate_labels: ' . implode( ', ', $duplicate_labels ) );
190 }
191 }
192
193 return $result;
194 }
195 }
196