PluginProbe
Elementor Website Builder – more than just a page builder / 4.2.0
Elementor Website Builder – more than just a page builder v4.2.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 / core / utils / template-library-snapshot-processor.php

template-library-snapshot-processor.php in Elementor Website Builder – more than just a page builder 4.2.0, at core/utils/template-library-snapshot-processor.php

228 lines 6.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\Core\Utils;
4
5 if ( ! defined( 'ABSPATH' ) ) {
6 exit;
7 }
8
9 abstract class Template_Library_Snapshot_Processor {
10
11 abstract protected function get_item_prefix(): string;
12 abstract protected function get_max_items(): int;
13 abstract protected function can_access_repository(): bool;
14 abstract protected function load_current_data(): array;
15 abstract protected function parse_incoming_snapshot( array $snapshot ): ?array;
16 abstract protected function get_incoming_items( array $parsed_snapshot ): array;
17 abstract protected function count_current_items( array $items ): int;
18 /**
19 * @param array $data {
20 * @type array $updated_items All items (existing + new) after processing.
21 * @type array $new_items Only the newly added items.
22 * @type array $order The updated order of all items.
23 * }
24 * @param array $metadata The original data from load_current_data().
25 */
26 abstract protected function save_data( array $data, array $metadata ): array;
27
28 protected function normalize_for_comparison( array $item ): array {
29 return $item;
30 }
31
32 protected function is_matching_item( array $existing_item, array $incoming_item ): bool {
33 return Template_Library_Import_Export_Utils::items_equal_ignoring_keys(
34 $this->normalize_for_comparison( $existing_item ),
35 $incoming_item,
36 []
37 );
38 }
39
40 protected function get_empty_result(): array {
41 return [
42 'id_map' => [],
43 'ids_to_flatten' => [],
44 ];
45 }
46
47 public function merge_and_get_id_map( array $snapshot ): array {
48 if ( ! $this->can_access_repository() ) {
49 return $this->get_empty_result();
50 }
51
52 $parsed = $this->parse_incoming_snapshot( $snapshot );
53 if ( null === $parsed ) {
54 return $this->get_empty_result();
55 }
56
57 $current = $this->load_current_data();
58 $current_items = $current['items'] ?? [];
59 $existing_labels = Template_Library_Import_Export_Utils::extract_labels( $current_items );
60 $label_to_id = Template_Library_Import_Export_Utils::build_label_to_id_index( $current_items );
61
62 $id_map = [];
63 $ids_to_flatten = [];
64 $new_items = [];
65 $updated_items = $current_items;
66 $existing_ids = array_fill_keys( array_keys( $updated_items ), true );
67 $updated_order = $current['order'] ?? [];
68
69 $incoming_items = $this->get_incoming_items( $parsed );
70 foreach ( $incoming_items as $incoming_id => $incoming_item ) {
71 if ( empty( $incoming_item ) ) {
72 continue;
73 }
74
75 $incoming_label = $incoming_item['label'] ?? null;
76 $matching_id = is_string( $incoming_label ) ? ( $label_to_id[ $incoming_label ] ?? null ) : null;
77
78 if ( null !== $matching_id && isset( $updated_items[ $matching_id ] ) ) {
79 $is_same = $this->is_matching_item( $updated_items[ $matching_id ], $incoming_item );
80
81 if ( $is_same ) {
82 if ( $matching_id !== $incoming_id ) {
83 $id_map[ $incoming_id ] = $matching_id;
84 }
85 continue;
86 }
87 }
88
89 if ( $this->count_current_items( $updated_items ) >= $this->get_max_items() ) {
90 $ids_to_flatten[] = $incoming_id;
91 continue;
92 }
93
94 if ( null !== $matching_id && isset( $updated_items[ $matching_id ] ) ) {
95 $target_id = Template_Library_Import_Export_Utils::generate_unique_id(
96 array_keys( $updated_items ),
97 $this->get_item_prefix()
98 );
99 } elseif ( isset( $existing_ids[ $incoming_id ] ) ) {
100 $target_id = Template_Library_Import_Export_Utils::generate_unique_id(
101 array_keys( $updated_items ),
102 $this->get_item_prefix()
103 );
104 } else {
105 $target_id = $incoming_id;
106 }
107
108 if ( $target_id !== $incoming_id ) {
109 $id_map[ $incoming_id ] = $target_id;
110 }
111
112 $this->add_item_with_label(
113 $incoming_item,
114 $target_id,
115 $updated_items,
116 $existing_ids,
117 $existing_labels,
118 $updated_order,
119 $new_items
120 );
121
122 $new_label = $updated_items[ $target_id ]['label'] ?? null;
123 if ( is_string( $new_label ) && ! isset( $label_to_id[ $new_label ] ) ) {
124 $label_to_id[ $new_label ] = $target_id;
125 }
126 }
127
128 $saved_result = $this->save_data( [
129 'updated_items' => $updated_items,
130 'new_items' => $new_items,
131 'order' => $updated_order,
132 ], $current );
133
134 return array_merge($this->get_empty_result(), [
135 'id_map' => $id_map,
136 'ids_to_flatten' => $ids_to_flatten,
137 ], $saved_result);
138 }
139
140 public function create_all_as_new( array $snapshot ): array {
141 return $this->process_snapshot($snapshot, function ( $incoming_id, $incoming_item, $updated_items ) {
142 return Template_Library_Import_Export_Utils::generate_unique_id( array_keys( $updated_items ), $this->get_item_prefix() );
143 });
144 }
145
146 protected function process_snapshot( array $snapshot, callable $id_strategy ): array {
147 if ( ! $this->can_access_repository() ) {
148 return $this->get_empty_result();
149 }
150
151 $parsed = $this->parse_incoming_snapshot( $snapshot );
152 if ( null === $parsed ) {
153 return $this->get_empty_result();
154 }
155
156 $current = $this->load_current_data();
157 $current_items = $current['items'] ?? [];
158 $existing_labels = Template_Library_Import_Export_Utils::extract_labels( $current_items );
159
160 $id_map = [];
161 $ids_to_flatten = [];
162 $new_items = [];
163 $updated_items = $current_items;
164 $existing_ids = array_fill_keys( array_keys( $updated_items ), true );
165 $updated_order = $current['order'] ?? [];
166
167 $incoming_items = $this->get_incoming_items( $parsed );
168
169 foreach ( $incoming_items as $incoming_id => $incoming_item ) {
170 if ( empty( $incoming_item ) ) {
171 continue;
172 }
173
174 if ( $this->count_current_items( $updated_items ) >= $this->get_max_items() ) {
175 $ids_to_flatten[] = $incoming_id;
176 continue;
177 }
178
179 $target_id = $id_strategy( $incoming_id, $incoming_item, $updated_items, $existing_ids );
180
181 if ( null === $target_id ) {
182 continue;
183 }
184
185 if ( $target_id !== $incoming_id ) {
186 $id_map[ $incoming_id ] = $target_id;
187 }
188
189 $this->add_item_with_label(
190 $incoming_item,
191 $target_id,
192 $updated_items,
193 $existing_ids,
194 $existing_labels,
195 $updated_order,
196 $new_items
197 );
198 }
199
200 $saved_result = $this->save_data( [
201 'updated_items' => $updated_items,
202 'new_items' => $new_items,
203 'order' => $updated_order,
204 ], $current );
205
206 return array_merge($this->get_empty_result(), [
207 'id_map' => $id_map,
208 'ids_to_flatten' => $ids_to_flatten,
209 ], $saved_result);
210 }
211
212 protected function add_item_with_label( array $item, string $target_id, array &$updated_items, array &$existing_ids, array &$existing_labels, array &$updated_order, array &$new_items ): void {
213 $item = $this->prepare_item_for_save( $item, $target_id );
214 $item = Template_Library_Import_Export_Utils::apply_unique_label( $item, $existing_labels );
215 $updated_items[ $target_id ] = $item;
216 $new_items[ $target_id ] = $item;
217 $existing_ids[ $target_id ] = true;
218
219 if ( ! in_array( $target_id, $updated_order, true ) ) {
220 $updated_order[] = $target_id;
221 }
222 }
223
224 protected function prepare_item_for_save( array $item, string $target_id ): array {
225 return $item;
226 }
227 }
228