Add Creative Elements templates and update index files

- Introduced new templates for catalog, checkout, contact, and error pages.
- Implemented caching headers and redirection in index.php files across various directories.
- Enhanced product and layout templates for better integration with Creative Elements.
- Added backoffice header styles and scripts for improved UI/UX in the admin panel.
This commit is contained in:
2025-07-01 00:56:07 +02:00
parent f00cd5b992
commit 6cc26c0ed2
642 changed files with 213294 additions and 12 deletions

View File

@@ -0,0 +1,97 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks, Elementor
* @copyright 2019-2022 WebshopWorks.com & Elementor.com
* @license https://www.gnu.org/licenses/gpl-3.0.html
*/
namespace CE;
defined('_PS_VERSION_') or die;
class TemplateLibraryXClassesXImportImages
{
const DIR = 'cms/';
const PLACEHOLDER = 'placeholder.png';
private static $imported = [];
public function import($attachment)
{
static $allowed_ext = ['jpg', 'jpe', 'jpeg', 'png', 'gif', 'bmp', 'tif', 'tiff', 'svg'];
$url = $attachment['url'];
if (stripos($url, 'https://') === 0) {
$url = 'http' . \Tools::substr($url, 5);
}
if (isset(self::$imported[$url])) {
// Image was already imported
return self::$imported[$url];
}
if (count($cms = explode('/img/cms/', $url)) > 1) {
// Get filename with subdir
$filename = $cms[1];
} else {
$filename = basename($url);
if (self::PLACEHOLDER == $filename) {
// Do not import placeholder
return self::$imported[$url] = false;
}
}
$file_content = wp_remote_get($url);
if (empty($file_content)) {
// Image isn't available
return self::$imported[$url] = false;
}
$file_info = pathinfo($filename);
if (!in_array(\Tools::strToLower($file_info['extension']), $allowed_ext)) {
// Image extension isn't allowed
return self::$imported[$url] = false;
}
if ($file_info['dirname'] !== '.' && !is_dir(_PS_IMG_DIR_ . self::DIR . $file_info['dirname'])) {
// Create subdir
if (!@mkdir(_PS_IMG_DIR_ . self::DIR . $file_info['dirname'], 0775, true)) {
// Can not create subdir
$filename = $file_info['basename'];
}
}
$file_path = _PS_IMG_DIR_ . self::DIR . $filename;
if (file_exists($file_path)) {
// Filename already exists
$existing_content = \Tools::file_get_contents($file_path);
if ($file_content === $existing_content) {
// Same image already exists
return self::$imported[$url] = [
'id' => 0,
'url' => basename(_PS_IMG_) . '/' . self::DIR . $filename,
];
}
// Add unique filename
$dirname = $file_info['dirname'] !== '.' && $filename !== $file_info['basename'] ? $file_info['dirname'] . '/' : '';
$filename = $dirname . $file_info['filename'] . '_' . Utils::generateRandomString() . '.' . $file_info['extension'];
$file_path = _PS_IMG_DIR_ . self::DIR . $filename;
}
if (!file_put_contents($file_path, $file_content)) {
// Image saved successfuly
return self::$imported[$url] = [
'id' => 0,
'url' => basename(_PS_IMG_) . '/' . self::DIR . $filename,
];
}
// Fallback
return $attachment;
}
}

View File

@@ -0,0 +1,8 @@
<?php
header('Expires: Thu, 28 Feb 2019 00:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../../../../../');
die;

View File

@@ -0,0 +1,8 @@
<?php
header('Expires: Thu, 28 Feb 2019 00:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../../../../');
die;

View File

