balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

manager.php (15317B)


      1 <?php
      2 namespace Elementor\TemplateLibrary;
      3 
      4 use Elementor\Api;
      5 use Elementor\Core\Common\Modules\Ajax\Module as Ajax;
      6 use Elementor\Core\Settings\Manager as SettingsManager;
      7 use Elementor\TemplateLibrary\Classes\Import_Images;
      8 use Elementor\Plugin;
      9 use Elementor\User;
     10 
     11 if ( ! defined( 'ABSPATH' ) ) {
     12 	exit; // Exit if accessed directly.
     13 }
     14 
     15 /**
     16  * Elementor template library manager.
     17  *
     18  * Elementor template library manager handler class is responsible for
     19  * initializing the template library.
     20  *
     21  * @since 1.0.0
     22  */
     23 class Manager {
     24 
     25 	/**
     26 	 * Registered template sources.
     27 	 *
     28 	 * Holds a list of all the supported sources with their instances.
     29 	 *
     30 	 * @access protected
     31 	 *
     32 	 * @var Source_Base[]
     33 	 */
     34 	protected $_registered_sources = [];
     35 
     36 	/**
     37 	 * Imported template images.
     38 	 *
     39 	 * Holds an instance of `Import_Images` class.
     40 	 *
     41 	 * @access private
     42 	 *
     43 	 * @var Import_Images
     44 	 */
     45 	private $_import_images = null;
     46 
     47 	/**
     48 	 * Template library manager constructor.
     49 	 *
     50 	 * Initializing the template library manager by registering default template
     51 	 * sources and initializing ajax calls.
     52 	 *
     53 	 * @since 1.0.0
     54 	 * @access public
     55 	 */
     56 	public function __construct() {
     57 		$this->register_default_sources();
     58 
     59 		$this->add_actions();
     60 	}
     61 
     62 	/**
     63 	 * @since 2.3.0
     64 	 * @access public
     65 	 */
     66 	public function add_actions() {
     67 		add_action( 'elementor/ajax/register_actions', [ $this, 'register_ajax_actions' ] );
     68 		add_action( 'wp_ajax_elementor_library_direct_actions', [ $this, 'handle_direct_actions' ] );
     69 	}
     70 
     71 	/**
     72 	 * Get `Import_Images` instance.
     73 	 *
     74 	 * Retrieve the instance of the `Import_Images` class.
     75 	 *
     76 	 * @since 1.0.0
     77 	 * @access public
     78 	 *
     79 	 * @return Import_Images Imported images instance.
     80 	 */
     81 	public function get_import_images_instance() {
     82 		if ( null === $this->_import_images ) {
     83 			$this->_import_images = new Import_Images();
     84 		}
     85 
     86 		return $this->_import_images;
     87 	}
     88 
     89 	/**
     90 	 * Register template source.
     91 	 *
     92 	 * Used to register new template sources displayed in the template library.
     93 	 *
     94 	 * @since 1.0.0
     95 	 * @access public
     96 	 *
     97 	 * @param string $source_class The name of source class.
     98 	 * @param array  $args         Optional. Class arguments. Default is an
     99 	 *                             empty array.
    100 	 *
    101 	 * @return \WP_Error|true True if the source was registered, `WP_Error`
    102 	 *                        otherwise.
    103 	 */
    104 	public function register_source( $source_class, $args = [] ) {
    105 		if ( ! class_exists( $source_class ) ) {
    106 			return new \WP_Error( 'source_class_name_not_exists' );
    107 		}
    108 
    109 		$source_instance = new $source_class( $args );
    110 
    111 		if ( ! $source_instance instanceof Source_Base ) {
    112 			return new \WP_Error( 'wrong_instance_source' );
    113 		}
    114 
    115 		$source_id = $source_instance->get_id();
    116 
    117 		if ( isset( $this->_registered_sources[ $source_id ] ) ) {
    118 			return new \WP_Error( 'source_exists' );
    119 		}
    120 
    121 		$this->_registered_sources[ $source_id ] = $source_instance;
    122 
    123 		return true;
    124 	}
    125 
    126 	/**
    127 	 * Unregister template source.
    128 	 *
    129 	 * Remove an existing template sources from the list of registered template
    130 	 * sources.
    131 	 *
    132 	 * @deprecated 2.7.0
    133 	 *
    134 	 * @since 1.0.0
    135 	 * @access public
    136 	 *
    137 	 * @param string $id The source ID.
    138 	 *
    139 	 * @return bool Whether the source was unregistered.
    140 	 */
    141 	public function unregister_source( $id ) {
    142 		return true;
    143 	}
    144 
    145 	/**
    146 	 * Get registered template sources.
    147 	 *
    148 	 * Retrieve registered template sources.
    149 	 *
    150 	 * @since 1.0.0
    151 	 * @access public
    152 	 *
    153 	 * @return Source_Base[] Registered template sources.
    154 	 */
    155 	public function get_registered_sources() {
    156 		return $this->_registered_sources;
    157 	}
    158 
    159 	/**
    160 	 * Get template source.
    161 	 *
    162 	 * Retrieve single template sources for a given template ID.
    163 	 *
    164 	 * @since 1.0.0
    165 	 * @access public
    166 	 *
    167 	 * @param string $id The source ID.
    168 	 *
    169 	 * @return false|Source_Base Template sources if one exist, False otherwise.
    170 	 */
    171 	public function get_source( $id ) {
    172 		$sources = $this->get_registered_sources();
    173 
    174 		if ( ! isset( $sources[ $id ] ) ) {
    175 			return false;
    176 		}
    177 
    178 		return $sources[ $id ];
    179 	}
    180 
    181 	/**
    182 	 * Get templates.
    183 	 *
    184 	 * Retrieve all the templates from all the registered sources.
    185 	 *
    186 	 * @since 1.0.0
    187 	 * @access public
    188 	 *
    189 	 * @return array Templates array.
    190 	 */
    191 	public function get_templates() {
    192 		$templates = [];
    193 
    194 		foreach ( $this->get_registered_sources() as $source ) {
    195 			$templates = array_merge( $templates, $source->get_items() );
    196 		}
    197 
    198 		return $templates;
    199 	}
    200 
    201 	/**
    202 	 * Get library data.
    203 	 *
    204 	 * Retrieve the library data.
    205 	 *
    206 	 * @since 1.9.0
    207 	 * @access public
    208 	 *
    209 	 * @param array $args Library arguments.
    210 	 *
    211 	 * @return array Library data.
    212 	 */
    213 	public function get_library_data( array $args ) {
    214 		$library_data = Api::get_library_data( ! empty( $args['sync'] ) );
    215 
    216 		// Ensure all document are registered.
    217 		Plugin::$instance->documents->get_document_types();
    218 
    219 		return [
    220 			'templates' => $this->get_templates(),
    221 			'config' => $library_data['types_data'],
    222 		];
    223 	}
    224 
    225 	/**
    226 	 * Save template.
    227 	 *
    228 	 * Save new or update existing template on the database.
    229 	 *
    230 	 * @since 1.0.0
    231 	 * @access public
    232 	 *
    233 	 * @param array $args Template arguments.
    234 	 *
    235 	 * @return \WP_Error|int The ID of the saved/updated template.
    236 	 */
    237 	public function save_template( array $args ) {
    238 		$validate_args = $this->ensure_args( [ 'post_id', 'source', 'content', 'type' ], $args );
    239 
    240 		if ( is_wp_error( $validate_args ) ) {
    241 			return $validate_args;
    242 		}
    243 
    244 		$source = $this->get_source( $args['source'] );
    245 
    246 		if ( ! $source ) {
    247 			return new \WP_Error( 'template_error', 'Template source not found.' );
    248 		}
    249 
    250 		$args['content'] = json_decode( $args['content'], true );
    251 
    252 		$page = SettingsManager::get_settings_managers( 'page' )->get_model( $args['post_id'] );
    253 
    254 		$args['page_settings'] = $page->get_data( 'settings' );
    255 
    256 		$template_id = $source->save_item( $args );
    257 
    258 		if ( is_wp_error( $template_id ) ) {
    259 			return $template_id;
    260 		}
    261 
    262 		return $source->get_item( $template_id );
    263 	}
    264 
    265 	/**
    266 	 * Update template.
    267 	 *
    268 	 * Update template on the database.
    269 	 *
    270 	 * @since 1.0.0
    271 	 * @access public
    272 	 *
    273 	 * @param array $template_data New template data.
    274 	 *
    275 	 * @return \WP_Error|Source_Base Template sources instance if the templates
    276 	 *                               was updated, `WP_Error` otherwise.
    277 	 */
    278 	public function update_template( array $template_data ) {
    279 		$validate_args = $this->ensure_args( [ 'source', 'content', 'type' ], $template_data );
    280 
    281 		if ( is_wp_error( $validate_args ) ) {
    282 			return $validate_args;
    283 		}
    284 
    285 		$source = $this->get_source( $template_data['source'] );
    286 
    287 		if ( ! $source ) {
    288 			return new \WP_Error( 'template_error', 'Template source not found.' );
    289 		}
    290 
    291 		$template_data['content'] = json_decode( $template_data['content'], true );
    292 
    293 		$update = $source->update_item( $template_data );
    294 
    295 		if ( is_wp_error( $update ) ) {
    296 			return $update;
    297 		}
    298 
    299 		return $source->get_item( $template_data['id'] );
    300 	}
    301 
    302 	/**
    303 	 * Update templates.
    304 	 *
    305 	 * Update template on the database.
    306 	 *
    307 	 * @since 1.0.0
    308 	 * @access public
    309 	 *
    310 	 * @param array $args Template arguments.
    311 	 *
    312 	 * @return \WP_Error|true True if templates updated, `WP_Error` otherwise.
    313 	 */
    314 	public function update_templates( array $args ) {
    315 		foreach ( $args['templates'] as $template_data ) {
    316 			$result = $this->update_template( $template_data );
    317 
    318 			if ( is_wp_error( $result ) ) {
    319 				return $result;
    320 			}
    321 		}
    322 
    323 		return true;
    324 	}
    325 
    326 	/**
    327 	 * Get template data.
    328 	 *
    329 	 * Retrieve the template data.
    330 	 *
    331 	 * @since 1.5.0
    332 	 * @access public
    333 	 *
    334 	 * @param array $args Template arguments.
    335 	 *
    336 	 * @return \WP_Error|bool|array ??
    337 	 */
    338 	public function get_template_data( array $args ) {
    339 		$validate_args = $this->ensure_args( [ 'source', 'template_id' ], $args );
    340 
    341 		if ( is_wp_error( $validate_args ) ) {
    342 			return $validate_args;
    343 		}
    344 
    345 		if ( isset( $args['edit_mode'] ) ) {
    346 			Plugin::$instance->editor->set_edit_mode( $args['edit_mode'] );
    347 		}
    348 
    349 		$source = $this->get_source( $args['source'] );
    350 
    351 		if ( ! $source ) {
    352 			return new \WP_Error( 'template_error', 'Template source not found.' );
    353 		}
    354 
    355 		do_action( 'elementor/template-library/before_get_source_data', $args, $source );
    356 
    357 		$data = $source->get_data( $args );
    358 
    359 		do_action( 'elementor/template-library/after_get_source_data', $args, $source );
    360 
    361 		return $data;
    362 	}
    363 
    364 	/**
    365 	 * Delete template.
    366 	 *
    367 	 * Delete template from the database.
    368 	 *
    369 	 * @since 1.0.0
    370 	 * @access public
    371 	 *
    372 	 * @param array $args Template arguments.
    373 	 *
    374 	 * @return \WP_Post|\WP_Error|false|null Post data on success, false or null
    375 	 *                                       or 'WP_Error' on failure.
    376 	 */
    377 	public function delete_template( array $args ) {
    378 		$validate_args = $this->ensure_args( [ 'source', 'template_id' ], $args );
    379 
    380 		if ( is_wp_error( $validate_args ) ) {
    381 			return $validate_args;
    382 		}
    383 
    384 		$source = $this->get_source( $args['source'] );
    385 
    386 		if ( ! $source ) {
    387 			return new \WP_Error( 'template_error', 'Template source not found.' );
    388 		}
    389 
    390 		return $source->delete_template( $args['template_id'] );
    391 	}
    392 
    393 	/**
    394 	 * Export template.
    395 	 *
    396 	 * Export template to a file.
    397 	 *
    398 	 * @since 1.0.0
    399 	 * @access public
    400 	 *
    401 	 * @param array $args Template arguments.
    402 	 *
    403 	 * @return mixed Whether the export succeeded or failed.
    404 	 */
    405 	public function export_template( array $args ) {
    406 		$validate_args = $this->ensure_args( [ 'source', 'template_id' ], $args );
    407 
    408 		if ( is_wp_error( $validate_args ) ) {
    409 			return $validate_args;
    410 		}
    411 
    412 		$source = $this->get_source( $args['source'] );
    413 
    414 		if ( ! $source ) {
    415 			return new \WP_Error( 'template_error', 'Template source not found' );
    416 		}
    417 
    418 		return $source->export_template( $args['template_id'] );
    419 	}
    420 
    421 	/**
    422 	 * @since 2.3.0
    423 	 * @access public
    424 	 */
    425 	public function direct_import_template() {
    426 		/** @var Source_Local $source */
    427 		$source = $this->get_source( 'local' );
    428 
    429 		return $source->import_template( $_FILES['file']['name'], $_FILES['file']['tmp_name'] );
    430 	}
    431 
    432 	/**
    433 	 * Import template.
    434 	 *
    435 	 * Import template from a file.
    436 	 *
    437 	 * @since 1.0.0
    438 	 * @access public
    439 	 *
    440 	 * @param array $data
    441 	 *
    442 	 * @return mixed Whether the export succeeded or failed.
    443 	 */
    444 	public function import_template( array $data ) {
    445 		// Imported templates can be either JSON files, or Zip files containing multiple JSON files
    446 		$upload_result = Plugin::$instance->uploads_manager->handle_elementor_upload( $data, [ 'zip', 'json' ] );
    447 
    448 		if ( is_wp_error( $upload_result ) ) {
    449 			return $upload_result;
    450 		}
    451 
    452 		/** @var Source_Local $source_local */
    453 		$source_local = $this->get_source( 'local' );
    454 
    455 		return $source_local->import_template( $upload_result['name'], $upload_result['tmp_name'] );
    456 	}
    457 
    458 	/**
    459 	 * Mark template as favorite.
    460 	 *
    461 	 * Add the template to the user favorite templates.
    462 	 *
    463 	 * @since 1.9.0
    464 	 * @access public
    465 	 *
    466 	 * @param array $args Template arguments.
    467 	 *
    468 	 * @return mixed Whether the template marked as favorite.
    469 	 */
    470 	public function mark_template_as_favorite( $args ) {
    471 		$validate_args = $this->ensure_args( [ 'source', 'template_id', 'favorite' ], $args );
    472 
    473 		if ( is_wp_error( $validate_args ) ) {
    474 			return $validate_args;
    475 		}
    476 
    477 		$source = $this->get_source( $args['source'] );
    478 
    479 		return $source->mark_as_favorite( $args['template_id'], filter_var( $args['favorite'], FILTER_VALIDATE_BOOLEAN ) );
    480 	}
    481 
    482 	/**
    483 	 * Register default template sources.
    484 	 *
    485 	 * Register the 'local' and 'remote' template sources that Elementor use by
    486 	 * default.
    487 	 *
    488 	 * @since 1.0.0
    489 	 * @access private
    490 	 */
    491 	private function register_default_sources() {
    492 		$sources = [
    493 			'local',
    494 			'remote',
    495 		];
    496 
    497 		foreach ( $sources as $source_filename ) {
    498 			$class_name = ucwords( $source_filename );
    499 			$class_name = str_replace( '-', '_', $class_name );
    500 
    501 			$this->register_source( __NAMESPACE__ . '\Source_' . $class_name );
    502 		}
    503 	}
    504 
    505 	/**
    506 	 * Handle ajax request.
    507 	 *
    508 	 * Fire authenticated ajax actions for any given ajax request.
    509 	 *
    510 	 * @since 1.0.0
    511 	 * @access private
    512 	 *
    513 	 * @param string $ajax_request Ajax request.
    514 	 *
    515 	 * @param array $data
    516 	 *
    517 	 * @return mixed
    518 	 * @throws \Exception
    519 	 */
    520 	private function handle_ajax_request( $ajax_request, array $data ) {
    521 		if ( ! User::is_current_user_can_edit_post_type( Source_Local::CPT ) ) {
    522 			throw new \Exception( 'Access Denied' );
    523 		}
    524 
    525 		if ( ! empty( $data['editor_post_id'] ) ) {
    526 			$editor_post_id = absint( $data['editor_post_id'] );
    527 
    528 			if ( ! get_post( $editor_post_id ) ) {
    529 				throw new \Exception( esc_html__( 'Post not found.', 'elementor' ) );
    530 			}
    531 
    532 			Plugin::$instance->db->switch_to_post( $editor_post_id );
    533 		}
    534 
    535 		$result = call_user_func( [ $this, $ajax_request ], $data );
    536 
    537 		if ( is_wp_error( $result ) ) {
    538 			throw new \Exception( $result->get_error_message() );
    539 		}
    540 
    541 		return $result;
    542 	}
    543 
    544 	/**
    545 	 * Init ajax calls.
    546 	 *
    547 	 * Initialize template library ajax calls for allowed ajax requests.
    548 	 *
    549 	 * @since 2.3.0
    550 	 * @access public
    551 	 *
    552 	 * @param Ajax $ajax
    553 	 */
    554 	public function register_ajax_actions( Ajax $ajax ) {
    555 		$library_ajax_requests = [
    556 			'get_library_data',
    557 			'get_template_data',
    558 			'save_template',
    559 			'update_templates',
    560 			'delete_template',
    561 			'import_template',
    562 			'mark_template_as_favorite',
    563 		];
    564 
    565 		foreach ( $library_ajax_requests as $ajax_request ) {
    566 			$ajax->register_ajax_action( $ajax_request, function( $data ) use ( $ajax_request ) {
    567 				return $this->handle_ajax_request( $ajax_request, $data );
    568 			} );
    569 		}
    570 	}
    571 
    572 	/**
    573 	 * @since 2.3.0
    574 	 * @access public
    575 	 */
    576 	public function handle_direct_actions() {
    577 		if ( ! User::is_current_user_can_edit_post_type( Source_Local::CPT ) ) {
    578 			return;
    579 		}
    580 
    581 		/** @var Ajax $ajax */
    582 		$ajax = Plugin::$instance->common->get_component( 'ajax' );
    583 
    584 		if ( ! $ajax->verify_request_nonce() ) {
    585 			$this->handle_direct_action_error( 'Access Denied' );
    586 		}
    587 
    588 		$action = $_REQUEST['library_action'];
    589 
    590 		$result = $this->$action( $_REQUEST );
    591 
    592 		if ( is_wp_error( $result ) ) {
    593 			/** @var \WP_Error $result */
    594 			$this->handle_direct_action_error( $result->get_error_message() . '.' );
    595 		}
    596 
    597 		$callback = "on_{$action}_success";
    598 
    599 		if ( method_exists( $this, $callback ) ) {
    600 			$this->$callback( $result );
    601 		}
    602 
    603 		die;
    604 	}
    605 
    606 	/**
    607 	 * On successful template import.
    608 	 *
    609 	 * Redirect the user to the template library after template import was
    610 	 * successful finished.
    611 	 *
    612 	 * @since 2.3.0
    613 	 * @access private
    614 	 */
    615 	private function on_direct_import_template_success() {
    616 		wp_safe_redirect( admin_url( Source_Local::ADMIN_MENU_SLUG ) );
    617 	}
    618 
    619 	/**
    620 	 * @since 2.3.0
    621 	 * @access private
    622 	 */
    623 	private function handle_direct_action_error( $message ) {
    624 		_default_wp_die_handler( $message, 'Elementor Library' );
    625 	}
    626 
    627 	/**
    628 	 * Ensure arguments exist.
    629 	 *
    630 	 * Checks whether the required arguments exist in the specified arguments.
    631 	 *
    632 	 * @since 1.0.0
    633 	 * @access private
    634 	 *
    635 	 * @param array $required_args  Required arguments to check whether they
    636 	 *                              exist.
    637 	 * @param array $specified_args The list of all the specified arguments to
    638 	 *                              check against.
    639 	 *
    640 	 * @return \WP_Error|true True on success, 'WP_Error' otherwise.
    641 	 */
    642 	private function ensure_args( array $required_args, array $specified_args ) {
    643 		$not_specified_args = array_diff( $required_args, array_keys( array_filter( $specified_args ) ) );
    644 
    645 		if ( $not_specified_args ) {
    646 			return new \WP_Error( 'arguments_not_specified', sprintf( 'The required argument(s) "%s" not specified.', implode( ', ', $not_specified_args ) ) );
    647 		}
    648 
    649 		return true;
    650 	}
    651 }