PluginProbe
Elementor Website Builder – more than just a page builder / 4.1.0-dev3
Elementor Website Builder – more than just a page builder v4.1.0-dev3
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 4.1.0-dev2 All 455 releases
← All changes | modules/global-classes/global-classes-repository.php +84 -201 4.3.0 → 4.1.0-dev3 View file →
@@ -2,9 +2,9 @@
2 2 namespace Elementor\Modules\GlobalClasses;
3 3
4 4 use Elementor\Core\Kits\Documents\Kit;
5 5 use Elementor\Modules\DesignSystemSync\Classes\Global_Classes_Sync_Map;
6 -use Elementor\Core\Kits\Concerns\Has_Kit_Dependency;
6 +use Elementor\Modules\GlobalClasses\Concerns\Has_Kit_Dependency;
7 7 use Elementor\Modules\GlobalClasses\Concerns\Has_Preview_Context;
8 8 use Elementor\Modules\GlobalClasses\Utils\Global_Class_Data_Normalizer;
9 9
10 10 if ( ! defined( 'ABSPATH' ) ) {
@@ -28,8 +28,12 @@
28 28 'event' => [
29 29 'frontend' => self::CONTEXT_FRONTEND,
30 30 'preview' => self::CONTEXT_PREVIEW,
31 31 ],
32 + 'meta_key' => [
33 + 'frontend' => self::META_KEY_FRONTEND,
34 + 'preview' => self::META_KEY_PREVIEW,
35 + ],
32 36 ];
33 37
34 38 private ?Global_Classes $cache = null;
35 39
@@ -66,15 +70,13 @@
66 70 return $this->labels()->get_ordered_labels();
67 71 }
68 72
69 73 public function get_order(): array {
70 - return Global_Classes_Order::make( $this->get_kit() )->set_preview( $this->is_preview() )->get_order();
74 + return Global_Classes_Order::make( $this->get_kit() )->get_order();
71 75 }
72 76
73 77 public function update_order_and_labels( array $order, array $new_labels ): void {
74 - Global_Classes_Order::make( $this->get_kit() )
75 - ->set_preview( $this->is_preview() )
76 - ->set_order( $order );
78 + Global_Classes_Order::make( $this->get_kit() )->set_order( $order );
77 79
78 80 $labels = $this->labels();
79 81 $existing_labels = $labels->get_labels();
80 82
@@ -91,9 +93,9 @@
91 93 return Global_Classes_Labels::make( $this->get_kit() )->set_preview( $this->is_preview() );
92 94 }
93 95
94 96 public function get( string $class_id ): ?array {
95 - $post = Global_Class_Post::find_by_class_id( $class_id, $this->is_preview(), $this->get_kit() );
97 + $post = Global_Class_Post::find_by_class_id( $class_id, $this->is_preview() );
96 98
97 99 return $post ? $post->to_array() : null;
98 100 }
99 101
@@ -101,17 +103,13 @@
101 103 if ( empty( $class_ids ) ) {
102 104 return [];
103 105 }
104 106
105 - $post_ids = Global_Classes_Post_IDs::make( $this->get_kit() )->get_post_ids( $class_ids );
106 107 $items = [];
107 108
108 - foreach ( $post_ids as $class_id => $post_id ) {
109 - $post = Global_Class_Post::from_post_id( $post_id, $this->is_preview() );
110 -
111 - if ( $post ) {
112 - $items[ $class_id ] = $post->to_array();
113 - }
109 + foreach ( $this->iterate_class_posts_for_ids( $class_ids ) as $class_post ) {
110 + $class_data = $class_post->to_array();
111 + $items[ $class_data['id'] ] = $class_data;
114 112 }
115 113
116 114 return $items;
117 115 }
@@ -133,26 +131,24 @@
133 131 $final_label_map[ $id ] = $before[ $id ];
134 132 }
135 133 }
136 134
137 - $affected_post_ids = $this->get_posts_affected_by_deletion( $to_delete );
138 -
139 135 $this->persist_class_batch_mutations( $to_delete, $to_create, $to_update, $touched_items, $is_preview );
140 136
141 - $classes_order = Global_Classes_Order::make( $this->get_kit() )->set_preview( $this->is_preview() );
137 + $classes_order = Global_Classes_Order::make( $this->get_kit() );
142 138 $classes_order->set_order( $order );
143 139 $labels->set_labels( $final_label_map );
144 140
145 141 if ( ! $is_preview ) {
146 142 Global_Classes_Sync_Map::make( $this->get_kit() )->apply_changes( $touched_items, $to_delete );
147 - $this->propagate_order_to_preview( $order, $to_delete );
148 143
149 - $this->bulk_clear_preview_meta( array_values( $to_update ) );
150 - $this->clear_preview_labels_for_ids( array_merge(
151 - array_values( $to_create ),
152 - array_values( $to_update ),
153 - array_values( $to_delete )
154 - ) );
144 + $this->each_class_id_batch( array_values( $to_update ), function ( string $class_id ) {
145 + $post = Global_Class_Post::find_by_class_id( $class_id, false );
146 + if ( $post ) {
147 + delete_post_meta( $post->get_post_id(), Global_Class_Post::META_KEY_DATA_PREVIEW );
148 + clean_post_cache( $post->get_post_id() );
149 + }
150 + } );
155 151 }
156 152
157 153 $this->cache = null;
158 154 $this->flush_runtime_cache();
@@ -161,35 +157,11 @@
161 157 'added' => $to_create,
162 158 'deleted' => $to_delete,
163 159 'modified' => $to_update,
164 160 'order' => $order_changed,
165 - 'affected_post_ids' => $affected_post_ids,
166 161 ] );
167 -
168 - if ( ! empty( $to_delete ) && ! $is_preview ) {
169 - do_action(
170 - 'elementor/global_classes/cleanup',
171 - $to_delete,
172 - $affected_post_ids
173 - );
174 - }
175 162 }
176 163
177 - private function propagate_order_to_preview( array $published_order, array $deleted_ids ): void {
178 - $preview_order = Global_Classes_Order::make( $this->get_kit() )->set_preview( true );
179 - $existing_order = $preview_order->get_order();
180 - $unpublished_ids = array_flip( array_diff( $existing_order, $published_order, $deleted_ids ) );
181 - $merged_order = $published_order;
182 -
183 - foreach ( $existing_order as $position => $id ) {
184 - if ( isset( $unpublished_ids[ $id ] ) ) {
185 - array_splice( $merged_order, min( $position, count( $merged_order ) ), 0, [ $id ] );
186 - }
187 - }
188 -
189 - $preview_order->set_order( $merged_order );
190 - }
191 -
192 164 public function each_item( callable $cb, bool $skip_migration = false, int $batch_size = self::READ_BATCH_SIZE ): void {
193 165 $order = Global_Classes_Order::make( $this->get_kit() )->get_order();
194 166
195 167 if ( empty( $order ) ) {
@@ -203,69 +175,31 @@
203 175 }
204 176 }
205 177
206 178 public function put( array $items, array $order ) {
207 - $current_ids = Global_Classes_Order::make( $this->get_kit() )
208 - ->set_preview( $this->is_preview() )
209 - ->get_order();
179 + $current_ids = Global_Classes_Order::make( $this->get_kit() )->get_order();
210 180
211 181 $new_ids = array_keys( $items );
182 +
212 183 $current_order_string = implode( ';', $current_ids );
213 - $deleted_class_ids = array_values( array_diff( $current_ids, $new_ids ) );
214 184
215 185 $changes = [
216 186 'added' => array_values( array_diff( $new_ids, $current_ids ) ),
217 - 'deleted' => $deleted_class_ids,
187 + 'deleted' => array_values( array_diff( $current_ids, $new_ids ) ),
218 188 'modified' => array_values( array_intersect( $new_ids, $current_ids ) ),
219 189 'order' => implode( ';', $order ) !== $current_order_string,
220 190 ];
221 191
222 - /**
223 - * We collect all affected ids before the put_to_posts execution
224 - * as the update mechanism would handle the Global_Classes_Relations as it iterates over the update batches
225 - * So once we get to the cleanup phase - we would no longer have the relevant relations
226 - *
227 - * On top of that - by collecting all affected posts in advance, means we would iterate over each document's elements only once
228 - * (as the alternative would be to trigger the cleanup per removed class, but that means we may end up iterating over the same document N times, if all N styles are used in it)
229 - */
230 - $affected_post_ids = $this->get_posts_affected_by_deletion( $deleted_class_ids );
231 -
232 192 $this->put_to_posts( $items, $order, $current_ids );
233 193
234 194 $this->cache = null;
235 195
236 - $changes['affected_post_ids'] = $affected_post_ids;
237 -
238 196 do_action( 'elementor/global_classes/update', $this->get_context_key( 'event' ), $changes );
239 -
240 - if ( ! empty( $deleted_class_ids ) && ! $this->is_preview() ) {
241 - do_action(
242 - 'elementor/global_classes/cleanup',
243 - $deleted_class_ids,
244 - $affected_post_ids
245 - );
246 - }
247 197 }
248 198
249 - private function get_posts_affected_by_deletion( array $deleted_class_ids ): array {
250 - if ( empty( $deleted_class_ids ) ) {
251 - return [];
252 - }
253 -
254 - $relations = new Global_Classes_Relations();
255 - $post_ids = [];
256 -
257 - foreach ( $deleted_class_ids as $class_id ) {
258 - $post_ids[] = $relations->get_posts_by_style( $class_id );
259 - }
260 -
261 - return array_values( array_unique( array_merge( ...$post_ids ) ) );
262 - }
263 -
264 199 private function all_from_posts(): Global_Classes {
265 - $order = Global_Classes_Order::make( $this->get_kit() )
266 - ->set_preview( $this->is_preview() )
267 - ->get_order();
200 + $classes_order = Global_Classes_Order::make( $this->get_kit() );
201 + $order = $classes_order->get_order();
268 202
269 203 if ( empty( $order ) ) {
270 204 return Global_Classes::make( [], [] );
271 205 }
@@ -291,9 +225,9 @@
291 225 $to_update = array_intersect( $new_ids, $current_ids );
292 226
293 227 $this->persist_class_batch_mutations( $to_delete, $to_create, $to_update, $items, $is_preview );
294 228
295 - $classes_order = Global_Classes_Order::make( $this->get_kit() )->set_preview( $this->is_preview() );
229 + $classes_order = Global_Classes_Order::make( $this->get_kit() );
296 230 $classes_order->set_order( $order );
297 231
298 232 $label_map = [];
299 233 foreach ( $order as $id ) {
@@ -310,14 +244,15 @@
310 244 array_flip( $touched_ids )
311 245 );
312 246 Global_Classes_Sync_Map::make( $this->get_kit() )->apply_changes( $touched_items, array_values( $to_delete ) );
313 247
314 - $this->bulk_clear_preview_meta( array_values( $to_update ) );
315 - $this->clear_preview_labels_for_ids( array_merge(
316 - array_values( $to_create ),
317 - array_values( $to_update ),
318 - array_values( $to_delete )
319 - ) );
248 + $this->each_class_id_batch( array_values( $to_update ), function ( string $class_id ) {
249 + $post = Global_Class_Post::find_by_class_id( $class_id, false );
250 + if ( $post ) {
251 + delete_post_meta( $post->get_post_id(), Global_Class_Post::META_KEY_DATA_PREVIEW );
252 + clean_post_cache( $post->get_post_id() );
253 + }
254 + } );
320 255 }
321 256 }
322 257
323 258 private function iterate_class_posts_for_ids( array $class_ids ): \Generator {
@@ -334,13 +269,28 @@
334 269 ],
335 270 ],
336 271 ] );
337 272
273 + $seen_class_ids = [];
274 +
338 275 foreach ( $posts as $post ) {
276 + $class_id = get_post_meta( $post->ID, Global_Class_Post::META_KEY_ID, true );
277 +
278 + if ( $class_id && isset( $seen_class_ids[ $class_id ] ) ) {
279 + // if for some reason there's already a post meta to that class - delete any other ones
280 + // otherwise we may end up updating a stale post meta
281 + wp_delete_post( $post->ID, true );
282 + continue;
283 + }
284 +
285 + if ( $class_id ) {
286 + $seen_class_ids[ $class_id ] = true;
287 + }
288 +
339 289 yield Global_Class_Post::from_post( $post, $this->is_preview() );
340 290 clean_post_cache( $post->ID );
341 291 }
342 - unset( $posts );
292 + unset( $posts, $seen_class_ids );
343 293 $this->flush_runtime_cache();
344 294 }
345 295 }
346 296
@@ -351,28 +301,13 @@
351 301 array $items_by_id,
352 302 bool $is_preview
353 303 ): void {
354 304 $relations = new Global_Classes_Relations();
355 - $post_ids_map = Global_Classes_Post_IDs::make( $this->get_kit() );
356 305
357 - $ids_to_resolve = array_values( array_merge(
358 - array_values( $to_delete ),
359 - array_values( $to_update ),
360 - array_values( $to_create )
361 - ) );
362 - $post_ids = $post_ids_map->get_post_ids( $ids_to_resolve );
306 + $this->each_class_id_batch( array_values( $to_delete ), function ( string $class_id ) use ( $is_preview, $relations ) {
307 + $post = Global_Class_Post::find_by_class_id( $class_id, false );
363 308
364 - $this->each_class_id_batch(
365 - array_values( $to_delete ),
366 - function ( string $class_id ) use ( $is_preview, $relations, $post_ids ) {
367 - $post = isset( $post_ids[ $class_id ] )
368 - ? Global_Class_Post::from_post_id( $post_ids[ $class_id ], false )
369 - : null;
370 -
371 - if ( ! $post ) {
372 - return;
373 - }
374 -
309 + if ( $post ) {
375 310 if ( $is_preview ) {
376 311 $post->set_preview( true );
377 312 $post->update_data( [] );
378 313 clean_post_cache( $post->get_post_id() );
@@ -380,11 +315,11 @@
380 315 $relations->clear_class_relations( $class_id );
381 316 $post->delete();
382 317 }
383 318 }
384 - );
319 + } );
385 320
386 - $this->each_class_id_batch( $to_create, function ( string $class_id ) use ( $items_by_id, $is_preview, $post_ids, $post_ids_map ) {
321 + $this->each_class_id_batch( $to_create, function ( string $class_id ) use ( $items_by_id, $is_preview ) {
387 322 if ( ! isset( $items_by_id[ $class_id ] ) ) {
388 323 return;
389 324 }
390 325
@@ -389,56 +324,48 @@
389 324 }
390 325
391 326 $item = $items_by_id[ $class_id ];
392 327 $data = Global_Class_Data_Normalizer::normalize_style_fields( $item );
393 - $kit = $this->get_kit();
394 - $existing_post_id = $post_ids[ $class_id ] ?? null;
395 - $existing_post = $existing_post_id ? Global_Class_Post::from_post_id( $existing_post_id, $is_preview ) : null;
396 328
397 - if ( $existing_post ) {
398 - $existing_post->update_data( $data );
329 + if ( $is_preview ) {
330 + $post = Global_Class_Post::find_by_class_id( $class_id, true );
399 331
400 - if ( ! $is_preview ) {
401 - $existing_post->update_label( $item['label'] );
332 + if ( $post ) {
333 + $post->set_preview( true );
334 + $post->update_data( $data );
335 + $post->update_label( $item['label'] );
336 + clean_post_cache( $post->get_post_id() );
337 + } else {
338 + $created = Global_Class_Post::create( $class_id, $item['label'], $data );
339 + if ( $created ) {
340 + clean_post_cache( $created->get_post_id() );
341 + }
402 342 }
343 + } else {
344 + $created = Global_Class_Post::create( $class_id, $item['label'], $data );
345 + if ( $created ) {
346 + clean_post_cache( $created->get_post_id() );
347 + }
348 + }
349 + } );
403 350
404 - clean_post_cache( $existing_post->get_post_id() );
405 -
351 + $this->each_class_id_batch( $to_update, function ( string $class_id ) use ( $items_by_id, $is_preview ) {
352 + if ( ! isset( $items_by_id[ $class_id ] ) ) {
406 353 return;
407 354 }
408 355
409 - $created = Global_Class_Post::create( $class_id, $item['label'], $data, $kit );
356 + $item = $items_by_id[ $class_id ];
357 + $post = Global_Class_Post::find_by_class_id( $class_id, $is_preview );
410 358
411 - if ( $created ) {
412 - $post_ids_map->set( $class_id, $created->get_post_id() );
413 - clean_post_cache( $created->get_post_id() );
359 + if ( ! $post ) {
360 + return;
414 361 }
362 +
363 + $data = Global_Class_Data_Normalizer::normalize_style_fields( $item );
364 + $post->update_data( $data );
365 + $post->update_label( $item['label'] );
366 + clean_post_cache( $post->get_post_id() );
415 367 } );
416 -
417 - $this->each_class_id_batch(
418 - $to_update,
419 - function ( string $class_id ) use ( $items_by_id, $is_preview, $post_ids ) {
420 - if ( ! isset( $items_by_id[ $class_id ] ) || ! isset( $post_ids[ $class_id ] ) ) {
421 - return;
422 - }
423 -
424 - $item = $items_by_id[ $class_id ];
425 - $post = Global_Class_Post::from_post_id( $post_ids[ $class_id ], $is_preview );
426 -
427 - if ( ! $post ) {
428 - return;
429 - }
430 -
431 - $data = Global_Class_Data_Normalizer::normalize_style_fields( $item );
432 - $post->update_data( $data );
433 -
434 - if ( ! $is_preview ) {
435 - $post->update_label( $item['label'] );
436 - }
437 -
438 - clean_post_cache( $post->get_post_id() );
439 - }
440 - );
441 368 }
442 369
443 370 public function delete_all(): void {
444 371 $order = $this->get_order();
@@ -443,9 +370,9 @@
443 370 public function delete_all(): void {
444 371 $order = $this->get_order();
445 372
446 373 $this->each_class_id_batch( $order, function ( string $class_id ) {
447 - $post = Global_Class_Post::find_by_class_id( $class_id, false, $this->get_kit() );
374 + $post = Global_Class_Post::find_by_class_id( $class_id );
448 375
449 376 if ( $post ) {
450 377 $post->delete();
451 378 }
@@ -452,52 +379,8 @@
452 379 } );
453 380
454 381 Global_Classes_Order::make( $this->get_kit() )->set_order( [] );
455 382 $this->labels()->set_labels( [] );
456 - }
457 -
458 - private function clear_preview_labels_for_ids( array $class_ids ): void {
459 - if ( empty( $class_ids ) ) {
460 - return;
461 - }
462 -
463 - $preview_labels = Global_Classes_Labels::make( $this->get_kit() )->set_preview( true );
464 - $labels_map = $preview_labels->get_labels();
465 -
466 - if ( empty( $labels_map ) ) {
467 - return;
468 - }
469 -
470 - $ids_to_remove = array_intersect( array_unique( $class_ids ), array_keys( $labels_map ) );
471 -
472 - if ( empty( $ids_to_remove ) ) {
473 - return;
474 - }
475 -
476 - foreach ( $ids_to_remove as $id ) {
477 - unset( $labels_map[ $id ] );
478 - }
479 -
480 - $preview_labels->set_labels( $labels_map );
481 - }
482 -
483 - private function bulk_clear_preview_meta( array $class_ids ): void {
484 - if ( empty( $class_ids ) ) {
485 - return;
486 - }
487 -
488 - $post_ids_map = Global_Classes_Post_IDs::make( $this->get_kit() );
489 -
490 - foreach ( array_chunk( $class_ids, self::PERSIST_BATCH_SIZE ) as $chunk ) {
491 - $post_ids = $post_ids_map->get_post_ids( $chunk );
492 -
493 - foreach ( $post_ids as $post_id ) {
494 - delete_post_meta( $post_id, Global_Class_Post::META_KEY_DATA_PREVIEW );
495 - clean_post_cache( $post_id );
496 - }
497 -
498 - $this->flush_runtime_cache();
499 - }
500 383 }
501 384
502 385 private function each_class_id_batch( $class_ids, callable $callback, int $batch_size = self::PERSIST_BATCH_SIZE ): void {
503 386 $class_ids = is_array( $class_ids ) ? $class_ids : iterator_to_array( $class_ids, false );