@@ -0,0 +1,686 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks, Elementor
* @copyright 2019-2022 WebshopWorks.com & Elementor.com
* @license https://www.gnu.org/licenses/gpl-3.0.html
*/
namespace CE;
defined('_PS_VERSION_') or die;
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.
*
* @access protected
*
* @var SourceBase[]
*/
protected $_registered_sources = [];
/**
* Imported template images.
*
* Holds an instance of `Import_Images` class.
*
* @access private
*
* @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
* @access public
*/
public function __construct()
{
$this->registerDefaultSources();
$this->addActions();
}
/**
* @since 2.3.0
* @access public
*/
public function addActions()
{
add_action('elementor/ajax/register_actions', [$this, 'register_ajax_actions']);
add_action('wp_ajax_elementor_library_direct_actions', [$this, 'handle_direct_actions']);
// 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'] = call_user_func('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
* @access public
*
* @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
* @access public
*
* @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');
}
$this->_registered_sources[$source_instance->getId()] = $source_instance;
return true;
}
/**
* Unregister template source.
*
* Remove an existing template sources from the list of registered template
* sources.
*
* @since 1.0.0
* @access public
*
* @param string $id The source ID.
*
* @return bool Whether the source was unregistered.
*/
public function unregisterSource($id)
{
if (!isset($this->_registered_sources[$id])) {
return false;
}
unset($this->_registered_sources[$id]);
return true;
}
/**
* Get registered template sources.
*
* Retrieve registered template sources.
*
* @since 1.0.0
* @access public
*
* @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
* @access public
*
* @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
* @access public
*
* @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
* @access public
*
* @param array $args Library arguments.
*
* @return array Library data.
*/
public function getLibraryData(array $args)
{
$library_data = Api::getLibraryData(!empty($args['sync']));
return [
'templates' => $this->getTemplates(),
'config' => $library_data['types_data'],
];
}
/**
* Save template.
*
* Save new or update existing template on the database.
*
* @since 1.0.0
* @access public
*
* @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
* @access public
*
* @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
* @access public
*
* @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
* @access public
*
* @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
* @access public
*
* @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
* @access public
*
* @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
* @access public
*/
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
* @access public
*
* @param array $data
*
* @return mixed Whether the export succeeded or failed.
*/
public function importTemplate(array $data)
{
/** @var SourceLocal $source */
$file_content = call_user_func('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
* @access public
*
* @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
* @access private
*/
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
* @access private
*
* @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
* @access public
*
* @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
* @access public
*/
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);
}
die;
}
// private function onDirectImportTemplateSuccess()
/**
* @since 2.3.0
* @access private
*/
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
* @access private
*
* @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;
}
}

View File

