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

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

216 lines 5.8 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\Core\Utils\Collection;
7 use Elementor\Modules\Components\Utils\Parsing_Utils;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 class Overridable_Groups_Parser {
14 public static function make(): self {
15 return new static();
16 }
17
18 public function parse( array $groups ): Parse_Result {
19 $result = Parse_Result::make();
20
21 $structure_validation_result = $this->validate_structure( $groups );
22
23 if ( ! $structure_validation_result->is_valid() ) {
24 return $structure_validation_result;
25 }
26
27 $parsed_groups = $this->parse_groups_items( $groups['items'] );
28 if ( ! $parsed_groups->is_valid() ) {
29 $result->errors()->merge( $parsed_groups->errors() );
30
31 return $result;
32 }
33
34 $parsed_order = $this->parse_groups_order( $groups['order'] );
35 if ( ! $parsed_order->is_valid() ) {
36 $result->errors()->merge( $parsed_order->errors() );
37
38 return $result;
39 }
40
41 $validation_result = $this->validate( $parsed_groups->unwrap(), $parsed_order->unwrap() );
42
43 if ( ! $validation_result->is_valid() ) {
44 return $validation_result;
45 }
46
47 $sanitized_groups = $this->sanitize( $parsed_groups->unwrap(), $parsed_order->unwrap() );
48
49 return Parse_Result::make()->wrap( $sanitized_groups );
50 }
51
52 private function validate_structure( array $groups ): Parse_Result {
53 $result = Parse_Result::make();
54
55 $inner_fields = [ 'items', 'order' ];
56
57 foreach ( $inner_fields as $inner_field ) {
58 if ( ! isset( $groups[ $inner_field ] ) ) {
59 $result->errors()->add( "groups.$inner_field", 'missing' );
60
61 return $result;
62 }
63
64 if ( ! is_array( $groups[ $inner_field ] ) ) {
65 $result->errors()->add( "groups.$inner_field", 'invalid_structure' );
66
67 return $result;
68 }
69 }
70
71 foreach ( $groups['items'] as $group_id => $group ) {
72 if ( ! is_array( $group ) ) {
73 $result->errors()->add( "groups.items.$group_id", 'invalid_structure' );
74
75 continue;
76 }
77
78 $required_fields = [ 'id', 'label', 'props' ];
79
80 foreach ( $required_fields as $field ) {
81 if ( ! isset( $group[ $field ] ) ) {
82 $result->errors()->add( "groups.items.$group_id.$field", 'missing' );
83 }
84 }
85
86 if ( isset( $group['props'] ) && ! is_array( $group['props'] ) ) {
87 $result->errors()->add( "groups.items.$group_id.props", 'invalid_structure' );
88 }
89 }
90
91 return $result;
92 }
93
94 private function validate( array $items, array $order ): Parse_Result {
95 $result = Parse_Result::make();
96
97 $items_ids_collection = Collection::make( $items )->keys();
98 $order_collection = Collection::make( $order );
99
100 $excess_ids = $order_collection->diff( $items_ids_collection );
101 $missing_ids = $items_ids_collection->diff( $order_collection );
102
103 $excess_ids->each( fn( $id ) => $result->errors()->add( "groups.order.$id", 'excess' ) );
104 $missing_ids->each( fn( $id ) => $result->errors()->add( "groups.order.$id", 'missing' ) );
105
106 return $result;
107 }
108
109 private function parse_groups_items( array $items ): Parse_Result {
110 $result = Parse_Result::make();
111
112 $validate_groups_items_result = $this->validate_groups_items( $items );
113
114 if ( ! $validate_groups_items_result->is_valid() ) {
115 $result->errors()->merge( $validate_groups_items_result->errors() );
116
117 return $result;
118 }
119
120 return Parse_Result::make()->wrap( $this->sanitize_groups_items( $items ) );
121 }
122
123 private function validate_groups_items( array $items ): Parse_Result {
124 $result = Parse_Result::make();
125
126 $labels = [];
127
128 foreach ( $items as $group_id => $group ) {
129 if ( $group_id !== $group['id'] ) {
130 $result->errors()->add( "groups.items.$group_id.id", 'mismatching_value' );
131 }
132
133 $duplicate_props = Parsing_Utils::get_duplicates( $group['props'] );
134
135 if ( ! empty( $duplicate_props ) ) {
136 $result->errors()->add( "groups.items.$group_id.props", 'duplicate_props: ' . implode( ', ', $duplicate_props ) );
137 }
138
139 $labels[] = $group['label'];
140 }
141
142 $duplicate_labels = Parsing_Utils::get_duplicates( $labels );
143
144 if ( ! empty( $duplicate_labels ) ) {
145 $result->errors()->add( 'groups.items', 'duplicate_labels: ' . implode( ', ', $duplicate_labels ) );
146 }
147
148 return $result;
149 }
150
151 private function parse_groups_order( array $order ): Parse_Result {
152 $result = Parse_Result::make();
153
154 $validate_groups_order_result = $this->validate_groups_order( $order );
155
156 if ( ! $validate_groups_order_result->is_valid() ) {
157 return $validate_groups_order_result;
158 }
159
160 return Parse_Result::make()->wrap( $this->sanitize_groups_order( $order ) );
161 }
162
163 private function validate_groups_order( array $order ): Parse_Result {
164 $result = Parse_Result::make();
165
166 $order_collection = Collection::make( $order );
167 $non_string_items = $order_collection->some( fn( $item ) => ! is_string( $item ) );
168
169 if ( $non_string_items ) {
170 $result->errors()->add( 'groups.order', 'non_string_items' );
171
172 return $result;
173 }
174
175 if ( Parsing_Utils::get_duplicates( $order ) ) {
176 $result->errors()->add( 'groups.order', 'duplicate_ids' );
177
178 return $result;
179 }
180
181 return $result;
182 }
183
184 private function sanitize( array $items, array $order ): array {
185 return [
186 'items' => $items,
187 'order' => $order,
188 ];
189 }
190
191 private function sanitize_groups_items( array $items ): array {
192 $sanitized_items = [];
193
194 foreach ( $items as $group_id => $group ) {
195 $sanitized_group_id = sanitize_key( $group_id );
196 $sanitized_items[ $sanitized_group_id ] = $this->sanitize_single_group( $group );
197 }
198
199 return $sanitized_items;
200 }
201
202 private function sanitize_single_group( array $group ): array {
203 return [
204 'id' => sanitize_key( $group['id'] ),
205 'label' => sanitize_text_field( $group['label'] ),
206 'props' => array_map( 'sanitize_key', $group['props'] ),
207 ];
208 }
209
210 private function sanitize_groups_order( array $order ): array {
211 return Collection::make( $order )
212 ->map( fn( $item ) => sanitize_key( $item ) )
213 ->values();
214 }
215 }
216