Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/elementor/includes/db.php
Keine Baseline-Datei – Diff nur gegen leer.
1
-
1
+
<?php
2
+
namespace Elementor;
3
+
4
+
use Elementor\Core\Base\Document;
5
+
use Elementor\Core\DynamicTags\Manager;
6
+
use Elementor\TemplateLibrary\Source_Local;
7
+
8
+
if ( ! defined( 'ABSPATH' ) ) {
9
+
exit; // Exit if accessed directly.
10
+
}
11
+
12
+
/**
13
+
* Elementor database.
14
+
*
15
+
* Elementor database handler class is responsible for communicating with the
16
+
* DB, save and retrieve Elementor data and meta data.
17
+
*
18
+
* @since 1.0.0
19
+
*/
20
+
class DB {
21
+
22
+
/**
23
+
* Current DB version of the editor.
24
+
*/
25
+
const DB_VERSION = '0.4';
26
+
27
+
/**
28
+
* Post publish status.
29
+
*
30
+
* @deprecated 3.1.0 Use `Document::STATUS_PUBLISH` const instead.
31
+
*/
32
+
const STATUS_PUBLISH = Document::STATUS_PUBLISH;
33
+
34
+
/**
35
+
* Post draft status.
36
+
*
37
+
* @deprecated 3.1.0 Use `Document::STATUS_DRAFT` const instead.
38
+
*/
39
+
const STATUS_DRAFT = Document::STATUS_DRAFT;
40
+
41
+
/**
42
+
* Post private status.
43
+
*
44
+
* @deprecated 3.1.0 Use `Document::STATUS_PRIVATE` const instead.
45
+
*/
46
+
const STATUS_PRIVATE = Document::STATUS_PRIVATE;
47
+
48
+
/**
49
+
* Post autosave status.
50
+
*
51
+
* @deprecated 3.1.0 Use `Document::STATUS_AUTOSAVE` const instead.
52
+
*/
53
+
const STATUS_AUTOSAVE = Document::STATUS_AUTOSAVE;
54
+
55
+
/**
56
+
* Post pending status.
57
+
*
58
+
* @deprecated 3.1.0 Use `Document::STATUS_PENDING` const instead.
59
+
*/
60
+
const STATUS_PENDING = Document::STATUS_PENDING;
61
+
62
+
/**
63
+
* Switched post data.
64
+
*
65
+
* Holds the switched post data.
66
+
*
67
+
* @since 1.5.0
68
+
* @access protected
69
+
*
70
+
* @var array Switched post data. Default is an empty array.
71
+
*/
72
+
protected $switched_post_data = [];
73
+
74
+
/**
75
+
* Switched data.
76
+
*
77
+
* Holds the switched data.
78
+
*
79
+
* @since 2.0.0
80
+
* @access protected
81
+
*
82
+
* @var array Switched data. Default is an empty array.
83
+
*/
84
+
protected $switched_data = [];
85
+
86
+
/**
87
+
* Get builder.
88
+
*
89
+
* Retrieve editor data from the database.
90
+
*
91
+
* @since 1.0.0
92
+
* @deprecated 3.1.0 Use `Plugin::$instance->documents->get( $post_id )->get_elements_raw_data( null, true )` OR `Plugin::$instance->documents->get_doc_or_auto_save( $post_id )->get_elements_raw_data( null, true )` instead.
93
+
* @access public
94
+
*
95
+
* @param int $post_id Post ID.
96
+
* @param string $status Optional. Post status. Default is `publish`.
97
+
*
98
+
* @return array Editor data.
99
+
*/
100
+
public function get_builder( $post_id, $status = Document::STATUS_PUBLISH ) {
101
+
Plugin::$instance->modules_manager
102
+
->get_modules( 'dev-tools' )
103
+
->deprecation
104
+
->deprecated_function(
105
+
__METHOD__,
106
+
'3.1.0',
107
+
'`Plugin::$instance->documents->get( $post_id )->get_elements_raw_data( null, true )` OR `Plugin::$instance->documents->get_doc_or_auto_save( $post_id )->get_elements_raw_data( null, true )`'
108
+
);
109
+
110
+
if ( Document::STATUS_DRAFT === $status ) {
111
+
$document = Plugin::$instance->documents->get_doc_or_auto_save( $post_id );
112
+
} else {
113
+
$document = Plugin::$instance->documents->get( $post_id );
114
+
}
115
+
116
+
if ( $document ) {
117
+
$editor_data = $document->get_elements_raw_data( null, true );
118
+
} else {
119
+
$editor_data = [];
120
+
}
121
+
122
+
return $editor_data;
123
+
}
124
+
125
+
/**
126
+
* Get JSON meta.
127
+
*
128
+
* Retrieve post meta data, and return the JSON decoded data.
129
+
*
130
+
* @since 1.0.0
131
+
* @access protected
132
+
*
133
+
* @param int $post_id Post ID.
134
+
* @param string $key The meta key to retrieve.
135
+
*
136
+
* @return array Decoded JSON data from post meta.
137
+
*/
138
+
protected function _get_json_meta( $post_id, $key ) {
139
+
Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( __METHOD__, '3.1.0' );
140
+
141
+
$meta = get_post_meta( $post_id, $key, true );
142
+
143
+
if ( is_string( $meta ) && ! empty( $meta ) ) {
144
+
$meta = json_decode( $meta, true );
145
+
}
146
+
147
+
if ( empty( $meta ) ) {
148
+
$meta = [];
149
+
}
150
+
151
+
return $meta;
152
+
}
153
+
154
+
/**
155
+
* Is using Elementor.
156
+
*
157
+
* Set whether the page is using Elementor or not.
158
+
*
159
+
* @since 1.5.0
160
+
* @deprecated 3.1.0 Use `Plugin::$instance->documents->get( $post_id )->set_is_build_with_elementor( $is_elementor )` instead.
161
+
* @access public
162
+
*
163
+
* @param int $post_id Post ID.
164
+
* @param bool $is_elementor Optional. Whether the page is elementor page.
165
+
* Default is true.
166
+
*/
167
+
public function set_is_elementor_page( $post_id, $is_elementor = true ) {
168
+
Plugin::$instance->modules_manager
169
+
->get_modules( 'dev-tools' )
170
+
->deprecation
171
+
->deprecated_function(
172
+
__METHOD__,
173
+
'3.1.0',
174
+
'Plugin::$instance->documents->get( $post_id )->set_is_build_with_elementor( $is_elementor )'
175
+
);
176
+
177
+
$document = Plugin::$instance->documents->get( $post_id );
178
+
179
+
if ( ! $document ) {
180
+
return;
181
+
}
182
+
183
+
$document->set_is_built_with_elementor( $is_elementor );
184
+
}
185
+
186
+
/**
187
+
* Render element plain content.
188
+
*
189
+
* When saving data in the editor, this method renders recursively the plain
190
+
* content containing only the content and the HTML. No CSS data.
191
+
*
192
+
* @since 2.0.0
193
+
* @access private
194
+
*
195
+
* @param array $element_data Element data.
196
+
*/
197
+
private function render_element_plain_content( $element_data ) {
198
+
if ( 'widget' === $element_data['elType'] ) {
199
+
/** @var Widget_Base $widget */
200
+
$widget = Plugin::$instance->elements_manager->create_element_instance( $element_data );
201
+
202
+
if ( $widget ) {
203
+
$widget->render_plain_content();
204
+
}
205
+
}
206
+
207
+
if ( ! empty( $element_data['elements'] ) ) {
208
+
foreach ( $element_data['elements'] as $element ) {
209
+
$this->render_element_plain_content( $element );
210
+
}
211
+
}
212
+
}
213
+
214
+
/**
215
+
* Save plain text.
216
+
*
217
+
* Retrieves the raw content, removes all kind of unwanted HTML tags and saves
218
+
* the content as the `post_content` field in the database.
219
+
*
220
+
* @since 1.9.0
221
+
* @access public
222
+
*
223
+
* @param int $post_id Post ID.
224
+
*/
225
+
public function save_plain_text( $post_id ) {
226
+
// Switch $dynamic_tags to parsing mode = remove.
227
+
$dynamic_tags = Plugin::$instance->dynamic_tags;
228
+
$parsing_mode = $dynamic_tags->get_parsing_mode();
229
+
$dynamic_tags->set_parsing_mode( Manager::MODE_REMOVE );
230
+
231
+
$plain_text = $this->get_plain_text( $post_id );
232
+
233
+
wp_update_post(
234
+
[
235
+
'ID' => $post_id,
236
+
'post_content' => $plain_text,
237
+
]
238
+
);
239
+
240
+
// Restore parsing mode.
241
+
$dynamic_tags->set_parsing_mode( $parsing_mode );
242
+
}
243
+
244
+
/**
245
+
* Iterate data.
246
+
*
247
+
* Accept any type of Elementor data and a callback function. The callback
248
+
* function runs recursively for each element and his child elements.
249
+
*
250
+
* @since 1.0.0
251
+
* @access public
252
+
*
253
+
* @param array $data_container Any type of elementor data.
254
+
* @param callable $callback A function to iterate data by.
255
+
* @param array $args Array of args pointers for passing parameters in & out of the callback.
256
+
*
257
+
* @return mixed Iterated data.
258
+
*/
259
+
public function iterate_data( $data_container, $callback, $args = [] ) {
260
+
if ( isset( $data_container['elType'] ) ) {
261
+
if ( ! empty( $data_container['elements'] ) ) {
262
+
$data_container['elements'] = $this->iterate_data( $data_container['elements'], $callback, $args );
263
+
}
264
+
265
+
return call_user_func( $callback, $data_container, $args );
266
+
}
267
+
268
+
foreach ( $data_container as $element_key => $element_value ) {
269
+
$element_data = $this->iterate_data( $data_container[ $element_key ], $callback, $args );
270
+
271
+
if ( null === $element_data ) {
272
+
continue;
273
+
}
274
+
275
+
$data_container[ $element_key ] = $element_data;
276
+
}
277
+
278
+
return $data_container;
279
+
}
280
+
281
+
public static function iterate_elementor_documents( $callback, $batch_size = 100 ) {
282
+
$processed_posts = 0;
283
+
284
+
while ( true ) {
285
+
$args = wp_parse_args( [
286
+
'post_type' => [ Source_Local::CPT, 'post', 'page' ],
287
+
'post_status' => [ 'publish' ],
288
+
'posts_per_page' => $batch_size,
289
+
'meta_key' => Document::BUILT_WITH_ELEMENTOR_META_KEY,
290
+
'meta_value' => 'builder',
291
+
'offset' => $processed_posts,
292
+
'fields' => 'ids',
293
+
] );
294
+
295
+
$query = new \WP_Query( $args );
296
+
297
+
if ( empty( $query->posts ) ) {
298
+
break;
299
+
}
300
+
301
+
foreach ( $query->posts as $post_id ) {
302
+
$document = Plugin::$instance->documents->get( $post_id );
303
+
$elements_data = $document->get_json_meta( Document::ELEMENTOR_DATA_META_KEY );
304
+
305
+
$callback( $document, $elements_data );
306
+
307
+
$processed_posts++;
308
+
}
309
+
}
310
+
}
311
+
312
+
/**
313
+
* Safely copy Elementor meta.
314
+
*
315
+
* Make sure the original page was built with Elementor and the post is not
316
+
* auto-save. Only then copy elementor meta from one post to another using
317
+
* `copy_elementor_meta()`.
318
+
*
319
+
* @since 1.9.2
320
+
* @access public
321
+
*
322
+
* @param int $from_post_id Original post ID.
323
+
* @param int $to_post_id Target post ID.
324
+
*/
325
+
public function safe_copy_elementor_meta( $from_post_id, $to_post_id ) {
326
+
// It's from WP-Admin & not from Elementor.
327
+
if ( ! did_action( 'elementor/db/before_save' ) ) {
328
+
$from_document = Plugin::$instance->documents->get( $from_post_id );
329
+
330
+
if ( ! $from_document || ! $from_document->is_built_with_elementor() ) {
331
+
return;
332
+
}
333
+
334
+
// It's an exited Elementor auto-save.
335
+
if ( get_post_meta( $to_post_id, '_elementor_data', true ) ) {
336
+
return;
337
+
}
338
+
}
339
+
340
+
$this->copy_elementor_meta( $from_post_id, $to_post_id );
341
+
}
342
+
343
+
/**
344
+
* Copy Elementor meta.
345
+
*
346
+
* Duplicate the data from one post to another.
347
+
*
348
+
* Consider using `safe_copy_elementor_meta()` method instead.
349
+
*
350
+
* @since 1.1.0
351
+
* @access public
352
+
*
353
+
* @param int $from_post_id Original post ID.
354
+
* @param int $to_post_id Target post ID.
355
+
*/
356
+
public function copy_elementor_meta( $from_post_id, $to_post_id ) {
357
+
$from_post_meta = get_post_meta( $from_post_id );
358
+
$core_meta = [
359
+
'_wp_page_template',
360
+
'_thumbnail_id',
361
+
];
362
+
363
+
foreach ( $from_post_meta as $meta_key => $values ) {
364
+
// Copy only meta with the `_elementor` prefix.
365
+
if ( 0 === strpos( $meta_key, '_elementor' ) || in_array( $meta_key, $core_meta, true ) ) {
366
+
$value = $values[0];
367
+
368
+
// The elementor JSON needs slashes before saving.
369
+
if ( '_elementor_data' === $meta_key ) {
370
+
$value = wp_slash( $value );
371
+
} else {
372
+
$value = maybe_unserialize( $value );
373
+
}
374
+
375
+
// Don't use `update_post_meta` that can't handle `revision` post type.
376
+
update_metadata( 'post', $to_post_id, $meta_key, $value );
377
+
}
378
+
}
379
+
}
380
+
381
+
/**
382
+
* Is built with Elementor.
383
+
*
384
+
* Check whether the post was built with Elementor.
385
+
*
386
+
* @since 1.0.10
387
+
* @deprecated 3.2.0 Use `Plugin::$instance->documents->get( $post_id )->is_built_with_elementor()` instead.
388
+
* @access public
389
+
*
390
+
* @param int $post_id Post ID.
391
+
*
392
+
* @return bool Whether the post was built with Elementor.
393
+
*/
394
+
public function is_built_with_elementor( $post_id ) {
395
+
Plugin::$instance->modules_manager
396
+
->get_modules( 'dev-tools' )
397
+
->deprecation
398
+
->deprecated_function(
399
+
__METHOD__,
400
+
'3.2.0',
401
+
'Plugin::$instance->documents->get( $post_id )->is_built_with_elementor()'
402
+
);
403
+
404
+
$document = Plugin::$instance->documents->get( $post_id );
405
+
406
+
if ( ! $document ) {
407
+
return false;
408
+
}
409
+
410
+
return $document->is_built_with_elementor();
411
+
}
412
+
413
+
/**
414
+
* Switch to post.
415
+
*
416
+
* Change the global WordPress post to the requested post.
417
+
*
418
+
* @since 1.5.0
419
+
* @access public
420
+
*
421
+
* @param int $post_id Post ID to switch to.
422
+
*/
423
+
public function switch_to_post( $post_id ) {
424
+
$post_id = absint( $post_id );
425
+
// If is already switched, or is the same post, return.
426
+
if ( get_the_ID() === $post_id ) {
427
+
$this->switched_post_data[] = false;
428
+
return;
429
+
}
430
+
431
+
$this->switched_post_data[] = [
432
+
'switched_id' => $post_id,
433
+
'original_id' => get_the_ID(), // Note, it can be false if the global isn't set.
434
+
];
435
+
436
+
$GLOBALS['post'] = get_post( $post_id ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
437
+
438
+
setup_postdata( $GLOBALS['post'] );
439
+
}
440
+
441
+
/**
442
+
* Restore current post.
443
+
*
444
+
* Rollback to the previous global post, rolling back from `DB::switch_to_post()`.
445
+
*
446
+
* @since 1.5.0
447
+
* @access public
448
+
*/
449
+
public function restore_current_post() {
450
+
$data = array_pop( $this->switched_post_data );
451
+
452
+
// If not switched, return.
453
+
if ( ! $data ) {
454
+
return;
455
+
}
456
+
457
+
// It was switched from an empty global post, restore this state and unset the global post.
458
+
if ( false === $data['original_id'] ) {
459
+
unset( $GLOBALS['post'] );
460
+
return;
461
+
}
462
+
463
+
$GLOBALS['post'] = get_post( $data['original_id'] ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
464
+
465
+
setup_postdata( $GLOBALS['post'] );
466
+
}
467
+
468
+
469
+
/**
470
+
* Switch to query.
471
+
*
472
+
* Change the WordPress query to a new query with the requested
473
+
* query variables.
474
+
*
475
+
* @since 2.0.0
476
+
* @access public
477
+
*
478
+
* @param array $query_vars New query variables.
479
+
* @param bool $force_global_post
480
+
*/
481
+
public function switch_to_query( $query_vars, $force_global_post = false ) {
482
+
global $wp_query;
483
+
$current_query_vars = $wp_query->query;
484
+
485
+
// If is already switched, or is the same query, return.
486
+
if ( $current_query_vars === $query_vars ) {
487
+
$this->switched_data[] = false;
488
+
return;
489
+
}
490
+
491
+
$new_query = new \WP_Query( $query_vars );
492
+
493
+
$switched_data = [
494
+
'switched' => $new_query,
495
+
'original' => $wp_query,
496
+
];
497
+
498
+
if ( ! empty( $GLOBALS['post'] ) ) {
499
+
$switched_data['post'] = $GLOBALS['post'];
500
+
}
501
+
502
+
$this->switched_data[] = $switched_data;
503
+
504
+
$wp_query = $new_query; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
505
+
506
+
// Ensure the global post is set only if needed.
507
+
unset( $GLOBALS['post'] );
508
+
509
+
if ( isset( $new_query->posts[0] ) ) {
510
+
if ( $force_global_post || $new_query->is_singular() ) {
511
+
$GLOBALS['post'] = $new_query->posts[0]; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
512
+
setup_postdata( $GLOBALS['post'] );
513
+
}
514
+
}
515
+
516
+
if ( $new_query->is_author() ) {
517
+
$GLOBALS['authordata'] = get_userdata( $new_query->get( 'author' ) ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
518
+
}
519
+
}
520
+
521
+
/**
522
+
* Restore current query.
523
+
*
524
+
* Rollback to the previous query, rolling back from `DB::switch_to_query()`.
525
+
*
526
+
* @since 2.0.0
527
+
* @access public
528
+
*/
529
+
public function restore_current_query() {
530
+
$data = array_pop( $this->switched_data );
531
+
532
+
// If not switched, return.
533
+
if ( ! $data ) {
534
+
return;
535
+
}
536
+
537
+
global $wp_query;
538
+
539
+
$wp_query = $data['original']; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
540
+
541
+
// Ensure the global post/authordata is set only if needed.
542
+
unset( $GLOBALS['post'] );
543
+
unset( $GLOBALS['authordata'] );
544
+
545
+
if ( ! empty( $data['post'] ) ) {
546
+
$GLOBALS['post'] = $data['post']; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
547
+
setup_postdata( $GLOBALS['post'] );
548
+
}
549
+
550
+
if ( $wp_query->is_author() ) {
551
+
$GLOBALS['authordata'] = get_userdata( $wp_query->get( 'author' ) ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
552
+
}
553
+
}
554
+
555
+
/**
556
+
* Get plain text.
557
+
*
558
+
* Retrieve the post plain text.
559
+
*
560
+
* @since 1.9.0
561
+
* @access public
562
+
*
563
+
* @param int $post_id Post ID.
564
+
*
565
+
* @return string Post plain text.
566
+
*/
567
+
public function get_plain_text( $post_id ) {
568
+
$document = Plugin::$instance->documents->get( $post_id );
569
+
$data = $document ? $document->get_elements_data() : [];
570
+
571
+
return $this->get_plain_text_from_data( $data );
572
+
}
573
+
574
+
/**
575
+
* Get plain text from data.
576
+
*
577
+
* Retrieve the post plain text from any given Elementor data.
578
+
*
579
+
* @since 1.9.2
580
+
* @access public
581
+
*
582
+
* @param array $data Post ID.
583
+
*
584
+
* @return string Post plain text.
585
+
*/
586
+
public function get_plain_text_from_data( $data ) {
587
+
ob_start();
588
+
if ( $data ) {
589
+
foreach ( $data as $element_data ) {
590
+
$this->render_element_plain_content( $element_data );
591
+
}
592
+
}
593
+
594
+
$plain_text = ob_get_clean();
595
+
596
+
// Remove unnecessary tags.
597
+
$plain_text = preg_replace( '/<\/?div[^>]*\>/i', '', $plain_text );
598
+
$plain_text = preg_replace( '/<\/?span[^>]*\>/i', '', $plain_text );
599
+
$plain_text = preg_replace( '#<script(.*?)>(.*?)</script>#is', '', $plain_text );
600
+
$plain_text = preg_replace( '/<i [^>]*><\\/i[^>]*>/', '', $plain_text );
601
+
$plain_text = preg_replace( '/ class=".*?"/', '', $plain_text );
602
+
603
+
// Remove empty lines.
604
+
$plain_text = preg_replace( '/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/', "\n", $plain_text );
605
+
606
+
$plain_text = trim( $plain_text );
607
+
608
+
return $plain_text;
609
+
}
610
+
}
611
+