@@ -0,0 +1,380 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks, Elementor
* @copyright 2019-2022 WebshopWorks.com & Elementor.com
* @license https://www.gnu.org/licenses/gpl-3.0.html
*/
namespace CE;
defined('_PS_VERSION_') or die;
/**
* Elementor template library source base.
*
* Elementor template library source base handler class is responsible for
* initializing all the methods controlling the source of Elementor templates.
*
* @since 1.0.0
* @abstract
*/
abstract class TemplateLibraryXSourceBase
{
/**
* User meta.
*
* Holds the current user meta data.
*
* @access private
*
* @var array
*/
private $user_meta;
/**
* Get template ID.
*
* Retrieve the template ID.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function getId();
/**
* Get template title.
*
* Retrieve the template title.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function getTitle();
/**
* Register template data.
*
* Used to register custom template data like a post type, a taxonomy or any
* other data.
*
* @since 1.0.0
* @access public
*/
public function registerData()
{
}
/**
* Get templates.
*
* Retrieve templates from the template library.
*
* @since 1.0.0
* @access public
* @abstract
*
* @param array $args Optional. Filter templates list based on a set of
* arguments. Default is an empty array.
*/
abstract public function getItems($args = []);
/**
* Get template.
*
* Retrieve a single template from the template library.
*
* @since 1.0.0
* @access public
* @abstract
*
* @param int $template_id The template ID.
*/
abstract public function getItem($template_id);
/**
* Get template data.
*
* Retrieve a single template data from the template library.
*
* @since 1.5.0
* @access public
* @abstract
*
* @param array $args Custom template arguments.
*/
abstract public function getData(array $args);
/**
* Delete template.
*
* Delete template from the database.
*
* @since 1.0.0
* @access public
* @abstract
*
* @param int $template_id The template ID.
*/
abstract public function deleteTemplate($template_id);
/**
* Save template.
*
* Save new or update existing template on the database.
*
* @since 1.0.0
* @access public
* @abstract
*
* @param array $template_data The template data.
*/
abstract public function saveItem($template_data);
/**
* Update template.
*
* Update template on the database.
*
* @since 1.0.0
* @access public
* @abstract
*
* @param array $new_data New template data.
*/
abstract public function updateItem($new_data);
/**
* Export template.
*
* Export template to a file.
*
* @since 1.0.0
* @access public
* @abstract
*
* @param int $template_id The template ID.
*/
abstract public function exportTemplate($template_id);
/**
* Template library source base constructor.
*
* Initializing the template library source base by registering custom
* template data.
*
* @since 1.0.0
* @access public
*/
public function __construct()
{
$this->registerData();
}
/**
* Mark template as favorite.
*
* Update user meta containing his favorite templates. For a given template
* ID, add the template to the favorite templates or remove it from the
* favorites, based on the `favorite` parameter.
*
* @since 1.9.0
* @access public
*
* @param int $template_id The template ID.
* @param bool $favorite Optional. Whether the template is marked as
* favorite, or not. Default is true.
*
* @return int|bool User meta ID if the key didn't exist, true on successful
* update, false on failure.
*/
public function markAsFavorite($template_id, $favorite = true)
{
$favorites_templates = $this->getUserMeta('favorites');
if (!$favorites_templates) {
$favorites_templates = [];
}
if ($favorite) {
$favorites_templates[$template_id] = $favorite;
} elseif (isset($favorites_templates[$template_id])) {
unset($favorites_templates[$template_id]);
}
return $this->updateUserMeta('favorites', $favorites_templates);
}
/**
* Get current user meta.
*
* Retrieve Elementor meta data for the current user.
*
* @since 1.9.0
* @access public
*
* @param string $item Optional. User meta key. Default is null.
*
* @return null|array An array of user meta data, or null otherwise.
*/
public function getUserMeta($item = null)
{
if (null === $this->user_meta) {
$this->user_meta = get_user_meta(get_current_user_id(), $this->getUserMetaPrefix(), true);
}
if (!$this->user_meta) {
$this->user_meta = [];
}
if ($item) {
if (isset($this->user_meta[$item])) {
return $this->user_meta[$item];
}
return null;
}
return $this->user_meta;
}
/**
* Update current user meta.
*
* Update user meta data based on meta key an value.
*
* @since 1.9.0
* @access public
*
* @param string $key Optional. User meta key.
* @param mixed $value Optional. User meta value.
*
* @return int|bool User meta ID if the key didn't exist, true on successful
* update, false on failure.
*/
public function updateUserMeta($key, $value)
{
$meta = $this->getUserMeta();
$meta[$key] = $value;
$this->user_meta = $meta;
return update_user_meta(get_current_user_id(), $this->getUserMetaPrefix(), $meta);
}
/**
* Replace elements IDs.
*
* For any given Elementor content/data, replace the IDs with new randomly
* generated IDs.
*
* @since 1.0.0
* @access protected
*
* @param array $content Any type of Elementor data.
*
* @return mixed Iterated data.
*/
protected function replaceElementsIds($content)
{
return Plugin::$instance->db->iterateData($content, function ($element) {
$element['id'] = Utils::generateRandomString();
return $element;
});
}
/**
* Get Elementor library user meta prefix.
*
* Retrieve user meta prefix used to save Elementor data.
*
* @since 1.9.0
* @access protected
*
* @return string User meta prefix.
*/
protected function getUserMetaPrefix()
{
return 'elementor_library_' . $this->getId();
}
/**
* Process content for export/import.
*
* Process the content and all the inner elements, and prepare all the
* elements data for export/import.
*
* @since 1.5.0
* @access protected
*
* @param array $content A set of elements.
* @param string $method Accepts either `onExport` to export data or
* `onImport` to import data.
*
* @return mixed Processed content data.
*/
protected function processExportImportContent($content, $method)
{
return Plugin::$instance->db->iterateData(
$content,
function ($element_data) use ($method) {
$element = Plugin::$instance->elements_manager->createElementInstance($element_data);
// If the widget/element isn't exist, like a plugin that creates a widget but deactivated
if (!$element) {
return null;
}
return ${'this'}->processElementExportImportContent($element, $method);
}
);
}
/**
* Process single element content for export/import.
*
* Process any given element and prepare the element data for export/import.
*
* @since 1.5.0
* @access protected
*
* @param ControlsStack $element
* @param string $method
*
* @return array Processed element data.
*/
protected function processElementExportImportContent(ControlsStack $element, $method)
{
$element_data = $element->getData();
if (method_exists($element, $method)) {
// TODO: Use the internal element data without parameters.
$element_data = $element->{$method}($element_data);
}
foreach ($element->getControls() as $control) {
$control_class = Plugin::$instance->controls_manager->getControl($control['type']);
// If the control isn't exist, like a plugin that creates the control but deactivated.
if (!$control_class) {
return $element_data;
}
if (method_exists($control_class, $method)) {
$element_data['settings'][$control['name']] = $control_class->{$method}($element->getSettings($control['name']), $control);
}
// On Export, check if the control has an argument 'export' => false.
if ('onExport' === $method && isset($control['export']) && false === $control['export']) {
unset($element_data['settings'][$control['name']]);
}
}
return $element_data;
}
}

View File

@@ -0,0 +1,8 @@
<?php
header('Expires: Thu, 28 Feb 2019 00:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../../../../../');
die;

View File

