Files
2024-11-20 09:09:44 +01:00

646 lines
16 KiB
PHP

<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks, Elementor
* @copyright 2019-2023 WebshopWorks.com & Elementor.com
* @license https://www.gnu.org/licenses/gpl-3.0.html
*/
namespace CE;
defined('_PS_VERSION_') or exit;
use CE\CoreXCommonXModulesXAjaxXModule as Ajax;
use CE\CoreXSettingsXManager as SettingsManager;
use CE\TemplateLibraryXClassesXImportImages as ImportImages;
use CE\TemplateLibraryXSourceBase as SourceBase;
use CE\TemplateLibraryXSourceLocal as SourceLocal;
/**
* Elementor template library manager.
*
* Elementor template library manager handler class is responsible for
* initializing the template library.
*
* @since 1.0.0
*/
class TemplateLibraryXManager
{
/**
* Registered template sources.
*
* Holds a list of all the supported sources with their instances.
*
* @var SourceBase[]
*/
protected $_registered_sources = [];
/**
* Imported template images.
*
* Holds an instance of `Import_Images` class.
*
* @var ImportImages
*/
private $_import_images = null;
/**
* Template library manager constructor.
*
* Initializing the template library manager by registering default template
* sources and initializing ajax calls.
*
* @since 1.0.0
*/
public function __construct()
{
$this->registerDefaultSources();
$this->addActions();
}
/**
* @since 2.3.0
*/
public function addActions()
{
add_action('elementor/ajax/register_actions', [$this, 'registerAjaxActions']);
add_action('wp_ajax_elementor_library_direct_actions', [$this, 'handleDirectActions']);
// TODO: bc since 2.3.0
add_action('wp_ajax_elementor_update_templates', function () {
if (!isset(${'_POST'}['templates'])) {
return;
}
foreach (${'_POST'}['templates'] as &$template) {
if (!isset($template['content'])) {
return;
}
$template['content'] = stripslashes($template['content']);
}
wp_send_json_success($this->handleAjaxRequest('update_templates', ${'_POST'}));
});
}
/**
* Get `Import_Images` instance.
*
* Retrieve the instance of the `Import_Images` class.
*
* @since 1.0.0
*
* @return ImportImages Imported images instance
*/
public function getImportImagesInstance()
{
if (null === $this->_import_images) {
$this->_import_images = new ImportImages();
}
return $this->_import_images;
}
/**
* Register template source.
*
* Used to register new template sources displayed in the template library.
*
* @since 1.0.0
*
* @param string $source_class The name of source class
* @param array $args Optional. Class arguments. Default is an
* empty array.
*
* @return WPError|true true if the source was registered, `WP_Error`
* otherwise
*/
public function registerSource($source_class, $args = [])
{
if (!class_exists($source_class)) {
return new WPError('source_class_name_not_exists');
}
$source_instance = new $source_class($args);
if (!$source_instance instanceof SourceBase) {
return new WPError('wrong_instance_source');
}
$source_id = $source_instance->getId();
if (isset($this->_registered_sources[$source_id])) {
return new WPError('source_exists');
}
$this->_registered_sources[$source_id] = $source_instance;
return true;
}
/**
* Get registered template sources.
*
* Retrieve registered template sources.
*
* @since 1.0.0
*
* @return SourceBase[] Registered template sources
*/
public function getRegisteredSources()
{
return $this->_registered_sources;
}
/**
* Get template source.
*
* Retrieve single template sources for a given template ID.
*
* @since 1.0.0
*
* @param string $id The source ID
*
* @return false|Source_Base Template sources if one exist, False otherwise
*/
public function getSource($id)
{
$sources = $this->getRegisteredSources();
if (!isset($sources[$id])) {
return false;
}
return $sources[$id];
}
/**
* Get templates.
*
* Retrieve all the templates from all the registered sources.
*
* @since 1.0.0
*
* @return array Templates array
*/
public function getTemplates()
{
$templates = [];
foreach ($this->getRegisteredSources() as $source) {
$templates = array_merge($templates, $source->getItems());
}
return $templates;
}
/**
* Get library data.
*
* Retrieve the library data.
*
* @since 1.9.0
*
* @param array $args Library arguments
*
* @return array Library data
*/
public function getLibraryData(array $args)
{
$library_data = Api::getLibraryData(!empty($args['sync']));
// Ensure all document are registered.
Plugin::$instance->documents->getDocumentTypes();
return [
'templates' => $this->getTemplates(),
'config' => $library_data['types_data'],
];
}
/**
* Save template.
*
* Save new or update existing template on the database.
*
* @since 1.0.0
*
* @param array $args Template arguments
*
* @return WPError|int The ID of the saved/updated template
*/
public function saveTemplate(array $args)
{
$validate_args = $this->ensureArgs(['post_id', 'source', 'content', 'type'], $args);
if (is_wp_error($validate_args)) {
return $validate_args;
}
$source = $this->getSource($args['source']);
if (!$source) {
return new WPError('template_error', 'Template source not found.');
}
$args['content'] = json_decode($args['content'], true);
$page = SettingsManager::getSettingsManagers('page')->getModel($args['post_id']);
$args['page_settings'] = $page->getData('settings');
$template_id = $source->saveItem($args);
if (is_wp_error($template_id)) {
return $template_id;
}
return $source->getItem($template_id);
}
/**
* Update template.
*
* Update template on the database.
*
* @since 1.0.0
*
* @param array $template_data New template data
*
* @return WPError|Source_Base template sources instance if the templates
* was updated, `WP_Error` otherwise
*/
public function updateTemplate(array $template_data)
{
$validate_args = $this->ensureArgs(['source', 'content', 'type'], $template_data);
if (is_wp_error($validate_args)) {
return $validate_args;
}
$source = $this->getSource($template_data['source']);
if (!$source) {
return new WPError('template_error', 'Template source not found.');
}
$template_data['content'] = json_decode($template_data['content'], true);
$update = $source->updateItem($template_data);
if (is_wp_error($update)) {
return $update;
}
return $source->getItem($template_data['id']);
}
/**
* Update templates.
*
* Update template on the database.
*
* @since 1.0.0
*
* @param array $args Template arguments
*
* @return WPError|true True if templates updated, `WP_Error` otherwise
*/
public function updateTemplates(array $args)
{
foreach ($args['templates'] as $template_data) {
$result = $this->updateTemplate($template_data);
if (is_wp_error($result)) {
return $result;
}
}
return true;
}
/**
* Get template data.
*
* Retrieve the template data.
*
* @since 1.5.0
*
* @param array $args Template arguments
*
* @return WPError|bool|array ??
*/
public function getTemplateData(array $args)
{
$validate_args = $this->ensureArgs(['source', 'template_id'], $args);
if (is_wp_error($validate_args)) {
return $validate_args;
}
if (isset($args['edit_mode'])) {
Plugin::$instance->editor->setEditMode($args['edit_mode']);
}
$source = $this->getSource($args['source']);
if (!$source) {
return new WPError('template_error', 'Template source not found.');
}
do_action('elementor/template-library/before_get_source_data', $args, $source);
$data = $source->getData($args);
do_action('elementor/template-library/after_get_source_data', $args, $source);
return $data;
}
/**
* Delete template.
*
* Delete template from the database.
*
* @since 1.0.0
*
* @param array $args Template arguments
*
* @return WPPost|WPError|false|null post data on success, false or null
* or 'WP_Error' on failure
*/
public function deleteTemplate(array $args)
{
$validate_args = $this->ensureArgs(['source', 'template_id'], $args);
if (is_wp_error($validate_args)) {
return $validate_args;
}
$source = $this->getSource($args['source']);
if (!$source) {
return new WPError('template_error', 'Template source not found.');
}
return $source->deleteTemplate($args['template_id']);
}
/**
* Export template.
*
* Export template to a file.
*
* @since 1.0.0
*
* @param array $args Template arguments
*
* @return mixed Whether the export succeeded or failed
*/
public function exportTemplate(array $args)
{
$validate_args = $this->ensureArgs(['source', 'template_id'], $args);
if (is_wp_error($validate_args)) {
return $validate_args;
}
$source = $this->getSource($args['source']);
if (!$source) {
return new WPError('template_error', 'Template source not found');
}
return $source->exportTemplate($args['template_id']);
}
/**
* @since 2.3.0
*/
public function directImportTemplate()
{
/* @var SourceLocal $source */
$source = $this->getSource('local');
return $source->importTemplate($_FILES['file']['name'], $_FILES['file']['tmp_name']);
}
/**
* Import template.
*
* Import template from a file.
*
* @since 1.0.0
*
* @param array $data
*
* @return mixed Whether the export succeeded or failed
*/
public function importTemplate(array $data)
{
/* @var SourceLocal $source */
$file_content = base64_decode($data['fileData']);
$tmp_file = tmpfile();
fwrite($tmp_file, $file_content);
$source = $this->getSource('local');
$result = $source->importTemplate($data['fileName'], stream_get_meta_data($tmp_file)['uri']);
fclose($tmp_file);
return $result;
}
/**
* Mark template as favorite.
*
* Add the template to the user favorite templates.
*
* @since 1.9.0
*
* @param array $args Template arguments
*
* @return mixed Whether the template marked as favorite
*/
public function markTemplateAsFavorite($args)
{
unset($args['editor_post_id']);
$validate_args = $this->ensureArgs(['source', 'template_id', 'favorite'], $args);
if (is_wp_error($validate_args)) {
return $validate_args;
}
$source = $this->getSource($args['source']);
return $source->markAsFavorite($args['template_id'], filter_var($args['favorite'], FILTER_VALIDATE_BOOLEAN));
}
/**
* Register default template sources.
*
* Register the 'local' and 'remote' template sources that Elementor use by
* default.
*
* @since 1.0.0
*/
private function registerDefaultSources()
{
$sources = [
'local',
'remote',
];
foreach ($sources as $source_filename) {
$class_name = ucwords($source_filename);
$class_name = str_replace('-', '_', $class_name);
$this->registerSource(__NAMESPACE__ . '\TemplateLibraryXSource' . $class_name);
}
}
/**
* Handle ajax request.
*
* Fire authenticated ajax actions for any given ajax request.
*
* @since 1.0.0
*
* @param string $ajax_request Ajax request
* @param array $data
*
* @return mixed
*
* @throws \Exception
*/
private function handleAjaxRequest($ajax_request, array $data)
{
if (!User::isCurrentUserCanEditPostType(SourceLocal::CPT)) {
throw new \Exception('Access Denied');
}
if (!empty($data['editor_post_id'])) {
$editor_post_id = absint($data['editor_post_id']);
if (!get_post($editor_post_id)) {
throw new \Exception(__('Post not found.'));
}
Plugin::$instance->db->switchToPost($editor_post_id);
}
$result = call_user_func([$this, \Tools::toCamelCase($ajax_request)], $data);
if (is_wp_error($result)) {
throw new \Exception($result->getErrorMessage());
}
return $result;
}
/**
* Init ajax calls.
*
* Initialize template library ajax calls for allowed ajax requests.
*
* @since 2.3.0
*
* @param Ajax $ajax
*/
public function registerAjaxActions(Ajax $ajax)
{
$library_ajax_requests = [
'get_library_data',
'get_template_data',
'save_template',
'update_templates',
'delete_template',
'import_template',
'mark_template_as_favorite',
];
foreach ($library_ajax_requests as $ajax_request) {
$ajax->registerAjaxAction($ajax_request, function ($data) use ($ajax_request) {
return $this->handleAjaxRequest($ajax_request, $data);
});
}
}
/**
* @since 2.3.0
*/
public function handleDirectActions()
{
if (!User::isCurrentUserCanEditPostType(SourceLocal::CPT)) {
return;
}
/* @var Ajax $ajax */
// $ajax = Plugin::$instance->common->getComponent('ajax');
// if (!$ajax->verifyRequestNonce()) {
// $this->handleDirectActionError('Access Denied');
// }
$action = \Tools::toCamelCase(\Tools::getValue('library_action'));
$result = $this->$action($_REQUEST);
if (is_wp_error($result)) {
/* @var WPError $result */
$this->handleDirectActionError($result->getErrorMessage() . '.');
}
$callback = "on{$action}Success";
if (method_exists($this, $callback)) {
$this->$callback($result);
}
exit;
}
// private function onDirectImportTemplateSuccess()
/**
* @since 2.3.0
*/
private function handleDirectActionError($message)
{
// _default_wp_die_handler($message, 'Elementor Library');
wp_send_json_error('Elementor Library - ' . $message);
}
/**
* Ensure arguments exist.
*
* Checks whether the required arguments exist in the specified arguments.
*
* @since 1.0.0
*
* @param array $required_args required arguments to check whether they
* exist
* @param array $specified_args the list of all the specified arguments to
* check against
*
* @return WPError|true True on success, 'WP_Error' otherwise
*/
private function ensureArgs(array $required_args, array $specified_args)
{
$not_specified_args = array_diff($required_args, array_keys(array_filter($specified_args)));
if ($not_specified_args) {
return new WPError('arguments_not_specified', 'The required argument(s) `' . implode(', ', $not_specified_args) . '` not specified');
}
return true;
}
}