PluginProbe
Elementor Website Builder – more than just a page builder / 3.30.2
Elementor Website Builder – more than just a page builder v3.30.2
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 / includes / template-library / sources / base.php

base.php in Elementor Website Builder – more than just a page builder 3.30.2, at includes/template-library/sources/base.php

544 lines 13.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\TemplateLibrary;
3
4 use Elementor\Controls_Stack;
5 use Elementor\Core\Settings\Page\Model;
6 use Elementor\Plugin;
7 use Elementor\Utils;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly.
11 }
12
13 /**
14 * Elementor template library source base.
15 *
16 * Elementor template library source base handler class is responsible for
17 * initializing all the methods controlling the source of Elementor templates.
18 *
19 * @since 1.0.0
20 * @abstract
21 */
22 abstract class Source_Base {
23
24 /**
25 * User meta.
26 *
27 * Holds the current user meta data.
28 *
29 * @access private
30 *
31 * @var array
32 */
33 private $user_meta;
34
35 /**
36 * Get template ID.
37 *
38 * Retrieve the template ID.
39 *
40 * @since 1.0.0
41 * @access public
42 * @abstract
43 */
44 abstract public function get_id();
45
46 /**
47 * Get template title.
48 *
49 * Retrieve the template title.
50 *
51 * @since 1.0.0
52 * @access public
53 * @abstract
54 */
55 abstract public function get_title();
56
57 /**
58 * Register template data.
59 *
60 * Used to register custom template data like a post type, a taxonomy or any
61 * other data.
62 *
63 * @since 1.0.0
64 * @access public
65 * @abstract
66 */
67 abstract public function register_data();
68
69 /**
70 * Get templates.
71 *
72 * Retrieve templates from the template library.
73 *
74 * @since 1.0.0
75 * @access public
76 * @abstract
77 *
78 * @param array $args Optional. Filter templates list based on a set of
79 * arguments. Default is an empty array.
80 */
81 abstract public function get_items( $args = [] );
82
83 /**
84 * Get template.
85 *
86 * Retrieve a single template from the template library.
87 *
88 * @since 1.0.0
89 * @access public
90 * @abstract
91 *
92 * @param int $template_id The template ID.
93 */
94 abstract public function get_item( $template_id );
95
96 /**
97 * Get template data.
98 *
99 * Retrieve a single template data from the template library.
100 *
101 * @since 1.5.0
102 * @access public
103 * @abstract
104 *
105 * @param array $args Custom template arguments.
106 */
107 abstract public function get_data( array $args );
108
109 /**
110 * Delete template.
111 *
112 * Delete template from the database.
113 *
114 * @since 1.0.0
115 * @access public
116 * @abstract
117 *
118 * @param int $template_id The template ID.
119 */
120 abstract public function delete_template( $template_id );
121
122 /**
123 * Save template.
124 *
125 * Save new or update existing template on the database.
126 *
127 * @since 1.0.0
128 * @access public
129 * @abstract
130 *
131 * @param array $template_data The template data.
132 */
133 abstract public function save_item( $template_data );
134
135 /**
136 * Update template.
137 *
138 * Update template on the database.
139 *
140 * @since 1.0.0
141 * @access public
142 * @abstract
143 *
144 * @param array $new_data New template data.
145 */
146 abstract public function update_item( $new_data );
147
148 /**
149 * Export template.
150 *
151 * Export template to a file.
152 *
153 * @since 1.0.0
154 * @access public
155 * @abstract
156 *
157 * @param int $template_id The template ID.
158 */
159 abstract public function export_template( $template_id );
160
161 /**
162 * Template library source base constructor.
163 *
164 * Initializing the template library source base by registering custom
165 * template data.
166 *
167 * @since 1.0.0
168 * @access public
169 */
170 public function __construct() {
171 $this->register_data();
172 }
173
174 /**
175 * Mark template as favorite.
176 *
177 * Update user meta containing his favorite templates. For a given template
178 * ID, add the template to the favorite templates or remove it from the
179 * favorites, based on the `favorite` parameter.
180 *
181 * @since 1.9.0
182 * @access public
183 *
184 * @param int $template_id The template ID.
185 * @param bool $favorite Optional. Whether the template is marked as
186 * favorite, or not. Default is true.
187 *
188 * @return int|bool User meta ID if the key didn't exist, true on successful
189 * update, false on failure.
190 */
191 public function mark_as_favorite( $template_id, $favorite = true ) {
192 $favorites_templates = $this->get_user_meta( 'favorites' );
193
194 if ( ! $favorites_templates ) {
195 $favorites_templates = [];
196 }
197
198 if ( $favorite ) {
199 $favorites_templates[ $template_id ] = $favorite;
200 } elseif ( isset( $favorites_templates[ $template_id ] ) ) {
201 unset( $favorites_templates[ $template_id ] );
202 }
203
204 return $this->update_user_meta( 'favorites', $favorites_templates );
205 }
206
207 /**
208 * Get current user meta.
209 *
210 * Retrieve Elementor meta data for the current user.
211 *
212 * @since 1.9.0
213 * @access public
214 *
215 * @param string $item Optional. User meta key. Default is null.
216 *
217 * @return null|array An array of user meta data, or null otherwise.
218 */
219 public function get_user_meta( $item = null ) {
220 if ( null === $this->user_meta ) {
221 $this->user_meta = get_user_meta( get_current_user_id(), $this->get_user_meta_prefix(), true );
222 }
223
224 if ( ! $this->user_meta ) {
225 $this->user_meta = [];
226 }
227
228 if ( $item ) {
229 if ( isset( $this->user_meta[ $item ] ) ) {
230 return $this->user_meta[ $item ];
231 }
232
233 return null;
234 }
235
236 return $this->user_meta;
237 }
238
239 /**
240 * Update current user meta.
241 *
242 * Update user meta data based on meta key an value.
243 *
244 * @since 1.9.0
245 * @access public
246 *
247 * @param string $key Optional. User meta key.
248 * @param mixed $value Optional. User meta value.
249 *
250 * @return int|bool User meta ID if the key didn't exist, true on successful
251 * update, false on failure.
252 */
253 public function update_user_meta( $key, $value ) {
254 $meta = $this->get_user_meta();
255
256 $meta[ $key ] = $value;
257
258 $this->user_meta = $meta;
259
260 return update_user_meta( get_current_user_id(), $this->get_user_meta_prefix(), $meta );
261 }
262
263 /**
264 * Replace elements IDs.
265 *
266 * For any given Elementor content/data, replace the IDs with new randomly
267 * generated IDs.
268 *
269 * @since 1.0.0
270 * @access protected
271 *
272 * @param array $content Any type of Elementor data.
273 *
274 * @return mixed Iterated data.
275 */
276 protected function replace_elements_ids( $content ) {
277 return Plugin::$instance->db->iterate_data( $content, function( $element ) {
278 $element['id'] = Utils::generate_random_string();
279
280 return apply_filters( 'elementor/document/element/replace_id', $element );
281 } );
282 }
283
284 /**
285 * Get Elementor library user meta prefix.
286 *
287 * Retrieve user meta prefix used to save Elementor data.
288 *
289 * @since 1.9.0
290 * @access protected
291 *
292 * @return string User meta prefix.
293 */
294 protected function get_user_meta_prefix() {
295 return 'elementor_library_' . $this->get_id();
296 }
297
298 /**
299 * Process content for export/import.
300 *
301 * Process the content and all the inner elements, and prepare all the
302 * elements data for export/import.
303 *
304 * @since 1.5.0
305 * @access protected
306 *
307 * @param array $content A set of elements.
308 * @param string $method Accepts either `on_export` to export data or
309 * `on_import` to import data.
310 *
311 * @return mixed Processed content data.
312 */
313 protected function process_export_import_content( $content, $method ) {
314 return Plugin::$instance->db->iterate_data(
315 $content, function( $element_data ) use ( $method ) {
316 $element = Plugin::$instance->elements_manager->create_element_instance( $element_data );
317
318 // If the widget/element isn't exist, like a plugin that creates a widget but deactivated
319 if ( ! $element ) {
320 return null;
321 }
322
323 return $this->process_element_export_import_content( $element, $method );
324 }
325 );
326 }
327
328 /**
329 * Process single element content for export/import.
330 *
331 * Process any given element and prepare the element data for export/import.
332 *
333 * @since 1.5.0
334 * @access protected
335 *
336 * @param Controls_Stack $element
337 * @param string $method
338 *
339 * @return array Processed element data.
340 */
341 protected function process_element_export_import_content( Controls_Stack $element, $method ) {
342 $element_data = $element->get_data();
343
344 if ( method_exists( $element, $method ) ) {
345 // TODO: Use the internal element data without parameters.
346 $element_data = $element->{$method}( $element_data );
347 }
348
349 foreach ( $element->get_controls() as $control ) {
350 $control_class = Plugin::$instance->controls_manager->get_control( $control['type'] );
351
352 // If the control isn't exist, like a plugin that creates the control but deactivated.
353 if ( ! $control_class ) {
354 return $element_data;
355 }
356
357 if ( method_exists( $control_class, $method ) ) {
358 $element_data['settings'][ $control['name'] ] = $control_class->{$method}( $element->get_settings( $control['name'] ), $control );
359 }
360
361 // On Export, check if the control has an argument 'export' => false.
362 if ( 'on_export' === $method && isset( $control['export'] ) && false === $control['export'] ) {
363 unset( $element_data['settings'][ $control['name'] ] );
364 }
365 }
366
367 return $element_data;
368 }
369
370 public function get_item_children( array $args = [] ) {
371 return [];
372 }
373
374 public function search_templates( array $args = [] ) {
375 return [];
376 }
377
378 public function save_folder( array $folder_data = [] ) {
379 return new \WP_Error( 'template_error', 'Folders cannot be created in this source' );
380 }
381
382 public function move_template_to_folder( array $folder_data = [] ) {
383 return new \WP_Error( 'template_error', 'Templates cannot be moved in this source' );
384 }
385
386 public function move_bulk_templates_to_folder( array $folder_data = [] ) {
387 return new \WP_Error( 'template_error', 'Templates cannot be moved in this source' );
388 }
389
390 public function save_bulk_items( array $args = [] ) {
391 return [];
392 }
393
394 public function get_bulk_items( array $args = [] ) {
395 return [];
396 }
397
398 /**
399 * @param int $template_id
400 * @return \Elementor\Core\Base\Document|\WP_Error
401 */
402 public function create_document_for_preview( int $template_id ) {
403 return new \WP_Error( 'template_error', 'Can not generate preview for this source' );
404 }
405
406 /**
407 * @param int $template_id
408 * @param mixed $data
409 * @return string|\WP_Error
410 * @throws \Exception
411 */
412 public function save_item_preview( int $template_id, $data ) {
413 return new \WP_Error( 'template_error', 'Cannot save previews for this source' );
414 }
415
416 /**
417 * @param int $template_id
418 * @param string $error
419 * @return string|\WP_Error
420 * @throws \Exception
421 */
422 public function mark_preview_as_failed( int $template_id, string $error ) {
423 return new \WP_Error( 'template_error', 'Cannot mark preview as failed for this source' );
424 }
425
426 /**
427 * @param int[] $template_ids
428 * @return bool|\WP_Error
429 */
430 public function bulk_delete_items( array $template_ids ) {
431 return new \WP_Error( 'template_error', 'Bulk delete action is not supported for this source' );
432 }
433
434 /**
435 * @param int[] $template_ids
436 * @return bool|\WP_Error
437 */
438 public function bulk_undo_delete_items( array $template_ids ) {
439 return new \WP_Error( 'template_error', 'Undo delete action is not supported for this source' );
440 }
441
442 /**
443 * @return array|\WP_Error
444 */
445 public function get_quota() {
446 return new \WP_Error( 'template_error', 'This source does not support quotas' );
447 }
448
449 /**
450 * @return array|\WP_Error
451 */
452 public function import_template( $name, $path ) {
453 return new \WP_Error( 'template_error', 'This source does not support import' );
454 }
455
456 public function supports_quota(): bool {
457 return false;
458 }
459
460 public function validate_quota( array $items ) {
461 return new \WP_Error( 'quota_error', 'This source does not support quota validation' );
462 }
463
464 public function prepare_import_template_data( $file_path ) {
465 $data = json_decode( Utils::file_get_contents( $file_path ), true );
466
467 if ( empty( $data ) ) {
468 return new \WP_Error( 'file_error', 'Invalid File' );
469 }
470
471 $content = $data['content'];
472
473 if ( ! is_array( $content ) ) {
474 return new \WP_Error( 'file_error', 'Invalid Content In File' );
475 }
476
477 $content = $this->process_export_import_content( $content, 'on_import' );
478
479 $content = apply_filters(
480 "elementor/template_library/sources/{$this->get_id()}/import/elements",
481 $content
482 );
483
484 $page_settings = [];
485
486 if ( ! empty( $data['page_settings'] ) ) {
487 $page = new Model( [
488 'id' => 0,
489 'settings' => $data['page_settings'],
490 ] );
491
492 $page_settings_data = $this->process_element_export_import_content( $page, 'on_import' );
493
494 if ( ! empty( $page_settings_data['settings'] ) ) {
495 $page_settings = $page_settings_data['settings'];
496 }
497 }
498
499 return [
500 'content' => $content,
501 'page_settings' => $page_settings,
502 'title' => $data['title'],
503 'type' => $data['type'],
504 ];
505 }
506
507 /**
508 * Send file headers.
509 *
510 * Set the file header when export template data to a file.
511 *
512 * @since 1.6.0
513 * @access protected
514 *
515 * @param string $file_name File name.
516 * @param int $file_size File size.
517 */
518 protected function send_file_headers( $file_name, $file_size ) {
519 header( 'Content-Type: application/octet-stream' );
520 header( 'Content-Disposition: attachment; filename=' . $file_name );
521 header( 'Expires: 0' );
522 header( 'Cache-Control: must-revalidate' );
523 header( 'Pragma: public' );
524 header( 'Content-Length: ' . $file_size );
525 }
526
527 protected function filesize( $path ) {
528 return filesize( $path );
529 }
530
531 protected function serve_zip( $zip_complete_path ): void {
532 @ob_end_flush();
533 @readfile( $zip_complete_path );
534 }
535
536 protected function serve_file( string $file_content ): void {
537 @ob_end_clean();
538 flush();
539
540 // PHPCS - Export widget json
541 echo $file_content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
542 }
543 }
544