@@ -0,0 +1,884 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks, Elementor
* @copyright 2019-2022 WebshopWorks.com & Elementor.com
* @license https://www.gnu.org/licenses/gpl-3.0.html
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXBaseXDocument as Document;
use CE\CoreXSettingsXManager as SettingsManager;
use CE\CoreXSettingsXPageXModel as Model;
use CE\ModulesXLibraryXDocumentsXLibraryDocument as LibraryDocument;
/**
* Elementor template library local source.
*
* Elementor template library local source handler class is responsible for
* handling local Elementor templates saved by the user locally on his site.
*
* @since 1.0.0
*/
class TemplateLibraryXSourceLocal extends TemplateLibraryXSourceBase
{
/**
* Elementor template-library post-type slug.
*/
const CPT = 'CETemplate';
// const TAXONOMY_TYPE_SLUG = 'elementor_library_type';
// const TAXONOMY_CATEGORY_SLUG = 'elementor_library_category';
// const TYPE_META_KEY = '_elementor_template_type';
// const TEMP_FILES_DIR = 'elementor/tmp';
// const BULK_EXPORT_ACTION = 'elementor_export_multiple_templates';
// const ADMIN_MENU_SLUG = 'edit.php?post_type=elementor_library';
// const ADMIN_SCREEN_ID = 'edit-elementor_library';
/**
* Template types.
*
* Holds the list of supported template types that can be displayed.
*
* @access private
* @static
*
* @var array
*/
private static $template_types = [];
/**
* @since 2.3.0
* @access public
* @static
* @return array
*/
public static function getTemplateTypes()
{
return self::$template_types;
}
/**
* Get local template type.
*
* Retrieve the template type from the post meta.
*
* @since 1.0.0
* @access public
* @static
*
* @param int $template_id The template ID.
*
* @return mixed The value of meta data field.
*/
public static function getTemplateType($template_id)
{
$post = get_post($template_id);
// return get_post_meta($template_id, Document::TYPE_META_KEY, true);
return $post->template_type;
}
// public static function isBaseTemplatesScreen()
/**
* Add template type.
*
* Register new template type to the list of supported local template types.
*
* @since 1.0.3
* @access public
* @static
*
* @param string $type Template type.
*/
public static function addTemplateType($type)
{
self::$template_types[$type] = $type;
}
/**
* Remove template type.
*
* Remove existing template type from the list of supported local template
* types.
*
* @since 1.8.0
* @access public
* @static
*
* @param string $type Template type.
*/
public static function removeTemplateType($type)
{
if (isset(self::$template_types[$type])) {
unset(self::$template_types[$type]);
}
}
// public static function getAdminUrl($relative = false)
/**
* Get local template ID.
*
* Retrieve the local template ID.
*
* @since 1.0.0
* @access public
*
* @return string The local template ID.
*/
public function getId()
{
return 'local';
}
/**
* Get local template title.
*
* Retrieve the local template title.
*
* @since 1.0.0
* @access public
*
* @return string The local template title.
*/
public function getTitle()
{
return __('Local');
}
// public function registerData()
// public function adminMenuReorder()
// public function adminMenu();
// public function adminTitle($admin_title, $title);
// public function replaceAdminHeading();
/**
* Get local templates.
*
* Retrieve local templates saved by the user on his site.
*
* @since 1.0.0
* @access public
*
* @param array $args Optional. Filter templates based on a set of
* arguments. Default is an empty array.
*
* @return array Local templates.
*/
public function getItems($args = [])
{
$templates = [];
$table = _DB_PREFIX_ . 'ce_template';
$rows = \Db::getInstance()->executeS(
"SELECT id_ce_template, id_employee, title, type, date_add FROM $table WHERE active = 1 ORDER BY title ASC"
);
if ($rows) {
foreach ($rows as &$row) {
$post = new \stdClass();
$post->ID = new UId($row['id_ce_template'], UId::TEMPLATE);
$post->post_author = $row['id_employee'];
$post->post_date = $row['date_add'];
$post->post_title = $row['title'];
$post->template_type = $row['type'];
$templates[] = $this->getItem($post);
}
}
return $templates;
}
/**
* Save local template.
*
* Save new or update existing template on the database.
*
* @since 1.0.0
* @access public
*
* @param array $template_data Local template data.
*
* @return WPError|int The ID of the saved/updated template, `WP_Error` otherwise.
*/
public function saveItem($template_data)
{
$type = Plugin::$instance->documents->getDocumentType($template_data['type'], false);
if (!$type) {
return new WPError('save_error', sprintf('Invalid template type "%s".', $template_data['type']));
}
// TODO: Work with the documents system.
if (!current_user_can('add', 'AdminCETemplates')) {
return new WPError('save_error', __('Access denied.'));
}
$template_id = wp_insert_post([
'post_title' => !empty($template_data['title']) ? $template_data['title'] : __('(no title)'),
'post_status' => 'publish',
'post_type' => self::CPT,
'template_type' => $template_data['type'],
]);
if (is_wp_error($template_id)) {
return $template_id;
}
Plugin::$instance->db->setIsElementorPage($template_id);
Plugin::$instance->db->saveEditor($template_id, $template_data['content']);
// $this->saveItemType($template_id, $template_data['type']);
if (!empty($template_data['page_settings'])) {
SettingsManager::getSettingsManagers('page')->saveSettings($template_data['page_settings'], $template_id);
}
/**
* After template library save.
*
* Fires after Elementor template library was saved.
*
* @since 1.0.1
*
* @param int $template_id The ID of the template.
* @param array $template_data The template data.
*/
do_action('elementor/template-library/after_save_template', $template_id, $template_data);
/**
* After template library update.
*
* Fires after Elementor template library was updated.
*
* @since 1.0.1
*
* @param int $template_id The ID of the template.
* @param array $template_data The template data.
*/
do_action('elementor/template-library/after_update_template', $template_id, $template_data);
return $template_id;
}
/**
* Update local template.
*
* Update template on the database.
*
* @since 1.0.0
* @access public
*
* @param array $new_data New template data.
*
* @return WPError|true True if template updated, `WP_Error` otherwise.
*/
public function updateItem($new_data)
{
if (!current_user_can('edit', $new_data['id'])) {
return new WPError('save_error', __('Access denied.'));
}
Plugin::$instance->db->saveEditor($new_data['id'], $new_data['content']);
/**
* After template library update.
*
* Fires after Elementor template library was updated.
*
* @since 1.0.0
*
* @param int $new_data_id The ID of the new template.
* @param array $new_data The new template data.
*/
do_action('elementor/template-library/after_update_template', $new_data['id'], $new_data);
return true;
}
/**
* Get local template.
*
* Retrieve a single local template saved by the user on his site.
*
* @since 1.0.0
* @access public
*
* @param int|object $template_id The template ID.
*
* @return array Local template.
*/
public function getItem($template_id)
{
$post = is_object($template_id) ? $template_id : get_post($template_id);
$user = get_user_by('id', $post->post_author);
$page = SettingsManager::getSettingsManagers('page')->getModel($post->ID);
$page_settings = $page->getData('settings');
$data = [
'template_id' => "$post->ID",
'source' => $this->getId(),
'type' => $post->template_type,
'title' => $post->post_title,
// 'thumbnail' => get_the_post_thumbnail_url($post),
'date' => strtotime($post->post_date),
'human_date' => \Tools::displayDate($post->post_date),
'author' => $user ? $user->display_name : __('Unknown'),
'hasPageSettings' => !empty($page_settings),
'tags' => [],
'export_link' => $this->getExportLink($post->ID),
'url' => get_preview_post_link($post->ID),
];
/**
* Get template library template.
*
* Filters the template data when retrieving a single template from the
* template library.
*
* @since 1.0.0
*
* @param array $data Template data.
*/
return apply_filters('elementor/template-library/get_template', $data);
}
/**
* Get template data.
*
* Retrieve the data of a single local template saved by the user on his site.
*
* @since 1.5.0
* @access public
*
* @param array $args Custom template arguments.
*
* @return array Local template data.
*/
public function getData(array $args)
{
$db = Plugin::$instance->db;
$template_id = $args['template_id'];
// TODO: Validate the data (in JS too!).
if (!empty($args['display'])) {
$content = $db->getBuilder($template_id);
} else {
$content = $db->getPlainEditor($template_id);
}
if (!empty($content)) {
$content = $this->replaceElementsIds($content);
}
$data = [
'content' => $content,
];
if (!empty($args['page_settings'])) {
$page = SettingsManager::getSettingsManagers('page')->getModel($args['template_id']);
$data['page_settings'] = $page->getData('settings');
}
return $data;
}
/**
* Delete local template.
*
* Delete template from the database.
*
* @since 1.0.0
* @access public
*
* @param int $template_id The template ID.
*
* @return WPPost|WPError|false|null Post data on success, false or null
* or 'WP_Error' on failure.
*/
public function deleteTemplate($template_id)
{
if (!current_user_can('delete', $template_id)) {
return new WPError('template_error', __('Access denied.'));
}
return wp_delete_post($template_id, true) ? ['ID' => $template_id] : false;
}
/**
* Export local template.
*
* Export template to a file.
*
* @since 1.0.0
* @access public
*
* @param int $template_id The template ID.
*
* @return WPError Wrapper error if template export failed.
*/
public function exportTemplate($template_id)
{
$file_data = $this->prepareTemplateExport($template_id);
if (is_wp_error($file_data)) {
return $file_data;
}
$this->sendFileHeaders($file_data['name'], call_user_func('strlen', $file_data['content']));
// Clear buffering just in case.
@ob_end_clean();
flush();
// Output file contents.
echo $file_data['content'];
die;
}
/**
* Export multiple local templates.
*
* Export multiple template to a ZIP file.
*
* @since 1.6.0
* @access public
*
* @param array $template_ids An array of template IDs.
*
* @return WPError Wrapper error if export failed.
*/
public function exportMultipleTemplates(array $template_ids)
{
$files = [];
$temp_path = _PS_UPLOAD_DIR_;
// Create temp path if it doesn't exist
@mkdir($temp_path, 0775, true);
// Create all json files
foreach ($template_ids as $template_id) {
$file_data = $this->prepareTemplateExport($template_id);
if (is_wp_error($file_data)) {
continue;
}
$complete_path = $temp_path . $file_data['name'];
$put_contents = file_put_contents($complete_path, $file_data['content']);
if (!$put_contents) {
return new WPError('404', sprintf('Cannot create file "%s".', $file_data['name']));
}
$files[] = [
'path' => $complete_path,
'name' => $file_data['name'],
];
}
if (!$files) {
return new WPError('empty_files', 'There is no files to export (probably all the requested templates are empty).');
}
// Create temporary .zip file
$zip_archive_filename = 'CreativeElements_templates_' . date('Y-m-d') . '.zip';
$zip_archive = new \ZipArchive();
$zip_complete_path = $temp_path . $zip_archive_filename;
$zip_archive->open($zip_complete_path, \ZipArchive::CREATE);
foreach ($files as $file) {
$zip_archive->addFile($file['path'], $file['name']);
}
$zip_archive->close();
foreach ($files as $file) {
unlink($file['path']);
}
$this->sendFileHeaders($zip_archive_filename, filesize($zip_complete_path));
@ob_end_flush();
@readfile($zip_complete_path);
unlink($zip_complete_path);
die;
}
/**
* Import local template.
*
* Import template from a file.
*
* @since 1.0.0
* @access public
*
* @param string $name - The file name
* @param string $path - The file path
*
* @return WPError|array An array of items on success, 'WP_Error' on failure.
*/
public function importTemplate($name, $path)
{
if (empty($path)) {
return new WPError('file_error', 'Please upload a file to import');
}
$items = [];
$file_extension = pathinfo($name, PATHINFO_EXTENSION);
if ('zip' === $file_extension) {
if (!class_exists('\ZipArchive')) {
return new WPError('zip_error', 'PHP Zip extension not loaded');
}
$zip = new \ZipArchive();
$temp_path = _PS_UPLOAD_DIR_ . uniqid();
$zip->open($path);
$zip->extractTo($temp_path);
$zip->close();
$file_names = array_diff(scandir($temp_path), ['.', '..']);
foreach ($file_names as $file_name) {
$full_file_name = $temp_path . '/' . $file_name;
$import_result = $this->importSingleTemplate($full_file_name);
unlink($full_file_name);
if (is_wp_error($import_result)) {
return $import_result;
}
$items[] = $import_result;
}
rmdir($temp_path);
} else {
$import_result = $this->importSingleTemplate($path);
if (is_wp_error($import_result)) {
return $import_result;
}
$items[] = $import_result;
}
return $items;
}
// public function postRowActions($actions, WPPost $post)
// public function adminImportTemplateForm();
// public function blockTemplateFrontend()
/**
* Is template library supports export.
*
* whether the template library supports export.
*
* Template saved by the user locally on his site, support export by default
* but this can be changed using a filter.
*
* @since 1.0.0
* @access public
*
* @param int $template_id The template ID.
*
* @return bool Whether the template library supports export.
*/
public function isTemplateSupportsExport($template_id)
{
$export_support = true;
/**
* Is template library supports export.
*
* Filters whether the template library supports export.
*
* @since 1.0.0
*
* @param bool $export_support Whether the template library supports export.
* Default is true.
* @param int $template_id Post ID.
*/
$export_support = apply_filters('elementor/template_library/is_template_supports_export', $export_support, $template_id);
return $export_support;
}
// public function removeElementorPostStateFromLibrary($post_states, $post)
/**
* Get template export link.
*
* Retrieve the link used to export a single template based on the template
* ID.
*
* @since 2.0.0
* @access private
*
* @param int $template_id The template ID.
*
* @return string Template export URL.
*/
private function getExportLink($template_id)
{
return \Context::getContext()->link->getAdminLink('AdminCEEditor') . '&' . http_build_query([
'ajax' => 1,
'action' => 'elementor_library_direct_actions',
'library_action' => 'export_template',
'source' => $this->getId(),
'template_id' => "$template_id",
]);
}
// public function onSavePost($post_id, WPPost $post)
// private function saveItemType($post_id, $type)
// public function adminAddBulkExportAction($actions)
// public function adminExportMultipleTemplates($redirect_to, $action, $post_ids)
// public function adminPrintTabs($views)
// public function maybeRenderBlankState($which);
// public function addFilterByCategory($post_type)
/**
* Import single template.
*
* Import template from a file to the database.
*
* @since 1.6.0
* @access private
*
* @param string $file_name File name.
*
* @return WPError|int|array Local template array, or template ID, or `WPError`.
*/
private function importSingleTemplate($file_name)
{
$data = json_decode(call_user_func('file_get_contents', $file_name), true);
if (empty($data)) {
return new WPError('file_error', 'Invalid File');
}
if (isset($data['content'])) {
$content = $data['content'];
} elseif (isset($data['data'])) {
if (is_string($data['data'])) {
// iqit compatibility
$data['type'] = 'page';
$content = json_decode($data['data'], true);
} else {
// retro compatibility
$content = $data['data'];
}
}
if (!isset($content) || !is_array($content)) {
return new WPError('file_error', 'Invalid File');
}
$content = $this->processExportImportContent($content, 'onImport');
$page_settings = [];
if (!empty($data['page_settings'])) {
// $page = new Model([
// 'id' => 0,
// 'settings' => $data['page_settings'],
// ]);
// $page_settings_data = $this->processElementExportImportContent($page, 'onImport');
// if (!empty($page_settings_data['settings'])) {
// $page_settings = $page_settings_data['settings'];
// }
$page_settings = $data['page_settings'];
}
$template_id = $this->saveItem([
'content' => $content,
'title' => $data['title'],
'type' => $data['type'],
'page_settings' => $page_settings,
]);
if (is_wp_error($template_id)) {
return $template_id;
}
return $this->getItem($template_id);
}
/**
* Prepare template to export.
*
* Retrieve the relevant template data and return them as an array.
*
* @since 1.6.0
* @access private
*
* @param int $template_id The template ID.
*
* @return WPError|array Exported template data.
*/
private function prepareTemplateExport($template_id)
{
$template_data = $this->getData([
'template_id' => $template_id,
]);
if (empty($template_data['content'])) {
return new WPError('empty_template', 'The template is empty');
}
$template_data['content'] = $this->processExportImportContent($template_data['content'], 'onExport');
if (get_post_meta($template_id, '_elementor_page_settings', true)) {
$page = SettingsManager::getSettingsManagers('page')->getModel($template_id);
$page_settings_data = $this->processElementExportImportContent($page, 'onExport');
if (!empty($page_settings_data['settings'])) {
$template_data['page_settings'] = $page_settings_data['settings'];
}
}
$post = get_post($template_id);
$export_data = [
'version' => DB::DB_VERSION,
'title' => $post->post_title,
'type' => $post->template_type,
];
$export_data += $template_data;
return [
'name' => 'CreativeElements_' . $post->uid->id . '_' . date('Y-m-d') . '.json',
'content' => json_encode($export_data),
];
}
/**
* Send file headers.
*
* Set the file header when export template data to a file.
*
* @since 1.6.0
* @access private
*
* @param string $file_name File name.
* @param int $file_size File size.
*/
private function sendFileHeaders($file_name, $file_size)
{
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $file_name);
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $file_size);
}
/**
* Get template label by type.
*
* Retrieve the template label for any given template type.
*
* @since 2.0.0
* @access private
*
* @param string $template_type Template type.
*
* @return string Template label.
*/
private function getTemplateLabelByType($template_type)
{
$document_types = Plugin::instance()->documents->getDocumentTypes();
if (isset($document_types[$template_type])) {
$template_label = call_user_func([$document_types[$template_type], 'get_title']);
} else {
$template_label = ucwords(str_replace(['_', '-'], ' ', $template_type));
}
/**
* Template label by template type.
*
* Filters the template label by template type in the template library .
*
* @since 2.0.0
*
* @param string $template_label Template label.
* @param string $template_type Template type.
*/
$template_label = apply_filters('elementor/template-library/get_template_label_by_type', $template_label, $template_type);
return $template_label;
}
// public function adminQueryFilterTypes(\WPQuery $query)
// private function addActions()
// public function adminColumnsContent($column_name, $post_id)
// public function adminColumnsHeaders($posts_columns)
// private function getCurrentTabGroup($default = '')
// private function getLibraryTitle()
// private function isCurrentScreen()
/**
* Template library local source constructor.
*
* Initializing the template library local source base by registering custom
* template data and running custom actions.
*
* @since 1.0.0
* @access public
*/
public function __construct()
{
parent::__construct();
// $this->addActions();
}
}

View File

@@ -0,0 +1,233 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks, Elementor
* @copyright 2019-2022 WebshopWorks.com & Elementor.com
* @license https://www.gnu.org/licenses/gpl-3.0.html
*/
namespace CE;
defined('_PS_VERSION_') or die;
/**
* Elementor template library remote source.
*
* Elementor template library remote source handler class is responsible for
* handling remote templates from Elementor.com servers.
*
* @since 1.0.0
*/
class TemplateLibraryXSourceRemote extends TemplateLibraryXSourceBase
{
/**
* Get remote template ID.
*
* Retrieve the remote template ID.
*
* @since 1.0.0
* @access public
*
* @return string The remote template ID.
*/
public function getId()
{
return 'remote';
}
/**
* Get remote template title.
*
* Retrieve the remote template title.
*
* @since 1.0.0
* @access public
*
* @return string The remote template title.
*/
public function getTitle()
{
return __('Remote');
}
// public function registerData();
/**
* Get remote templates.
*
* Retrieve remote templates from Elementor.com servers.
*
* @since 1.0.0
* @access public
*
* @param array $args Optional. Nou used in remote source.
*
* @return array Remote templates.
*/
public function getItems($args = [])
{
$library_data = Api::getLibraryData();
$templates = [];
if (!empty($library_data['templates'])) {
foreach ($library_data['templates'] as $template_data) {
$templates[] = $this->prepareTemplate($template_data);
}
}
return $templates;
}
/**
* Get remote template.
*
* Retrieve a single remote template from Elementor.com servers.
*
* @since 1.0.0
* @access public
*
* @param int $template_id The template ID.
*
* @return array Remote template.
*/
public function getItem($template_id)
{
$templates = $this->getItems();
return $templates[$template_id];
}
/**
* Save remote template.
*
* Remote template from Elementor.com servers cannot be saved on the
* database as they are retrieved from remote servers.
*
* @since 1.0.0
* @access public
*
* @param array $template_data Remote template data.
*
* @return WPError
*/
public function saveItem($template_data)
{
return new WPError('invalid_request', 'Cannot save template to a remote source');
}
/**
* Update remote template.
*
* Remote template from Elementor.com servers cannot be updated on the
* database as they are retrieved from remote servers.
*
* @since 1.0.0
* @access public
*
* @param array $new_data New template data.
*
* @return WPError
*/
public function updateItem($new_data)
{
return new WPError('invalid_request', 'Cannot update template to a remote source');
}
/**
* Delete remote template.
*
* Remote template from Elementor.com servers cannot be deleted from the
* database as they are retrieved from remote servers.
*
* @since 1.0.0
* @access public
*
* @param int $template_id The template ID.
*
* @return WPError
*/
public function deleteTemplate($template_id)
{
return new WPError('invalid_request', 'Cannot delete template from a remote source');
}
/**
* Export remote template.
*
* Remote template from Elementor.com servers cannot be exported from the
* database as they are retrieved from remote servers.
*
* @since 1.0.0
* @access public
*
* @param int $template_id The template ID.
*
* @return WPError
*/
public function exportTemplate($template_id)
{
return new WPError('invalid_request', 'Cannot export template from a remote source');
}
/**
* Get remote template data.
*
* Retrieve the data of a single remote template from Elementor.com servers.
*
* @since 1.5.0
* @access public
*
* @param array $args Custom template arguments.
* @param string $context Optional. The context. Default is `display`.
*
* @return array Remote Template data.
*/
public function getData(array $args, $context = 'display')
{
$data = Api::getTemplateContent($args['template_id']);
if (is_wp_error($data)) {
return $data;
}
$data['content'] = $this->replaceElementsIds($data['content']);
$data['content'] = $this->processExportImportContent($data['content'], 'onImport');
$post_id = $args['editor_post_id'];
$document = Plugin::$instance->documents->get($post_id);
if ($document) {
$data['content'] = $document->getElementsRawData($data['content'], true);
}
return $data;
}
/**
* @since 2.2.0
* @access private
*/
private function prepareTemplate(array $template_data)
{
$favorite_templates = $this->getUserMeta('favorites');
return [
'template_id' => $template_data['id'],
'source' => $this->getId(),
'type' => $template_data['type'],
'subtype' => $template_data['subtype'],
'title' => $template_data['title'],
'thumbnail' => $template_data['thumbnail'],
'date' => $template_data['tmpl_created'],
'author' => $template_data['author'],
'tags' => json_decode($template_data['tags']),
'isPro' => ('1' === $template_data['is_pro']),
'popularityIndex' => (int) $template_data['popularity_index'],
'trendIndex' => (int) $template_data['trend_index'],
'hasPageSettings' => ('1' === $template_data['has_page_settings']),
'url' => $template_data['url'],
'favorite' => !empty($favorite_templates[$template_data['id']]),
];
}
}