This commit is contained in:
2025-07-13 11:19:53 +02:00
parent 38b28dd897
commit be0e84c23c
641 changed files with 217372 additions and 2 deletions

View File

@@ -0,0 +1,176 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CEContent extends ObjectModel
{
public $id_employee;
public $id_product = 0;
public $title;
public $hook;
public $content;
public $position;
public $active;
public $date_add;
public $date_upd;
public static $definition = [
'table' => 'ce_content',
'primary' => 'id_ce_content',
'multilang' => true,
'multilang_shop' => true,
'fields' => [
'id_employee' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
'id_product' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
'hook' => ['type' => self::TYPE_STRING, 'validate' => 'isHookName', 'required' => true, 'size' => 64],
// Shop fields
'position' => ['type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'],
'active' => ['type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isBool'],
'date_add' => ['type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'],
'date_upd' => ['type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'],
// Lang fields
'title' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128],
'content' => ['type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'],
],
];
public function __construct($id = null, $id_lang = null, $id_shop = null, $translator = null)
{
parent::__construct($id, $id_lang, $id_shop, $translator);
// Insert missing ce_content_lang row if new language was added
if (!$this->id && $id && $id_lang && $id_shop && Shop::getShop($id_shop) && Language::getLanguage($id_lang) && self::getHookById($id) !== false) {
$res = Db::getInstance()->insert('ce_content_lang', [
'id_ce_content' => (int) $id,
'id_lang' => (int) $id_lang,
'id_shop' => (int) $id_shop,
'title' => '',
'content' => '',
]);
empty($res) or parent::__construct($id, $id_lang, $id_shop, $translator);
}
}
public function add($auto_date = true, $null_values = false)
{
$ctx = Context::getContext();
$this->id_employee = $ctx->employee->id;
$res = parent::add($auto_date, $null_values);
if ($res && $this->hook && !empty($ctx->controller->module)) {
$ctx->controller->module->registerHook($this->hook, Shop::getContextListShopID());
}
return $res;
}
public function update($null_values = false)
{
if ('0000-00-00 00:00:00' === $this->date_add) {
$this->date_add = date('Y-m-d H:i:s');
}
$before = new self($this->id);
if ($res = parent::update($null_values)) {
$module = Context::getContext()->controller->module;
// handle hook changes
if ($before->hook && !method_exists($module, 'hook' . $before->hook) && !self::hasHook($before->hook)) {
$module->unregisterHook($before->hook, Shop::getContextListShopID());
}
empty($this->hook) or $module->registerHook($this->hook, Shop::getContextListShopID());
}
return $res;
}
public function delete()
{
$res = parent::delete();
if ($res && $this->hook != 'displayFooterProduct') {
$module = Context::getContext()->controller->module;
$shops = Shop::getContextListShopID();
// unregister hook if needed
if (!method_exists($module, 'hook' . $this->hook) && !self::hasHook($this->hook)) {
$module->unregisterHook($this->hook, $shops);
}
}
return $res;
}
public static function displayFieldName($field, $class = __CLASS__, $htmlentities = true, Context $ctx = null)
{
return 'hook' == $field ? 'Position' : parent::displayFieldName($field, $class, $htmlentities, $ctx);
}
public static function hasHook($hook)
{
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'ce_content';
$hook = $db->escape($hook);
return $db->getValue("SELECT 1 FROM $table WHERE hook LIKE '$hook'");
}
public static function getHookById($id)
{
$table = _DB_PREFIX_ . 'ce_content';
return Db::getInstance()->getValue(
"SELECT hook FROM $table WHERE id_ce_content = " . (int) $id
);
}
public static function getIdsByHook($hook, $id_lang, $id_shop, $id_product = 0, $preview = false)
{
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'ce_content';
$hook = $db->escape($hook);
$id_lang = (int) $id_lang;
$id_shop = (int) $id_shop;
$id_product = (int) $id_product;
$id_preview = isset($preview->id, $preview->id_type) && CE\UId::CONTENT == $preview->id_type
? (int) $preview->id
: 0
;
$res = $db->executeS(
"SELECT a.id_ce_content as id FROM $table a
LEFT JOIN {$table}_lang AS b ON a.id_ce_content = b.id_ce_content
LEFT JOIN {$table}_shop sa ON sa.id_ce_content = a.id_ce_content AND sa.id_shop = b.id_shop
WHERE b.id_lang = $id_lang AND sa.id_shop = $id_shop AND a.hook LIKE '$hook' " .
($id_product ? "AND (a.id_product = 0 OR a.id_product = $id_product) " : "") .
($id_preview ? "AND (a.active = 1 OR a.id_ce_content = $id_preview) " : "AND a.active = 1 ") .
"ORDER BY a.id_product DESC"
);
return $res ?: [];
}
public static function getFooterProductId($id_product)
{
if (!$id_product = (int) $id_product) {
return 0;
}
$table = _DB_PREFIX_ . 'ce_content';
return (int) Db::getInstance()->getValue(
"SELECT id_ce_content FROM $table WHERE id_product = $id_product AND hook = 'displayFooterProduct'"
);
}
public static function getMaintenanceId()
{
$table = _DB_PREFIX_ . 'ce_content';
return (int) Db::getInstance()->getValue(
"SELECT id_ce_content FROM $table WHERE hook LIKE 'displayMaintenance' ORDER BY active DESC"
);
}
}

View File

@@ -0,0 +1,319 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CEDatabase
{
private static $hooks = [
'displayBackOfficeHeader',
'displayHeader',
'displayFooterProduct',
'overrideLayoutTemplate',
'CETemplate',
// Actions
'actionFrontControllerAfterInit',
'actionFrontControllerInitAfter',
'actionObjectCERevisionDeleteAfter',
'actionObjectCETemplateDeleteAfter',
'actionObjectCEThemeDeleteAfter',
'actionObjectCEContentDeleteAfter',
'actionObjectProductDeleteAfter',
'actionObjectCategoryDeleteAfter',
'actionObjectManufacturerDeleteAfter',
'actionObjectSupplierDeleteAfter',
'actionObjectCmsDeleteAfter',
'actionObjectCmsCategoryDeleteAfter',
'actionObjectYbc_blog_post_classDeleteAfter',
'actionObjectXipPostsClassDeleteAfter',
'actionObjectStBlogClassDeleteAfter',
'actionObjectBlogPostsDeleteAfter',
'actionObjectNewsClassDeleteAfter',
'actionObjectTvcmsBlogPostsClassDeleteAfter',
'actionProductAdd',
];
public static function initConfigs()
{
$defaults = [
// General
'elementor_frontend_edit' => 1,
'elementor_max_revisions' => 10,
// Style
'elementor_default_generic_fonts' => 'sans-serif',
'elementor_container_width' => 1140,
'elementor_space_between_widgets' => 20,
'elementor_page_title_selector' => 'header.page-header',
'elementor_page_wrapper_selector' => '#content, #wrapper, #wrapper .container',
'elementor_viewport_lg' => 1025,
'elementor_viewport_md' => 768,
'elementor_global_image_lightbox' => 1,
// Advanced
'elementor_edit_buttons' => 'on',
'elementor_exclude_modules' => json_encode([
'administration',
'analytics_stats',
'billing_invoicing',
'checkout',
'dashboard',
'export',
'emailing',
'i18n_localization',
'migration_tools',
'payments_gateways',
'payment_security',
'quick_bulk_update',
'seo',
'shipping_logistics',
'market_place',
]),
'elementor_load_fontawesome' => 1,
'elementor_load_waypoints' => 1,
'elementor_load_slick' => 1,
];
foreach ($defaults as $key => $value) {
Configuration::hasKey($key) or Configuration::updateValue($key, $value);
}
copy(_CE_PATH_ . 'views/lib/filemanager/config.php', _PS_IMG_DIR_ . 'cms/config.php');
copy(_CE_PATH_ . 'views/lib/filemanager/.htaccess', _PS_IMG_DIR_ . 'cms/.htaccess');
}
public static function createTables()
{
$db = Db::getInstance();
$ce_revision = _DB_PREFIX_ . 'ce_revision';
$ce_template = _DB_PREFIX_ . 'ce_template';
$ce_content = _DB_PREFIX_ . 'ce_content';
$ce_theme = _DB_PREFIX_ . 'ce_theme';
$ce_font = _DB_PREFIX_ . 'ce_font';
$ce_meta = _DB_PREFIX_ . 'ce_meta';
$engine = _MYSQL_ENGINE_;
return $db->execute("
CREATE TABLE IF NOT EXISTS `$ce_revision` (
`id_ce_revision` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`parent` bigint(20) UNSIGNED NOT NULL,
`id_employee` int(10) UNSIGNED NOT NULL,
`title` varchar(255) NOT NULL,
`type` varchar(64) NOT NULL DEFAULT '',
`content` longtext NOT NULL,
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
`date_upd` datetime NOT NULL,
PRIMARY KEY (`id_ce_revision`),
KEY `id` (`parent`),
KEY `date_add` (`date_upd`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `$ce_template` (
`id_ce_template` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_employee` int(10) UNSIGNED NOT NULL,
`title` varchar(128) NOT NULL DEFAULT '',
`type` varchar(64) NOT NULL DEFAULT '',
`content` longtext,
`position` int(10) UNSIGNED NOT NULL DEFAULT 0,
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
PRIMARY KEY (`id_ce_template`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `$ce_content` (
`id_ce_content` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_employee` int(10) UNSIGNED NOT NULL,
`id_product` int(10) UNSIGNED NOT NULL DEFAULT 0,
`hook` varchar(64) NOT NULL DEFAULT '',
`position` int(10) UNSIGNED NOT NULL DEFAULT 0,
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
PRIMARY KEY (`id_ce_content`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `{$ce_content}_shop` (
`id_ce_content` int(10) UNSIGNED NOT NULL,
`id_shop` int(10) UNSIGNED NOT NULL,
`position` int(10) UNSIGNED NOT NULL DEFAULT 0,
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
PRIMARY KEY (`id_ce_content`,`id_shop`),
KEY `id_shop` (`id_shop`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `{$ce_content}_lang` (
`id_ce_content` int(10) UNSIGNED NOT NULL,
`id_lang` int(10) UNSIGNED NOT NULL,
`id_shop` int(10) UNSIGNED NOT NULL DEFAULT 1,
`title` varchar(128) NOT NULL DEFAULT '',
`content` longtext,
PRIMARY KEY (`id_ce_content`,`id_shop`,`id_lang`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `$ce_theme` (
`id_ce_theme` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`id_employee` int(10) UNSIGNED NOT NULL,
`type` varchar(64) NOT NULL DEFAULT '',
`position` int(10) UNSIGNED NOT NULL DEFAULT 0,
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
PRIMARY KEY (`id_ce_theme`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `{$ce_theme}_shop` (
`id_ce_theme` int(10) UNSIGNED NOT NULL,
`id_shop` int(10) UNSIGNED NOT NULL,
`position` int(10) UNSIGNED NOT NULL DEFAULT 0,
`active` tinyint(1) UNSIGNED NOT NULL DEFAULT 0,
`date_add` datetime NOT NULL,
`date_upd` datetime NOT NULL,
PRIMARY KEY (`id_ce_theme`,`id_shop`),
KEY `id_shop` (`id_shop`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `{$ce_theme}_lang` (
`id_ce_theme` int(10) UNSIGNED NOT NULL,
`id_lang` int(10) UNSIGNED NOT NULL,
`id_shop` int(10) UNSIGNED NOT NULL DEFAULT 1,
`title` varchar(128) NOT NULL DEFAULT '',
`content` text,
PRIMARY KEY (`id_ce_theme`,`id_shop`,`id_lang`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `$ce_font` (
`id_ce_font` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`family` varchar(128) NOT NULL DEFAULT '',
`files` text,
PRIMARY KEY (`id_ce_font`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
") && $db->execute("
CREATE TABLE IF NOT EXISTS `$ce_meta` (
`id_ce_meta` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`id` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
`name` varchar(255) DEFAULT NULL,
`value` longtext,
PRIMARY KEY (`id_ce_meta`),
KEY `id` (`id`),
KEY `name` (`name`)
) ENGINE=$engine DEFAULT CHARSET=utf8;
");
}
public static function updateTabs()
{
$id = (int) Tab::getIdFromClassName('IMPROVE');
try {
$pos = $id ? 1 : Tab::getInstanceFromClassName('AdminParentModules')->position;
$parent = self::updateTab($id, $pos, 'AdminParentCEContent', true, ['en' => 'Creative Elements'], 'ce');
self::updateTab($parent->id, 1, 'AdminCEThemes', true, [
'en' => 'Theme Builder',
'fr' => 'Constructeur de thème',
'es' => 'Maquetador de temas',
'it' => 'Generatore di temi',
'de' => 'Theme Builder',
'pl' => 'Kreator motywów',
]);
self::updateTab($parent->id, 2, 'AdminCEContent', true, [
'en' => 'Content Anywhere',
'fr' => 'Contenu nimporte où',
'es' => 'Contenido cualquier lugar',
'it' => 'Contenuto Ovunque',
'de' => 'Inhalt überall',
'pl' => 'Treść w dowolnym miejscu',
]);
self::updateTab($parent->id, 3, 'AdminCETemplates', true, [
'en' => 'Saved Templates',
'fr' => 'Modèles enregistrés',
'es' => 'Plantillas guardadas',
'it' => 'Template salvati',
'de' => 'Gespeicherte Templates',
'pl' => 'Zapisane szablony',
]);
self::updateTab($parent->id, 4, 'AdminCEFonts', true, [
'en' => 'Custom Fonts',
'fr' => 'Polices personnalisées',
'es' => 'Fuentes personalizadas',
'it' => 'Font Personalizzati',
'de' => 'Eigene Schriftarten',
'pl' => 'Własne czcionki',
]);
self::updateTab($parent->id, 5, 'AdminCESettings', true, [
'en' => 'Settings',
'fr' => 'Réglages',
'es' => 'Ajustes',
'it' => 'Impostazioni',
'de' => 'Einstellungen',
'pl' => 'Ustawienia',
]);
self::updateTab($parent->id, 6, 'AdminCEEditor', false, [
'en' => 'Live Editor',
'fr' => 'Éditeur en direct',
'es' => 'Editor en vivo',
'it' => 'Editor live',
'de' => 'Live Editor',
'pl' => 'Edytor na żywo',
]);
} catch (Exception $ex) {
return false;
}
return true;
}
protected static function updateTab($id_parent, $position, $class, $active, array $name, $icon = '')
{
$id = (int) Tab::getIdFromClassName($class);
$tab = new Tab($id);
$tab->id_parent = $id_parent;
$tab->position = (int) $position;
$tab->module = 'creativeelements';
$tab->class_name = $class;
$tab->active = $active;
$tab->icon = $icon;
$tab->name = [];
foreach (Language::getLanguages(false) as $lang) {
$tab->name[$lang['id_lang']] = isset($name[$lang['iso_code']]) ? $name[$lang['iso_code']] : $name['en'];
}
if (!$tab->save()) {
throw new Exception('Can not save Tab: ' . $class);
}
if (!$id && $tab->position != $position) {
$tab->position = (int) $position;
$tab->update();
}
return $tab;
}
public static function getHooks($all = true)
{
$hooks = self::$hooks;
if ($all) {
$ce_content = _DB_PREFIX_ . 'ce_content';
$rows = Db::getInstance()->executeS("SELECT DISTINCT hook FROM $ce_content");
if (!empty($rows)) {
foreach ($rows as &$row) {
$hook = $row['hook'];
if ($hook && !in_array($hook, $hooks)) {
$hooks[] = $hook;
}
}
}
}
return $hooks;
}
}

View File

@@ -0,0 +1,133 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CEFont extends ObjectModel
{
public $family;
public $files;
public static $definition = [
'table' => 'ce_font',
'primary' => 'id_ce_font',
'fields' => [
'family' => ['type' => self::TYPE_STRING, 'validate' => 'isImageTypeName', 'required' => true, 'size' => 128],
'files' => ['type' => self::TYPE_STRING, 'validate' => 'isJson'],
],
];
protected static $format = [
'woff' => 'woff',
'woff2' => 'woff2',
'ttf' => 'truetype',
'otf' => 'opentype',
];
public static function getAllowedExt()
{
return array_keys(self::$format);
}
public static function familyAlreadyExists($family, $exclude_id = 0)
{
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'ce_font';
$id_ce_font = (int) $exclude_id;
$family = $db->escape($family);
return (bool) $db->getValue(
"SELECT `id_ce_font` FROM `$table` WHERE `family` = '$family' AND `id_ce_font` != $id_ce_font"
);
}
public static function generateFontsList()
{
$fonts = [];
$font_types = [];
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'ce_font';
$rows = $db->executeS("SELECT `family`, `files` FROM `$table` ORDER BY `family`");
if ($rows) {
foreach ($rows as &$row) {
if ($font_face = self::getFontFaceFromData($row['family'], $row['files'])) {
$fonts[$row['family']] = ['font_face' => $font_face];
}
$font_types[$row['family']] = 'custom';
}
}
CE\update_post_meta(0, 'elementor_fonts_manager_fonts', $fonts);
CE\update_post_meta(0, 'elementor_fonts_manager_font_types', $font_types);
}
public static function getFontFaceFromData($family, $data)
{
is_array($data) or $data = json_decode($data, true);
if (!$data) {
return '';
}
ob_start();
foreach ($data as &$font) {
$src = [];
foreach (self::$format as $ext => $format) {
if (!empty($font[$ext]['url'])) {
if (stripos($font[$ext]['url'], 'modules/') === 0 || stripos($font[$ext]['url'], 'themes/') === 0) {
$url = '{{BASE}}' . trim($font[$ext]['url']);
} else {
$url = trim($font[$ext]['url']);
}
$src[] = "url('$url') format('$format')";
}
}
$src = implode(",\n\t\t", $src);
echo "@font-face {\n";
echo "\tfont-family: '$family';\n";
echo "\tfont-weight: {$font['font_weight']};\n";
echo "\tfont-style: {$font['font_style']};\n";
echo "\tfont-display: swap;\n";
echo "\tsrc: $src;\n";
echo "}\n";
}
return ob_get_clean();
}
public function add($auto_date = true, $null_values = false)
{
if ($result = parent::add($auto_date, $null_values)) {
self::generateFontsList();
}
return $result;
}
public function update($null_values = false)
{
if ($result = parent::update($null_values)) {
self::generateFontsList();
}
return $result;
}
public function delete()
{
if ($result = parent::delete()) {
self::generateFontsList();
}
return $result;
}
public function __toString()
{
return self::getFontFaceFromData($this->family, $this->files);
}
}

View File

@@ -0,0 +1,311 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CEMigrate
{
const IDS_META_KEY = '_ce_migrate_ids';
const MOVE_TIMEOUT = 30;
private static $ids;
private static function searchIds()
{
$table = _DB_PREFIX_ . 'creativepage';
$rows = Db::getInstance()->executeS("SELECT id, active FROM $table ORDER BY id");
$ids = [
'content' => [],
'template' => [],
];
if (!empty($rows)) {
foreach ($rows as &$row) {
$ids[$row['active'] < 2 ? 'content' : 'template'][] = (int) $row['id'];
}
}
return $ids;
}
public static function storeIds()
{
$ids = self::searchIds();
$count = count($ids['content']) + count($ids['template']);
if ($count > 0) {
Configuration::updateGlobalValue('ce_migrate', $count);
CE\update_post_meta(0, self::IDS_META_KEY, $ids) && self::$ids = $ids;
}
return $count;
}
public static function getIds()
{
if (null === self::$ids) {
self::$ids = CE\get_post_meta(0, self::IDS_META_KEY, true);
}
return self::$ids;
}
public static function removeIds($type, $done)
{
$ids = self::getIds();
$ids[$type] = array_values(array_diff($ids[$type], $done));
if (!empty($ids['content']) || !empty($ids['template'])) {
CE\update_post_meta(0, self::IDS_META_KEY, $ids) && self::$ids = $ids;
} else {
self::deleteIds();
Media::clearCache();
}
return [
'type' => $type,
'done' => $done,
];
}
private static function deleteIds()
{
Configuration::deleteByName('ce_migrate');
CE\delete_post_meta(0, self::IDS_META_KEY) && self::$ids = false;
}
private static function getJsDef()
{
$link = Context::getContext()->link;
return [
'ids' => self::getIds(),
'count' => Configuration::getGlobalValue('ce_migrate'),
'baseDir' => __PS_BASE_URI__,
'ajaxUrl' => [
'content' => $link->getAdminLink('AdminCEContent') . '&ajax=1',
'template' => $link->getAdminLink('AdminCETemplates') . '&ajax=1',
],
];
}
public static function registerJavaScripts()
{
$context = Context::getContext();
if ($context->controller instanceof AdminController) {
if (Tools::getValue('CEMigrate') === 'reset' && !self::storeIds()) {
return;
}
Media::addJsDef([
'ceMigrate' => self::getJsDef(),
]);
$context->controller->js_files[] = _MODULE_DIR_ . 'creativeelements/views/js/migrate.js?v=' . _CE_VERSION_;
}
}
public static function renderJavaScripts()
{
$ce_migrate = json_encode(self::getJsDef());
return CESmarty::sprintf(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_inline_script', "
$('#module-modal-import .modal-content').hide();
window.ceMigrate = $ce_migrate;
$.getScript(ceMigrate.baseDir + 'modules/creativeelements/views/js/migrate.js');
");
}
public static function moveConfigs()
{
$table = _DB_PREFIX_ . 'creativepage';
// Get old data rows
$rows = Db::getInstance()->executeS(
"SELECT id_shop, meta_key, meta_value FROM {$table}_meta
WHERE id = 0 AND meta_key LIKE 'elementor_scheme_%'"
);
// Update configs
if (!empty($rows)) {
foreach ($rows as &$row) {
$id_shop = $row['id_shop'];
$id_group = Shop::getGroupFromShop($id_shop);
Configuration::updateValue($row['meta_key'], $row['meta_value'], false, $id_group, $id_shop);
}
}
}
private static function isMoved($id)
{
$res = CE\get_post_meta($id, '_ce_migrated', true);
if (isset($res['started']) && $res['started'] + self::MOVE_TIMEOUT < time()) {
return false;
}
return (bool) $res;
}
private static function startMoving($id)
{
return CE\update_post_meta($id, '_ce_migrated', [
'started' => time(),
]);
}
private static function setMoved($id)
{
return CE\update_post_meta($id, '_ce_migrated', time());
}
public static function moveContent($id, $module)
{
if (self::isMoved($id)) {
return true;
} else {
self::startMoving($id);
}
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'creativepage';
// Get old data rows
$rows = $db->executeS(
"SELECT * FROM $table AS a
INNER JOIN {$table}_lang AS b ON a.id = b.id
INNER JOIN {$table}_shop AS sa ON a.id = sa.id AND b.id_shop = sa.id_shop
WHERE a.id = " . (int) $id
);
if (empty($rows)) {
return false;
}
$res = true;
$id_ce_content = null;
$shops = [];
// Re-structuring rows
foreach ($rows as &$row) {
$id_shop = $row['id_shop'];
$id_lang = $row['id_lang'];
if (empty($shops[$id_shop])) {
$shops[$id_shop] = $row;
$shops[$id_shop]['title'] = [];
$shops[$id_shop]['data'] = [];
}
$shops[$id_shop]['title'][$id_lang] = $row['title'];
$shops[$id_shop]['data'][$id_lang] = $row['data'];
}
foreach ($shops as $id_shop => &$row) {
// Create CEContent if needed
if (!$row['id_page'] || 'displayFooterProduct' === $row['type']) {
// Insert ce_content fields
if (!$id_ce_content) {
$ce_content = [
'id_employee' => (int) $row['id_employee'],
'id_product' => (int) $row['id_page'],
'hook' => $db->escape($row['type']),
'active' => $row['id_page'] ? 1 : (int) $row['active'],
'date_add' => $db->escape($row['date_add']),
'date_upd' => $db->escape($row['date_upd']),
];
if (!$db->insert('ce_content', $ce_content)) {
return false;
}
$id_ce_content = $db->insert_ID();
// Register hook
if (!$row['id_page']) {
$module->registerHook($ce_content['hook'], array_keys($shops));
}
}
// Insert ce_content_shop fields
$ce_content_shop = [
'id_ce_content' => (int) $id_ce_content,
'id_shop' => (int) $id_shop,
'active' => (int) $row['active'],
'date_add' => $db->escape($row['date_add']),
'date_upd' => $db->escape($row['date_upd']),
];
if (!$db->insert('ce_content_shop', $ce_content_shop)) {
return false;
}
// Insert ce_content_lang fields
foreach ($row['title'] as $id_lang => $title) {
$ce_content_lang = [
'id_ce_content' => (int) $id_ce_content,
'id_lang' => (int) $id_lang,
'id_shop' => (int) $id_shop,
'title' => $db->escape($title),
'content' => '',
];
if (!$db->insert('ce_content_lang', $ce_content_lang)) {
return false;
}
}
$id_page = $id_ce_content;
$id_type = CE\UId::CONTENT;
} else {
$id_page = $row['id_page'];
$id_type = CE\UId::getTypeId($row['type']);
}
// Update meta data
foreach ($row['data'] as $id_lang => &$json) {
if ($json) {
$uid = new CE\UId($id_page, $id_type, $id_lang, $id_shop);
$data = json_decode($json, true);
if ($id_ce_content || $row['id_page'] && $row['active']) {
$res &= CE\update_post_meta($uid, '_elementor_edit_mode', 'builder');
}
$res &= CE\update_post_meta($uid, '_elementor_data', $data);
}
}
}
empty($res) or self::setMoved($id);
return $res;
}
public static function moveTemplate($id)
{
if (self::isMoved($id)) {
return true;
} else {
self::startMoving($id);
}
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'creativepage';
// Get old data row
$row = $db->getRow(
"SELECT * FROM $table AS a
INNER JOIN {$table}_lang AS b ON a.id = b.id AND b.id_lang = 1 AND b.id_shop = 1
WHERE a.id = " . (int) $id
);
if (empty($row)) {
return false;
}
// Insert ce_template fields
$res = $db->insert('ce_template', [
'id_employee' => (int) $row['id_employee'],
'title' => $db->escape($row['title']),
'type' => $db->escape($row['type']),
'active' => true,
'date_add' => $db->escape($row['date_add']),
'date_upd' => $db->escape($row['date_upd']),
]);
// Update meta data
if ($res) {
$uid = new CE\UId($db->insert_ID(), CE\UId::TEMPLATE);
$data = json_decode($row['data'], true);
$res &= CE\update_post_meta($uid, '_elementor_edit_mode', 'builder');
$res &= CE\update_post_meta($uid, '_elementor_data', $data);
}
empty($res) or self::setMoved($id);
return $res;
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CERevision extends ObjectModel
{
public $parent;
public $id_employee;
public $title;
public $content;
public $active;
public $date_upd;
public static $definition = [
'table' => 'ce_revision',
'primary' => 'id_ce_revision',
'fields' => [
'parent' => ['type' => self::TYPE_STRING, 'validate' => 'isIp2Long', 'required' => true],
'id_employee' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 255],
'type' => ['type' => self::TYPE_STRING, 'validate' => 'isHookName', 'size' => 64],
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
'active' => ['type' => self::TYPE_INT, 'validate' => 'isBool'],
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
],
];
}

View File

@@ -0,0 +1,173 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CESmarty
{
protected static $tpls = [];
protected static function getTemplate($path)
{
if (isset(self::$tpls[$path])) {
return self::$tpls[$path];
}
$tpl = Context::getContext()->smarty->createTemplate($path);
CE\do_action('smarty/before_fetch', $tpl->smarty);
$tpl->fetch();
CE\do_action('smarty/after_fetch', $tpl->smarty);
return self::$tpls[$path] = $tpl;
}
public static function call($path, $func, array $params = [], $nocache = true)
{
$tpl = self::getTemplate($path);
CE\do_action('smarty/before_call', $tpl->smarty);
isset($tpl->smarty->ext->_tplFunction)
? $tpl->smarty->ext->_tplFunction->callTemplateFunction($tpl, $func, $params, $nocache)
: call_user_func("smarty_template_function_$func", $tpl, $params)
;
CE\do_action('smarty/after_call', $tpl->smarty);
}
public static function capture($path, $func, array $params = [], $nocache = true)
{
ob_start();
self::call($path, $func, $params, $nocache);
return ob_get_clean();
}
public static function get($path, $buffer)
{
$tpl = self::getTemplate($path);
return isset($tpl->smarty->ext->_capture)
? $tpl->smarty->ext->_capture->getBuffer($tpl, $buffer)
: Smarty::$_smarty_vars['capture'][$buffer]
;
}
public static function write($path, $buffer)
{
$tpl = self::getTemplate($path);
echo isset($tpl->smarty->ext->_capture)
? $tpl->smarty->ext->_capture->getBuffer($tpl, $buffer)
: Smarty::$_smarty_vars['capture'][$buffer]
;
}
public static function printf($path, $buffer)
{
$args = func_get_args();
array_shift($args);
$args[0] = self::get($path, $buffer);
call_user_func_array(__FUNCTION__, $args);
}
public static function sprintf($path, $buffer)
{
$args = func_get_args();
array_shift($args);
$args[0] = self::get($path, $buffer);
return call_user_func_array(__FUNCTION__, $args);
}
}
function smartyInclude(array $params)
{
if (empty($params['file'])) {
return;
}
$file = $params['file'];
try {
if (strrpos($file, '../') !== false || strcasecmp(Tools::substr($file, -4), '.tpl') !== 0) {
throw new Exception();
}
if (stripos($file, 'module:') === 0) {
$file = Tools::substr($file, 7);
if (!file_exists($path = _PS_THEME_DIR_ . "modules/$file") &&
(!_PARENT_THEME_NAME_ || !file_exists($path = _PS_PARENT_THEME_DIR_ . "modules/$file")) &&
!file_exists($path = _PS_MODULE_DIR_ . $file)
) {
throw new Exception();
}
} elseif (_PARENT_THEME_NAME_ && stripos($file, 'parent:') === 0) {
$file = Tools::substr($file, 7);
if (!file_exists($path = _PS_PARENT_THEME_DIR_ . "templates/$file")) {
throw new Exception();
}
} elseif (!file_exists($path = _PS_THEME_DIR_ . "templates/$file") &&
(!_PARENT_THEME_NAME_ || !file_exists($path = _PS_PARENT_THEME_DIR_ . "templates/$file"))
) {
throw new Exception();
}
$cache_id = isset($params['cache_id']) ? $params['cache_id'] : null;
$compile_id = isset($params['compile_id']) ? $params['compile_id'] : null;
unset($params['file'], $params['cache_id'], $params['compile_id']);
$out = Context::getContext()->smarty->fetch($path, $cache_id, $compile_id, $params);
} catch (Exception $ex) {
$out = "Failed including: '$file'";
}
return $out;
}
function ce__($text, $module = 'creativeelements')
{
return CE\translate($text, $module);
}
function ce_new($class)
{
$rc = new ReflectionClass($class);
$args = func_get_args();
array_shift($args);
return $rc->newInstanceArgs($args);
}
function ce_enqueue_miniature($uid)
{
static $enqueued = [];
if (isset($enqueued[$uid])) {
return;
}
$enqueued[$uid] = true;
$forceInline = Tools::getValue('render') === 'widget';
if ($forceInline || !Context::getContext()->controller->ajax) {
$css_file = new CE\ModulesXCatalogXFilesXCSSXProductMiniature($uid, $forceInline);
$css_file->enqueue();
}
}
function array_export($array)
{
echo preg_replace(['/\barray\s*\(/i', '/,\r?(\n\s*)\)/'], ['[', '$1]'], var_export($array, true));
}
function _q_c_($if, $then, $else)
{
return $if ? $then : $else;
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CETemplate extends ObjectModel
{
public $id_employee;
public $title;
public $type;
public $content;
public $position;
public $active;
public $date_add;
public $date_upd;
public static $definition = [
'table' => 'ce_template',
'primary' => 'id_ce_template',
'fields' => [
'id_employee' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
'title' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'size' => 128],
'type' => ['type' => self::TYPE_STRING, 'validate' => 'isHookName', 'required' => true, 'size' => 64],
'content' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
'position' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
'active' => ['type' => self::TYPE_INT, 'validate' => 'isBool'],
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
],
];
public function add($auto_date = true, $null_values = false)
{
$this->id_employee = Context::getContext()->employee->id;
return parent::add($auto_date, $null_values);
}
public static function getTypeById($id)
{
$table = _DB_PREFIX_ . 'ce_template';
return Db::getInstance()->getValue(
"SELECT type FROM $table WHERE id_ce_template = " . (int) $id
);
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CETheme extends ObjectModel
{
public $id_employee;
public $title;
public $type;
public $content;
public $position;
public $active;
public $date_add;
public $date_upd;
public static $definition = [
'table' => 'ce_theme',
'primary' => 'id_ce_theme',
'multilang' => true,
'multilang_shop' => true,
'fields' => [
'id_employee' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
'type' => ['type' => self::TYPE_STRING, 'validate' => 'isHookName', 'required' => true, 'size' => 64],
// Shop fields
'position' => ['type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isUnsignedInt'],
'active' => ['type' => self::TYPE_INT, 'shop' => true, 'validate' => 'isBool'],
'date_add' => ['type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'],
'date_upd' => ['type' => self::TYPE_DATE, 'shop' => true, 'validate' => 'isDate'],
// Lang fields
'title' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 128],
'content' => ['type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isCleanHtml'],
],
];
public function add($auto_date = true, $null_values = false)
{
$this->id_employee = Context::getContext()->employee->id;
return parent::add($auto_date, $null_values);
}
public function update($null_values = false)
{
if ('0000-00-00 00:00:00' === $this->date_add) {
$this->date_add = date('Y-m-d H:i:s');
}
return parent::update($null_values);
}
public function delete()
{
$result = parent::delete();
if ($result && 'product-miniature' === $this->type) {
array_map(
'unlink',
glob(_CE_TEMPLATES_ . "front/theme/catalog/_partials/miniatures/product-{$this->id}17????.tpl")
);
}
return $result;
}
public static function getOptions($type, $id_lang, $id_shop)
{
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'ce_theme';
$id_lang = (int) $id_lang;
$id_shop = (int) $id_shop;
$type = $db->escape($type);
$res = $db->executeS(
"SELECT t.id_ce_theme as `value`, CONCAT('#', t.id_ce_theme, ' ', tl.title) as `name` FROM $table AS t
INNER JOIN {$table}_shop as ts ON t.id_ce_theme = ts.id_ce_theme
INNER JOIN {$table}_lang as tl ON t.id_ce_theme = tl.id_ce_theme AND ts.id_shop = tl.id_shop
WHERE ts.active = 1 AND ts.id_shop = $id_shop AND tl.id_lang = $id_lang AND t.type = '$type'
ORDER BY tl.title"
);
return $res ?: [];
}
public static function getTypeById($id)
{
$table = _DB_PREFIX_ . 'ce_theme';
return Db::getInstance()->getValue(
"SELECT type FROM $table WHERE id_ce_theme = " . (int) $id
);
}
}

View File

@@ -0,0 +1,195 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
use PrestaShop\PrestaShop\Adapter\Configuration as ConfigurationAdapter;
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
use Symfony\Component\Filesystem\Filesystem;
defined('_PS_VERSION_') or exit;
if (version_compare(_PS_VERSION_, '1.7.7', '<')) {
require_once _CE_PATH_ . 'classes/assets/CEStylesheetManager5.php';
require_once _CE_PATH_ . 'classes/assets/CEJavascriptManager5.php';
} else {
require_once _CE_PATH_ . 'classes/assets/CEStylesheetManager.php';
require_once _CE_PATH_ . 'classes/assets/CEJavascriptManager.php';
}
require_once _CE_PATH_ . 'classes/assets/CECccReducer.php';
class CEAssetManager
{
protected $controller;
protected $stylesheetManager;
protected $javascriptManager;
protected $template;
public static function instance()
{
static $instance;
if (null === $instance) {
$instance = new self();
CE\add_action('wp_head', 'wp_enqueue_scripts', 1);
CE\do_action('wp_register_scripts');
}
return $instance;
}
protected function __construct()
{
$ctx = Context::getContext();
$config = new ConfigurationAdapter();
$this->controller = $ctx->controller;
$managers = [
'stylesheetManager' => 'CEStylesheetManager',
'javascriptManager' => 'CEJavascriptManager',
];
foreach ($managers as $prop => $class) {
$managerRef = new ReflectionProperty($this->controller, $prop);
$managerRef->setAccessible(true);
$manager = $managerRef->getValue($this->controller);
$listRef = new ReflectionProperty($manager, 'list');
$listRef->setAccessible(true);
$this->$prop = new $class([
_PS_THEME_URI_,
_PS_PARENT_THEME_URI_,
__PS_BASE_URI__,
], $config, $listRef->getValue($manager));
$managerRef->setValue($this->controller, $this->$prop);
}
$reducerRef = new ReflectionProperty($this->controller, 'cccReducer');
$reducerRef->setAccessible(true);
$this->cccReducer = new CECccReducer(
_PS_THEME_DIR_ . 'assets/cache/',
$config,
new Filesystem()
);
$reducerRef->setValue($this->controller, $this->cccReducer);
$this->template = &Closure::bind(function &() {
return ${'this'}->template;
}, $this->controller, $this->controller)->__invoke();
$ctx->smarty->registerPlugin('modifier', 'ce' . 'filter', [$this, 'modifierFilter']);
$ctx->smarty->registerFilter('output', [$this, 'outputFilter']);
}
public function registerStylesheet($id, $path, array $params = [])
{
$params = array_merge([
'media' => AbstractAssetManager::DEFAULT_MEDIA,
'priority' => AbstractAssetManager::DEFAULT_PRIORITY,
'inline' => false,
'server' => 'local',
], $params);
if (_MEDIA_SERVER_1_ && 'remote' !== $params['server'] && !Configuration::get('PS_CSS_THEME_CACHE')) {
$params['server'] = 'remote';
$path = '//' . Tools::getMediaServer($path) . ($this->stylesheetManager->getFullPath($path) ?: $path);
}
$this->stylesheetManager->register($id, $path, $params['media'], $params['priority'], $params['inline'], $params['server']);
}
public function registerJavascript($id, $path, array $params = [])
{
$params = array_merge([
'position' => AbstractAssetManager::DEFAULT_JS_POSITION,
'priority' => AbstractAssetManager::DEFAULT_PRIORITY,
'inline' => false,
'attributes' => null,
'server' => 'local',
], $params);
if (_MEDIA_SERVER_1_ && 'remote' !== $params['server'] && !Configuration::get('PS_JS_THEME_CACHE')) {
$params['server'] = 'remote';
$path = '//' . Tools::getMediaServer($path) . ($this->javascriptManager->getFullPath($path) ?: $path);
}
$this->javascriptManager->register($id, $path, $params['position'], $params['priority'], $params['inline'], $params['attributes'], $params['server']);
}
public function modifierFilter($str)
{
echo $str;
}
public function outputFilter($out, $tpl)
{
if ($this->template === $tpl->template_resource || 'errors/maintenance.tpl' === $tpl->template_resource) {
$assets = $this->fetchAssets();
if (false !== $pos = strpos($out, '<!--CE-JS-->')) {
$out = substr_replace($out, $assets->head, $pos, 0);
}
if (false !== $pos = strrpos($out, '<!--CE-JS-->')) {
$out = substr_replace($out, $assets->bottom, $pos, 0);
}
}
return $out;
}
public function fetchAssets()
{
$smarty = Context::getContext()->smarty;
$assets = new stdClass();
ob_start();
CE\do_action('wp_head');
$assets->head = ob_get_clean();
ob_start();
CE\do_action('wp_footer');
$assets->bottom = ob_get_clean();
$styles = $this->stylesheetManager->listAll();
foreach ($styles['external'] as $id => &$style) {
if (isset(CE\Helper::$inline_styles[$id])) {
$styles['inline'][$id] = [
'content' => implode("\n", CE\Helper::$inline_styles[$id])
];
}
}
$scripts = $this->javascriptManager->listAll();
$js_defs = Media::getJsDef();
if (!empty($smarty->tpl_vars['js_custom_vars'])) {
foreach ($smarty->tpl_vars['js_custom_vars']->value as $key => &$val) {
unset($js_defs[$key]);
}
}
Configuration::get('PS_CSS_THEME_CACHE') && $styles = $this->cccReducer->reduceCss($styles);
Configuration::get('PS_JS_THEME_CACHE') && $scripts = $this->cccReducer->reduceJs($scripts);
$smarty->assign([
'stylesheets' => &$styles,
'javascript' => &$scripts['head'],
'js_custom_vars' => &$js_defs,
]);
$assets->head = $smarty->fetch(_CE_TEMPLATES_ . 'front/theme/_partials/assets.tpl') . $assets->head;
$smarty->assign([
'stylesheets' => [],
'javascript' => &$scripts['bottom'],
'js_custom_vars' => [],
]);
$assets->bottom = $smarty->fetch(_CE_TEMPLATES_ . 'front/theme/_partials/assets.tpl') . $assets->bottom;
return $assets;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or exit;
class CECccReducer extends CccReducer
{
public function reduceCss($cssFileList)
{
return empty($cssFileList['external']) ? $cssFileList : parent::reduceCss($cssFileList);
}
protected function getPathFromUri($fullUri)
{
$fullUri = explode('?', $fullUri, 2)[0];
if (__PS_BASE_URI__ !== '/' && stripos($fullUri, __PS_BASE_URI__) === 0) {
return _PS_ROOT_DIR_ . substr($fullUri, strlen(__PS_BASE_URI__) - 1);
}
return _PS_ROOT_DIR_ . $fullUri;
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
defined('_PS_VERSION_') or exit;
class CEJavascriptManager extends JavascriptManager
{
public function __construct(array $directories, ConfigurationInterface $configuration, $list = null)
{
parent::__construct($directories, $configuration);
is_null($list) or $this->list = $list;
}
public function getFullPath(string $relativePath)
{
if (strrpos($relativePath, '?') !== false) {
$path = explode('?', $relativePath, 2);
$fullPath = parent::getFullPath($path[0]);
return $fullPath ? "$fullPath?$path[1]" : false;
}
return parent::getFullPath($relativePath);
}
public function getList()
{
return parent::getDefaultList();
}
public function listAll()
{
return parent::getList();
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
defined('_PS_VERSION_') or exit;
class CEJavascriptManager extends JavascriptManager
{
public function __construct(array $directories, ConfigurationInterface $configuration, $list = null)
{
parent::__construct($directories, $configuration);
is_null($list) or $this->list = $list;
}
public function getFullPath($relativePath)
{
if (strrpos($relativePath, '?') !== false) {
$path = explode('?', $relativePath, 2);
$fullPath = parent::getFullPath($path[0]);
return $fullPath ? "$fullPath?$path[1]" : false;
}
return parent::getFullPath($relativePath);
}
public function getList()
{
return parent::getDefaultList();
}
public function listAll()
{
return parent::getList();
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
defined('_PS_VERSION_') or exit;
class CEStylesheetManager extends StylesheetManager
{
public function __construct(array $directories, ConfigurationInterface $configuration, $list = null)
{
parent::__construct($directories, $configuration);
is_null($list) or $this->list = $list;
}
public function getFullPath(string $relativePath)
{
if (strrpos($relativePath, '?') !== false) {
$path = explode('?', $relativePath, 2);
$fullPath = parent::getFullPath($path[0]);
return $fullPath ? "$fullPath?$path[1]" : false;
}
return parent::getFullPath($relativePath);
}
public function getList()
{
return parent::getDefaultList();
}
public function listAll()
{
return parent::getList();
}
}

View File

@@ -0,0 +1,43 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
defined('_PS_VERSION_') or exit;
class CEStylesheetManager extends StylesheetManager
{
public function __construct(array $directories, ConfigurationInterface $configuration, $list = null)
{
parent::__construct($directories, $configuration);
is_null($list) or $this->list = $list;
}
public function getFullPath($relativePath)
{
if (strrpos($relativePath, '?') !== false) {
$path = explode('?', $relativePath, 2);
$fullPath = parent::getFullPath($path[0]);
return $fullPath ? "$fullPath?$path[1]" : false;
}
return parent::getFullPath($relativePath);
}
public function getList()
{
return parent::getDefaultList();
}
public function listAll()
{
return parent::getList();
}
}

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,16 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
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,52 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
class WPError
{
private $code;
private $message;
public function __construct($code = '', $message = '', $data = '')
{
if (!$code) {
return;
}
if ($data) {
throw new \RuntimeException('todo');
}
$this->code = $code;
$this->message = $message;
}
public function getErrorMessage($code = '')
{
if (!$this->code) {
return '';
}
if ($code) {
throw new \RuntimeException('todo');
}
return $this->code . ($this->message ? " - {$this->message}" : '');
}
}
function is_wp_error($error)
{
return $error instanceof WPError;
}
function _doing_it_wrong($function, $message = '', $version = '')
{
die(\Tools::displayError($function . ' was called incorrectly. ' . $message . ' ' . $version));
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,625 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
class WPPost
{
private $id;
private $uid;
private $model;
public $_obj;
public $post_author = 0;
public $post_parent = 0;
public $post_date = '';
public $post_modified = '';
public $post_title = '';
public $post_excerpt = '';
public $post_content = '';
public $template_type = 'post';
private function __construct()
{
}
public function __get($prop)
{
switch ($prop) {
case 'uid':
$val = $this->uid;
break;
case 'ID':
case 'post_ID':
$val = $this->id;
break;
case 'post_type':
$val = $this->model;
break;
case 'post_status':
$active = property_exists($this->_obj, 'active') ? 'active' : (
property_exists($this->_obj, 'enabled') ? 'enabled' : 'actif'
);
$val = $this->_obj->$active ? 'publish' : 'private';
break;
default:
throw new \RuntimeException('Unknown property: ' . $prop);
}
return $val;
}
public function __set($prop, $val)
{
switch ($prop) {
case 'ID':
case 'post_ID':
// allow change only when starts with zero
empty($this->id[0]) && $this->id = "$val";
break;
case 'post_type':
// readonly
break;
case 'post_status':
$active = property_exists($this->_obj, 'active') ? 'active' : 'actif';
$this->_obj->$active = 'publish' == $val;
break;
default:
throw new \RuntimeException('Unknown property: ' . $prop);
}
}
public function getLangId()
{
return (int) \Tools::substr($this->id, -4, 2);
}
public static function getInstance(UId $uid, array &$postarr = null)
{
$self = new self();
$self->id = "$uid";
$self->uid = $uid;
$self->model = $uid->getModel();
$objectModel = '\\' . $self->model;
if ($postarr) {
$obj = (object) $postarr;
} elseif ($uid->id_type <= UId::TEMPLATE) {
$obj = new $objectModel($uid->id ? $uid->id : null);
} elseif ($uid->id_type === UId::PRODUCT) {
$obj = new \Product($uid->id, false, $uid->id_lang, $uid->id_shop);
} else {
$obj = new $objectModel($uid->id, $uid->id_lang, $uid->id_shop);
}
$self->_obj = $obj;
if (in_array($uid->id_type, [UId::REVISION, UId::TEMPLATE, UId::THEME])) {
$self->template_type = &$obj->type;
} elseif ($uid->id_type === UId::CONTENT) {
$self->template_type = 'content';
}
property_exists($obj, 'id_employee') && $self->post_author = &$obj->id_employee;
property_exists($obj, 'parent') && $self->post_parent = &$obj->parent;
property_exists($obj, 'date_add') && $self->post_date = &$obj->date_add;
property_exists($obj, 'date_upd') && $self->post_modified = &$obj->date_upd;
if (property_exists($obj, 'title')) {
$self->post_title = &$obj->title;
} elseif (property_exists($obj, 'name')) {
$self->post_title = &$obj->name;
} elseif (property_exists($obj, 'meta_title')) {
$self->post_title = &$obj->meta_title;
}
if (property_exists($obj, 'content')) {
$self->post_content = &$obj->content;
} elseif (property_exists($obj, 'description')) {
$self->post_content = &$obj->description;
} elseif (property_exists($obj, 'post_content')) {
$self->post_content = &$obj->post_content;
}
return $self;
}
}
function get_post($post = null, $output = 'OBJECT', $filter = 'raw')
{
if (null === $post || 0 === $post) {
$post = get_the_ID();
}
if (false === $post || $post instanceof WPPost) {
$_post = $post;
} elseif ($post instanceof UId) {
$_post = WPPost::getInstance($post);
} elseif (is_numeric($post)) {
$_post = WPPost::getInstance(UId::parse($post));
} else {
_doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, 'Invalid $post argument!');
}
if (!$_post) {
return null;
}
if ('OBJECT' !== $output || 'raw' !== $filter) {
throw new \RuntimeException('todo');
}
return $_post;
}
function get_post_status($post = null)
{
if ($_post = get_post($post)) {
return $_post->post_status;
}
return false;
}
function wp_update_post($postarr = [], $wp_error = false)
{
if (is_array($postarr)) {
$id_key = isset($postarr['ID']) ? 'ID' : 'post_ID';
if (empty($postarr[$id_key])) {
_doing_it_wrong(__FUNCTION__, 'ID is missing!');
}
$post = get_post($postarr[$id_key]);
foreach ($postarr as $key => $value) {
$post->$key = $value;
}
} elseif ($postarr instanceof WPPost) {
$post = $postarr;
}
if (!isset($post) || $wp_error) {
throw new \RuntimeException('TODO');
}
// Fix for required lang properties must be defined on default language
$id_lang_def = \Configuration::get('PS_LANG_DEFAULT');
\Configuration::set('PS_LANG_DEFAULT', $post->uid->id_lang);
try {
// Fix: category groups would lose after save
if ($post->_obj instanceof \Category) {
$post->_obj->groupBox = $post->_obj->getGroups();
}
$res = @$post->_obj->update();
} catch (\Exception $ex) {
$res = false;
}
\Configuration::set('PS_LANG_DEFAULT', $id_lang_def);
return $res ? $post->ID : 0;
}
function wp_insert_post(array $postarr, $wp_error = false)
{
$is_revision = 'CERevision' === $postarr['post_type'];
if ($wp_error || !$is_revision && 'CETemplate' != $postarr['post_type']) {
throw new \RuntimeException('TODO');
}
$uid = new UId(0, $is_revision ? UId::REVISION : UId::TEMPLATE);
$post = WPPost::getInstance($uid);
$postarr['post_author'] = \Context::getContext()->employee->id;
foreach ($postarr as $key => &$value) {
$post->$key = $value;
}
if ($post->_obj->add()) {
$uid->id = $post->_obj->id;
$post->ID = "$uid";
} else {
$post->ID = 0;
}
return $post->ID;
}
function wp_delete_post($postid, $force_delete = false)
{
$post = get_post($postid);
return $post->_obj->delete() || $force_delete ? $post : false;
}
function get_post_meta($id, $key = '', $single = false)
{
if (false === $id) {
return $id;
}
$table = _DB_PREFIX_ . 'ce_meta';
$id = ($uid = UId::parse($id)) ? $uid->toDefault() : preg_replace('/\D+/', '', $id);
if (!is_numeric($id)) {
_doing_it_wrong(__FUNCTION__, 'Id must be numeric!');
}
if (!$key) {
$res = [];
$rows = \Db::getInstance()->executeS("SELECT name, value FROM $table WHERE id = $id");
if (!empty($rows)) {
foreach ($rows as &$row) {
$key = &$row['name'];
$val = &$row['value'];
isset($res[$key]) or $res[$key] = [];
$res[$key][] = isset($val[0]) && ('{' == $val[0] || '[' == $val[0] || '"' == $val[0]) ? json_decode($val, true) : $val;
}
}
return $res;
}
$key = preg_replace('/\W+/', '', $key);
if (!$single) {
throw new \RuntimeException('TODO');
}
$val = \Db::getInstance()->getValue("SELECT value FROM $table WHERE id = $id AND name = '$key'");
return isset($val[0]) && ('{' == $val[0] || '[' == $val[0] || '"' == $val[0]) ? json_decode($val, true) : $val;
}
function update_post_meta($id, $key, $value, $prev_value = '')
{
if ($prev_value) {
throw new \RuntimeException('TODO');
}
$db = \Db::getInstance();
$table = _DB_PREFIX_ . 'ce_meta';
$res = true;
$ids = ($uid = UId::parse($id)) ? $uid->getListByShopContext() : (array) $id;
$data = [
'name' => preg_replace('/\W+/', '', $key),
'value' => $db->escape(is_array($value) || is_object($value) ? json_encode($value) : $value, true),
];
foreach ($ids as $id) {
$data['id'] = preg_replace('/\D+/', '', $id);
$id_ce_meta = $db->getValue("SELECT id_ce_meta FROM $table WHERE id = {$data['id']} AND name = '{$data['name']}'");
if ($id_ce_meta) {
$data['id_ce_meta'] = (int) $id_ce_meta;
$type = \Db::REPLACE;
} else {
unset($data['id_ce_meta']);
$type = \Db::INSERT;
}
$res &= $db->insert($table, $data, false, true, $type, false);
}
return $res;
}
function delete_post_meta($id, $key, $value = '')
{
if ($value) {
throw new \RuntimeException('TODO');
}
$ids = ($uid = UId::parse($id)) ? $uid->getListByShopContext() : (array) $id;
foreach ($ids as &$id) {
$id = preg_replace('/\D+/', '', $id);
}
if (count($ids) > 1) {
$in = 'IN';
$ids = '(' . implode(', ', $ids) . ')';
} else {
$in = '=';
$ids = $ids[0];
}
$key = preg_replace('/[^\w\%]+/', '', $key);
$like = strrpos($key, '%') === false ? '=' : 'LIKE';
return \Db::getInstance()->delete('ce_meta', "id $in $ids AND name $like '$key'");
}
function get_post_type($post = null)
{
$uid = uidval($post, null);
return $uid ? $uid->getModel() : false;
}
function get_post_type_object($post_type)
{
// todo
return !$post_type ? null : (object) [
'cap' => (object) [
'edit_post' => 'edit',
'edit_posts' => 'edit',
'publish_posts' => 'edit',
],
];
}
function current_user_can($capability, $args = null)
{
if (is_admin()) {
$employee = \Context::getContext()->employee;
} elseif ($id_employee = get_current_user_id()) {
$employee = new \Employee($id_employee);
}
if (empty($employee->id_profile)) {
return false;
}
if ('manage_options' === $capability) {
return true;
}
if ($uid = uidval($args, false)) {
$controller = $uid->getAdminController();
} elseif (stripos($args, 'Admin') === 0) {
$controller = $args;
} else {
return false;
}
if ('AdminModules' === $controller) {
$id_module = \Module::getModuleIdByName($uid->getModule());
$action = 'view' === $capability ?: 'configure';
$result = \Module::getPermissionStatic($id_module, $action, $employee);
} else {
$id_tab = \Tab::getIdFromClassName($controller);
$access = \Profile::getProfileAccess($employee->id_profile, $id_tab);
$result = '1' === $access[$capability];
}
return $result;
}
function wp_set_post_lock($post_id)
{
if (!$user_id = get_current_user_id()) {
return false;
}
$now = time();
update_post_meta($post_id, '_edit_lock', "$now:$user_id");
return [$now, $user_id];
}
function wp_check_post_lock($post_id)
{
if (!$lock = get_post_meta($post_id, '_edit_lock', true)) {
return false;
}
list($time, $user) = explode(':', $lock);
if (empty($user)) {
return false;
}
$time_window = apply_filters('wp_check_post_lock_window', 150);
if ($time && $time > time() - $time_window && $user != get_current_user_id()) {
return (int) $user;
}
return false;
}
function wp_create_post_autosave(array $post_data)
{
$post_id = isset($post_data['ID']) ? $post_data['ID'] : $post_data['post_ID'];
unset($post_data['ID'], $post_data['post_ID']);
// Autosave already deleted in saveEditor method
$autosave = wp_get_post_autosave($post_id, get_current_user_id());
if ($autosave) {
foreach ($post_data as $key => $value) {
$autosave->$key = $value;
}
return $autosave->_obj->update() ? $autosave->ID : 0;
}
$post_data['post_type'] = 'CERevision';
$post_data['post_status'] = 'private';
$post_data['post_parent'] = $post_id;
$autosave_id = wp_insert_post($post_data);
if ($autosave_id) {
do_action('_wp_put_post_revision', $autosave_id);
return $autosave_id;
}
return 0;
}
function wp_is_post_autosave($post)
{
$uid = uidval($post);
if (UId::REVISION !== $uid->id_type) {
return false;
}
$table = _DB_PREFIX_ . 'ce_revision';
return \Db::getInstance()->getValue(
"SELECT parent FROM $table WHERE id_ce_revision = {$uid->id} AND active = 0"
);
}
function wp_get_post_autosave($post_id, $user_id = 0)
{
$uid = uidval($post_id);
if (UId::REVISION === $uid->id_type) {
return false;
}
$table = _DB_PREFIX_ . 'ce_revision';
$parent = $uid->toDefault();
$id_employee = (int) ($user_id ? $user_id : get_current_user_id());
$id = \Db::getInstance()->getValue(
"SELECT id_ce_revision FROM $table WHERE parent = $parent AND active = 0 AND id_employee = $id_employee"
);
return $id ? WPPost::getInstance(new UId($id, UId::REVISION)) : false;
}
function wp_get_post_parent_id($post_id)
{
if (!$post = get_post($post_id)) {
return false;
}
return !empty($post->_obj->parent) ? $post->_obj->parent : 0;
}
function wp_get_post_revisions($post_id, $args = null)
{
$uid = uidval($post_id);
$parent = $uid->toDefault();
$revisions = [];
$table = _DB_PREFIX_ . 'ce_revision';
$fields = !empty($args['fields']) && 'ids' === $args['fields'] ? 'id_ce_revision' : '*';
$id_employee = (int) \Context::getContext()->employee->id;
$limit = !empty($args['posts_per_page']) ? 'LIMIT 1, ' . (int) $args['posts_per_page'] : '';
$rows = \Db::getInstance()->executeS(
"SELECT $fields FROM $table
WHERE parent = $parent AND (active = 1 OR id_employee = $id_employee)
ORDER BY date_upd DESC $limit"
);
if ($rows) {
foreach ($rows as &$row) {
$uid = new UId($row['id_ce_revision'], UId::REVISION);
if ('*' === $fields) {
$row['id'] = $row['id_ce_revision'];
$revisions[] = WPPost::getInstance($uid, $row);
} else {
$revisions[] = "$uid";
}
}
}
return $revisions;
}
function wp_is_post_revision($post)
{
$revision = get_post($post);
return !empty($revision->_obj->parent) ? $revision->_obj->parent : false;
}
function wp_save_post_revision(WPPost $post)
{
if (UId::REVISION === $post->uid->id_type) {
return;
}
$revisions_to_keep = (int) \Configuration::get('elementor_max_revisions');
if (!$revisions_to_keep) {
return;
}
$db = \Db::getInstance();
$table = _DB_PREFIX_ . 'ce_revision';
$id_employee = \Context::getContext()->employee->id;
foreach (array_reverse($post->uid->getListByShopContext(true)) as $parent) {
$revisions = $db->executeS(
"SELECT id_ce_revision AS id FROM $table WHERE parent = $parent AND active = 1 ORDER BY date_upd DESC"
);
$return = wp_insert_post([
'post_type' => 'CERevision',
'post_status' => 'publish',
'post_author' => $id_employee,
'post_parent' => "$parent",
'post_title' => $post->post_title,
'post_content' => $post->post_content,
'template_type' => $post->template_type,
]);
if (!$return) {
$return = 0;
continue;
}
do_action('_wp_put_post_revision', $return);
for ($i = $revisions_to_keep - 1; isset($revisions[$i]); $i++) {
wp_delete_post_revision(new UId($revisions[$i]['id'], UId::REVISION));
}
}
return $return;
}
function wp_delete_post_revision($revision_id)
{
$revision = get_post($revision_id);
if ('CERevision' !== $revision->post_type) {
return false;
}
return $revision->_obj->delete();
}
function get_post_statuses()
{
return [
'private' => __('Disabled'),
'publish' => __('Enabled'),
];
}
function get_page_templates(WPPost $post = null, $post_type = 'CMS')
{
$templates = [];
foreach (\Context::getContext()->shop->theme->get('meta.available_layouts') as $name => &$layout) {
$templates[$name] = 'layout-full-width' === $name ? __('One Column') : $layout['name'];
}
$post_type = $post ? $post->post_type : $post_type;
if ('Product' === $post_type && \Configuration::get('CE_PRODUCT')) {
$templates = [];
}
return apply_filters("theme_{$post_type}_templates", $templates, $post);
}
function current_theme_supports()
{
// todo
return false;
}
function get_post_types_by_support($feature, $operator = 'and')
{
if ('elementor' !== $feature || 'and' !== $operator) {
throw new \RuntimeException('TODO');
}
return [
'CETemplate',
'CETheme',
'CMS',
'CMSCategory',
];
}
function post_type_supports($post_type, $feature)
{
if ('elementor' === $feature) {
return true;
}
if ('excerpt' === $feature) {
return false;
}
throw new \RuntimeException('TODO: ' . $feature);
}
function post_type_exists($post_type)
{
return UId::getTypeId($post_type) >= 0 ? true : false;
}
function setup_postdata($uid)
{
UId::$_ID = uidval($uid);
}

View File

@@ -0,0 +1,574 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
/**
* Unique Identifier
*/
class UId
{
const REVISION = 0;
const TEMPLATE = 1;
const CONTENT = 2;
const PRODUCT = 3;
const CATEGORY = 4;
const MANUFACTURER = 5;
const SUPPLIER = 6;
const CMS = 7;
const CMS_CATEGORY = 8;
const YBC_BLOG_POST = 9;
const XIPBLOG_POST = 10;
const STBLOG_POST = 11;
const ADVANCEBLOG_POST = 12;
const PRESTABLOG_POST = 13;
/** @deprecated */
const SIMPLEBLOG_POST = 14;
const PSBLOG_POST = 15;
const HIBLOG_POST = 16;
const THEME = 17;
const TVCMSBLOG_POST = 18;
public $id;
public $id_type;
public $id_lang;
public $id_shop;
private static $models = [
'CERevision',
'CETemplate',
'CEContent',
'Product',
'Category',
'Manufacturer',
'Supplier',
'CMS',
'CMSCategory',
'Ybc_blog_post_class',
'XipPostsClass',
'StBlogClass',
'BlogPosts',
'NewsClass',
'SimpleBlogPost',
'PsBlogBlog',
'HiBlogPost',
'CETheme',
'TvcmsPostsClass',
];
private static $admins = [
'AdminCEEditor',
'AdminCETemplates',
'AdminCEContent',
'AdminProducts',
'AdminCategories',
'AdminManufacturers',
'AdminSuppliers',
'AdminCmsContent',
'AdminCmsContent',
'AdminModules',
'AdminXipPost',
'AdminStBlog',
'AdminBlogPosts',
'AdminModules',
'AdminSimpleBlogPosts',
'AdminPsblogBlogs',
'AdminModules',
'AdminCEThemes',
'AdminTvcmsPost',
];
private static $modules = [
self::YBC_BLOG_POST => 'ybc_blog',
self::XIPBLOG_POST => 'xipblog',
self::STBLOG_POST => 'stblog',
self::ADVANCEBLOG_POST => 'advanceblog',
self::PRESTABLOG_POST => 'prestablog',
self::SIMPLEBLOG_POST => 'ph_simpleblog',
self::PSBLOG_POST => 'psblog',
self::HIBLOG_POST => 'hiblog',
self::TVCMSBLOG_POST => 'tvcmsblog',
];
private static $shop_ids = [];
public static $_ID;
public function __construct($id, $id_type, $id_lang = null, $id_shop = null)
{
$this->id = abs((int) $id);
$this->id_type = abs($id_type % 100);
if ($this->id_type <= self::TEMPLATE) {
$this->id_lang = 0;
$this->id_shop = 0;
} else {
is_null($id_lang) && $id_lang = \Context::getContext()->language->id;
$this->id_lang = abs($id_lang % 100);
$this->id_shop = $id_shop ? abs($id_shop % 100) : 0;
}
}
public function getModel()
{
if (empty(self::$models[$this->id_type])) {
throw new \RuntimeException('Unknown ObjectModel');
}
return self::$models[$this->id_type];
}
public function getAdminController()
{
if (empty(self::$admins[$this->id_type])) {
throw new \RuntimeException('Unknown AdminController');
}
if ((int) \Tools::getValue('footerProduct')) {
return self::$admins[self::PRODUCT];
}
return self::$admins[$this->id_type];
}
public function getModule()
{
return isset(self::$modules[$this->id_type]) ? self::$modules[$this->id_type] : '';
}
/**
* Get shop ID list where the object is allowed
*
* @param bool $all Get all or just by shop context
*
* @return array
*/
public function getShopIdList($all = false)
{
if ($this->id_type <= self::TEMPLATE) {
return [0];
}
if (isset(self::$shop_ids[$this->id_type][$this->id])) {
return self::$shop_ids[$this->id_type][$this->id];
}
isset(self::$shop_ids[$this->id_type]) or self::$shop_ids[$this->id_type] = [];
$ids = [];
$model = $this->getModel();
$def = &$model::${'definition'};
$db = \Db::getInstance();
$table = $db->escape(_DB_PREFIX_ . $def['table'] . '_shop');
$primary = $db->escape($def['primary']);
$id = (int) $this->id;
$ctx_ids = implode(', ', $all ? \Shop::getShops(true, null, true) : \Shop::getContextListShopID());
$rows = $db->executeS(
"SELECT id_shop FROM $table WHERE $primary = $id AND id_shop IN ($ctx_ids)"
);
if ($rows) {
foreach ($rows as &$row) {
$ids[] = $row['id_shop'];
}
}
return self::$shop_ids[$this->id_type][$this->id] = $ids;
}
public function getDefaultShopId()
{
return ($ids = $this->getShopIdList()) ? $ids[0] : 0;
}
/**
* Get UId list by shop context
*
* @param bool $strict Collect only from allowed shops
*
* @return array
*/
public function getListByShopContext($strict = false)
{
if ($this->id_shop || $this->id_type <= self::TEMPLATE) {
return ["$this"];
}
$list = [];
$ids = $strict ? $this->getShopIdList() : \Shop::getContextListShopID();
foreach ($ids as $id_shop) {
$this->id_shop = $id_shop;
$list[] = "$this";
}
$this->id_shop = 0;
return $list;
}
/**
* Get Language ID list of CE built contents
*
* @return array
*/
public function getBuiltLangIdList()
{
$ids = [];
if (self::TEMPLATE === $this->id_type) {
$ids[] = 0;
} elseif (self::CONTENT === $this->id_type || self::THEME === $this->id_type) {
foreach (\Language::getLanguages(false) as $lang) {
$ids[] = (int) $lang['id_lang'];
}
} else {
$id_shop = $this->id_shop ?: $this->getDefaultShopId();
$uids = self::getBuiltList($this->id, $this->id_type, $id_shop);
empty($uids[$id_shop]) or $ids = array_keys($uids[$id_shop]);
}
return $ids;
}
public function toDefault()
{
$id_shop = $this->id_shop ?: $this->getDefaultShopId();
return sprintf('%d%02d%02d%02d', $this->id, $this->id_type, $this->id_lang, $id_shop);
}
public function __toString()
{
return sprintf('%d%02d%02d%02d', $this->id, $this->id_type, $this->id_lang, $this->id_shop);
}
public static function parse($id)
{
if ($id instanceof UId) {
return $id;
}
if (!is_numeric($id) || \Tools::strlen($id) <= 6) {
return false;
}
return new self(
\Tools::substr($id, 0, -6),
\Tools::substr($id, -6, 2),
\Tools::substr($id, -4, 2),
\Tools::substr($id, -2)
);
}
public static function getTypeId($model)
{
$model = \Tools::strtolower($model);
return 'cms_category' === $model
? self::CMS_CATEGORY
: array_search($model, array_map('strtolower', self::$models))
;
}
/**
* Get UId list of CE built contents grouped by shop(s)
*
* @param int $id
* @param int $id_type
* @param int|null $id_shop
*
* @return array [
* id_shop => [
* id_lang => UId,
* ],
* ]
*/
public static function getBuiltList($id, $id_type, $id_shop = null)
{
$uids = [];
$table = _DB_PREFIX_ . 'ce_meta';
$shop = null === $id_shop ? '__' : '%02d';
$__id = sprintf("%d%02d__$shop", $id, $id_type, $id_shop);
$rows = \Db::getInstance()->executeS(
"SELECT id FROM $table WHERE id LIKE '$__id' AND name = '_elementor_edit_mode'"
);
if ($rows) {
foreach ($rows as &$row) {
$uid = self::parse($row['id']);
isset($uids[$uid->id_shop]) or $uids[$uid->id_shop] = [];
$uids[$uid->id_shop][$uid->id_lang] = $uid;
}
}
return $uids;
}
}
function absint($num)
{
if ($num instanceof UId) {
return $num;
}
$absint = preg_replace('/\D+/', '', $num);
return $absint ?: 0;
}
function get_user_meta($user_id, $key = '', $single = false)
{
return get_post_meta($user_id, '_u_' . $key, $single);
}
function update_user_meta($user_id, $key, $value, $prev_value = '')
{
return update_post_meta($user_id, '_u_' . $key, $value, $prev_value);
}
function get_the_ID()
{
if (!UId::$_ID && $uid_preview = \CreativeElements::getPreviewUId(false)) {
UId::$_ID = $uid_preview;
}
if (UId::$_ID) {
return UId::$_ID;
}
$controller = \Context::getContext()->controller;
if ($controller instanceof \AdminCEEditorController ||
$controller instanceof \CreativeElementsPreviewModuleFrontController
) {
$id_key = \Tools::getIsset('editor_post_id') ? 'editor_post_id' : 'template_id';
return UId::parse(\Tools::getValue('uid', \Tools::getValue($id_key)));
}
return false;
}
function get_preview_post_link($post = null, array $args = [], $relative = true)
{
$uid = uidval($post);
$ctx = \Context::getContext();
$id_shop = $uid->id_shop ?: $uid->getDefaultShopId();
$args['id_employee'] = $ctx->employee->id;
$args['adtoken'] = \Tools::getAdminTokenLite($uid->getAdminController());
$args['preview_id'] = $uid->toDefault();
switch ($uid->id_type) {
case UId::REVISION:
throw new \RuntimeException('TODO');
case UId::TEMPLATE:
$type = \CETemplate::getTypeById($uid->id);
$id_shop = $ctx->shop->id;
// continue
case UId::THEME:
isset($type) or $type = \CETheme::getTypeById($uid->id);
$id_lang = $uid->id_lang ?: $ctx->language->id;
if ('product' === $type || 'product-quick-view' === $type || 'product-miniature' === $type) {
$document = Plugin::$instance->documents->getDocOrAutoSave($uid, get_current_user_id());
$settings = $document->getData('settings');
empty($settings['preview_id']) or $prod = new \Product($settings['preview_id'], false, $id_lang);
if (empty($prod->id)) {
$prods = \Product::getProducts($id_lang, 0, 1, 'date_upd', 'DESC', false, true);
$prod = new \Product(!empty($prods[0]['id_product']) ? $prods[0]['id_product'] : null, false, $id_lang);
}
$prod_attr = empty($prod->cache_default_attribute) ? 0 : $prod->cache_default_attribute;
empty($prod->active) && empty($args['preview']) && $args['preview'] = 1;
$link = $ctx->link->getProductLink($prod, null, null, null, $id_lang, $id_shop, $prod_attr, false, $relative);
} elseif ('page-contact' === $type) {
$link = $ctx->link->getPageLink('contact', null, $id_lang, null, false, $id_shop, $relative);
} elseif ('page-not-found' === $type) {
$link = $ctx->link->getPageLink('pagenotfound', null, $id_lang, null, false, $id_shop, $relative);
} elseif ('page-index' === $type || 'header' === $type || 'footer' === $type) {
$link = $ctx->link->getPageLink('index', null, $id_lang, null, false, $id_shop, $relative);
\Configuration::get('PS_REWRITING_SETTINGS') && $link = preg_replace('~[^/]+$~', '', $link);
} else {
$link = $ctx->link->getModuleLink('creativeelements', 'preview', [], null, null, null, $relative);
}
break;
case UId::CONTENT:
$hook = \Tools::strtolower(\CEContent::getHookById($uid->id));
if (in_array($hook, Helper::$productHooks)) {
if ($id_product = (int) \Tools::getValue('footerProduct')) {
$args['footerProduct'] = $id_product;
$prod = new \Product($id_product, false, $uid->id_lang, $id_shop);
} else {
$prods = \Product::getProducts($uid->id_lang, 0, 1, 'date_upd', 'DESC', false, true);
$prod = new \Product(!empty($prods[0]['id_product']) ? $prods[0]['id_product'] : null, false, $uid->id_lang);
}
$prod_attr = empty($prod->cache_default_attribute) ? 0 : $prod->cache_default_attribute;
empty($prod->active) && empty($args['preview']) && $args['preview'] = 1;
$link = $ctx->link->getProductLink($prod, null, null, null, $uid->id_lang, $id_shop, $prod_attr, false, $relative);
break;
}
$page = 'index';
if (stripos($hook, 'shoppingcart') !== false) {
$page = 'cart';
$args['action'] = 'show';
} elseif ('displayleftcolumn' === $hook || 'displayrightcolumn' === $hook) {
$layout = 'r' != $hook[7] ? 'layout-left-column' : 'layout-right-column';
$layouts = $ctx->shop->theme->get('theme_settings')['layouts'];
unset($layouts['category']);
if ($key = array_search($layout, $layouts)) {
$page = $key;
} elseif ($key = array_search('layout-both-columns', $layouts)) {
$page = $key;
}
} elseif ('displaynotfound' === $hook) {
$page = 'search';
} elseif ('displaymaintenance' === $hook) {
$args['maintenance'] = 1;
}
$link = $ctx->link->getPageLink($page, null, $uid->id_lang, null, false, $id_shop, $relative);
if ('index' === $page && \Configuration::get('PS_REWRITING_SETTINGS')) {
// Remove rewritten URL if exists
$link = preg_replace('~[^/]+$~', '', $link);
}
break;
case UId::PRODUCT:
$prod = new \Product($uid->id, false, $uid->id_lang, $id_shop);
$prod_attr = !empty($prod->cache_default_attribute) ? $prod->cache_default_attribute : 0;
empty($prod->active) && empty($args['preview']) && $args['preview'] = 1;
$link = $ctx->link->getProductLink($prod, null, null, null, $uid->id_lang, $id_shop, $prod_attr, false, $relative);
break;
case UId::CATEGORY:
$link = $ctx->link->getCategoryLink($uid->id, null, $uid->id_lang, null, $id_shop, $relative);
break;
case UId::CMS:
$link = $ctx->link->getCmsLink($uid->id, null, null, $uid->id_lang, $id_shop, $relative);
break;
case UId::YBC_BLOG_POST:
$link = \Module::getInstanceByName('ybc_blog')->getLink('blog', ['id_post' => $uid->id], $uid->id_lang);
break;
case UID::XIPBLOG_POST:
$link = call_user_func('XipBlog::xipBlogPostLink', ['id' => $uid->id]);
break;
case UId::STBLOG_POST:
$post = new \StBlogClass($uid->id, $uid->id_lang);
$link = $ctx->link->getModuleLink('stblog', 'article', [
'id_st_blog' => $uid->id,
'id_blog' => $uid->id,
'rewrite' => $post->link_rewrite,
], null, $uid->id_lang, null, $relative);
break;
case UId::ADVANCEBLOG_POST:
$post = new \BlogPosts($uid->id, $uid->id_lang);
$args['blogtoken'] = $args['adtoken'];
unset($args['adtoken']);
$link = $ctx->link->getModuleLink('advanceblog', 'detail', [
'id' => $uid->id,
'post' => $post->link_rewrite,
], null, $uid->id_lang, null, $relative);
break;
case UId::PRESTABLOG_POST:
$post = new \NewsClass($uid->id, $uid->id_lang);
empty($post->actif) && $args['preview'] = \Module::getInstanceByName('prestablog')->generateToken($uid->id);
$link = call_user_func('PrestaBlog::prestablogUrl', [
'id' => $uid->id,
'seo' => $post->link_rewrite,
'titre' => $post->title,
'id_lang' => $uid->id_lang,
]);
break;
case UId::SIMPLEBLOG_POST:
$post = new \SimpleBlogPost($uid->id, $uid->id_lang, $uid->id_shop);
$cat = new \SimpleBlogCategory($post->id_simpleblog_category, $uid->id_lang, $uid->id_shop);
$link = call_user_func('SimpleBlogPost::getLink', $post->link_rewrite, $cat->link_rewrite);
break;
case UId::PSBLOG_POST:
$post = new \PsBlogBlog($uid->id, $uid->id_lang, $uid->id_shop);
$link = call_user_func('PsBlogHelper::getInstance')->getBlogLink([
'id_psblog_blog' => $post->id,
'link_rewrite' => $post->link_rewrite,
]);
break;
case UId::HIBLOG_POST:
$post = new \HiBlogPost($uid->id, $uid->id_lang, $uid->id_shop);
$link = \Module::getInstanceByName('hiblog')->returnBlogFrontUrl($post->id, $post->friendly_url, 'post');
break;
case UID::TVCMSBLOG_POST:
$link = call_user_func('TvcmsBlog::tvcmsBlogPostLink', [
'id' => $uid->id,
'rewrite' => call_user_func('TvcmsPostsClass::getTheRewrite', $uid->id),
]);
break;
default:
$method = "get{$uid->getModel()}Link";
$link = $ctx->link->$method($uid->id, null, $uid->id_lang, $id_shop, $relative);
break;
}
return explode('#', $link)[0] . (strrpos($link, '?') === false ? '?' : '&') . http_build_query($args);
}
function uidval($var, $fallback = -1)
{
if (null === $var) {
return get_the_ID();
}
if ($var instanceof UId) {
return $var;
}
if ($var instanceof WPPost) {
return $var->uid;
}
if (is_numeric($var)) {
return UId::parse($var);
}
if ($fallback !== -1) {
return $fallback;
}
throw new \RuntimeException('Can not convert to UId');
}
function get_edit_post_link($post_id)
{
$uid = uidval($post_id);
$ctx = \Context::getContext();
$id = $uid->id;
$model = $uid->getModel();
$admin = $uid->getAdminController();
switch ($uid->id_type) {
case UId::REVISION:
throw new \RuntimeException('TODO');
case UId::YBC_BLOG_POST:
$link = $ctx->link->getAdminLink($admin) . '&' . http_build_query([
'configure' => 'ybc_blog',
'tab_module' => 'front_office_features',
'module_name' => 'ybc_blog',
'control' => 'post',
'id_post' => $id,
]);
break;
case UId::PRESTABLOG_POST:
$link = $ctx->link->getAdminLink($admin) . "&configure=prestablog&editNews&idN=$id";
break;
case UId::CONTENT:
if (\Tools::getIsset('footerProduct')) {
$id = (int) \Tools::getValue('footerProduct');
$model = 'Product';
$admin = 'AdminProducts';
}
// Continue default case
default:
$def = &$model::${'definition'};
$args = [
$def['primary'] => $id,
"update{$def['table']}" => 1,
];
$link = $ctx->link->getAdminLink($admin, true, $args) . '&' . http_build_query($args);
break;
}
return $link;
}

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,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>creativeelements</name>
<displayName><![CDATA[Creative Elements - live PageBuilder [in-stock]]]></displayName>
<version><![CDATA[2.5.0]]></version>
<description><![CDATA[The most advanced frontend drag &amp; drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design. &lt;a href=&quot;https://creativeelements.webshopworks.com/buy-license?utm_source=upgrade&amp;utm_campaign=in-stock&amp;utm_medium=backoffice&amp;utm_term=alysum&quot; target=&quot;_blank&quot;&gt;[Upgrade to PREMIUM]&lt;/a&gt;]]></description>
<author><![CDATA[WebshopWorks]]></author>
<tab><![CDATA[content_management]]></tab>
<is_configurable>1</is_configurable>
<need_instance>1</need_instance>
<limited_countries></limited_countries>
</module>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>creativeelements</name>
<displayName><![CDATA[Creative Elements - live Theme &amp; Page Builder]]></displayName>
<version><![CDATA[2.5.11]]></version>
<description><![CDATA[The most advanced frontend drag &amp; drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.]]></description>
<author><![CDATA[WebshopWorks]]></author>
<tab><![CDATA[content_management]]></tab>
<is_configurable>1</is_configurable>
<need_instance>1</need_instance>
<limited_countries></limited_countries>
</module>

View File

@@ -0,0 +1,309 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
require_once _PS_MODULE_DIR_ . 'creativeelements/classes/CEContent.php';
class AdminCEContentController extends ModuleAdminController
{
public $bootstrap = true;
public $table = 'ce_content';
public $identifier = 'id_ce_content';
public $className = 'CEContent';
public $lang = true;
protected $_defaultOrderBy = 'title';
public function __construct()
{
parent::__construct();
if ((Tools::getIsset('updatece_content') || Tools::getIsset('addce_content')) && Shop::getContextShopID() === null) {
$this->displayWarning(
$this->trans('You are in a multistore context: any modification will impact all your shops, or each shop of the active group.', [], 'Admin.Catalog.Notification')
);
}
$table_shop = _DB_PREFIX_ . $this->table . '_shop';
$this->_select = 'sa.*';
$this->_join = "LEFT JOIN $table_shop sa ON sa.id_ce_content = a.id_ce_content AND b.id_shop = sa.id_shop";
$this->_where = "AND sa.id_shop = " . (int) $this->context->shop->id . " AND a.id_product = 0";
$this->fields_list = [
'id_ce_content' => [
'title' => $this->trans('ID', [], 'Admin.Global'),
'class' => 'fixed-width-xs',
'align' => 'center',
],
'title' => [
'title' => $this->trans('Title', [], 'Admin.Global'),
],
'hook' => [
'title' => $this->trans('Position', [], 'Admin.Global'),
'class' => 'fixed-width-xl',
],
'date_add' => [
'title' => $this->trans('Created on', [], 'Modules.Facetedsearch.Admin'),
'filter_key' => 'sa!date_add',
'class' => 'fixed-width-lg',
'type' => 'datetime',
],
'date_upd' => [
'title' => $this->l('Modified on'),
'filter_key' => 'sa!date_upd',
'class' => 'fixed-width-lg',
'type' => 'datetime',
],
'active' => [
'title' => $this->trans('Displayed', [], 'Admin.Global'),
'filter_key' => 'sa!active',
'class' => 'fixed-width-xs',
'align' => 'center',
'active' => 'status',
'type' => 'bool',
],
];
$this->bulk_actions = [
'delete' => [
'text' => $this->trans('Delete selected', [], 'Admin.Notifications.Info'),
'icon' => 'fa fa-icon-trash',
'confirm' => $this->trans('Delete selected items?', [], 'Admin.Notifications.Info'),
],
];
}
public function ajaxProcessHideEditor()
{
$id = (int) Tools::getValue('id');
$id_type = (int) Tools::getValue('idType');
$uids = CE\UId::getBuiltList($id, $id_type, $this->context->shop->id);
$res = empty($uids) ? $uids : array_keys($uids[$this->context->shop->id]);
die(json_encode($res));
}
public function ajaxProcessMigrate()
{
if ($ids = Tools::getValue('ids')) {
require_once _CE_PATH_ . 'classes/CEMigrate.php';
$done = [];
foreach ($ids as $id) {
CEMigrate::moveContent($id, $this->module) && $done[] = (int) $id;
}
$res = CEMigrate::removeIds('content', $done);
die(json_encode($res));
}
}
public function setMedia($isNewTheme = false)
{
parent::setMedia($isNewTheme);
$this->addJquery();
$this->js_files[] = _MODULE_DIR_ . 'creativeelements/views/lib/e-select2/js/e-select2.full.min.js?v=4.0.6-rc1';
$this->css_files[_MODULE_DIR_ . 'creativeelements/views/lib/e-select2/css/e-select2.min.css?v=4.0.6-rc1'] = 'all';
}
public function initHeader()
{
parent::initHeader();
$display_suppliers = Configuration::get('PS_DISPLAY_SUPPLIERS');
$display_manufacturers = version_compare(_PS_VERSION_, '1.7.7', '<')
? $display_suppliers
: Configuration::get('PS_DISPLAY_MANUFACTURERS');
$id_lang = $this->context->language->id;
$link = $this->context->link;
$tabs = &$this->context->smarty->tpl_vars['tabs']->value;
foreach ($tabs as &$tab0) {
foreach ($tab0['sub_tabs'] as &$tab1) {
if ('AdminParentCEContent' === $tab1['class_name']) {
foreach ($tab1['sub_tabs'] as &$tab2) {
if ('AdminCEContent' === $tab2['class_name']) {
$sub_tabs = &$tab2['sub_tabs'];
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminCEContent'));
$tab['current'] = true;
$tab['href'] = $link->getAdminLink('AdminCEContent');
$sub_tabs[] = $tab;
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminCmsContent'));
$tab['current'] = '';
$tab['href'] = $link->getAdminLink('AdminCmsContent');
$sub_tabs[] = $tab;
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminProducts'));
$tab['current'] = '';
$tab['href'] = $link->getAdminLink('AdminProducts');
$sub_tabs[] = $tab;
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminCategories'));
$tab['current'] = '';
$tab['href'] = $link->getAdminLink('AdminCategories');
$sub_tabs[] = $tab;
if ($display_manufacturers) {
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminManufacturers'));
$tab['current'] = '';
$tab['href'] = $link->getAdminLink('AdminManufacturers');
$sub_tabs[] = $tab;
}
if ($display_suppliers) {
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminSuppliers'));
$tab['current'] = '';
$tab['href'] = $link->getAdminLink('AdminSuppliers');
$sub_tabs[] = $tab;
}
return;
}
}
}
}
}
}
public function initToolBarTitle()
{
$this->page_header_toolbar_title = $this->l('Place Content Anywhere');
$this->context->smarty->assign('icon', 'icon-list');
$this->toolbar_title[] = $this->l('Contents List');
}
public function initPageHeaderToolbar()
{
if (empty($this->display)) {
$this->page_header_toolbar_btn['addce_content'] = [
'href' => self::$currentIndex . '&addce_content&token=' . $this->token,
'desc' => $this->trans('Add new', [], 'Admin.Actions'),
'icon' => 'process-icon-new',
];
}
parent::initPageHeaderToolbar();
}
public function initContent()
{
$this->context->smarty->assign('current_tab_level', 3);
return parent::initContent();
}
public function renderList()
{
$this->addRowAction('edit');
$this->addRowAction('delete');
return parent::renderList();
}
public function renderForm()
{
$col = count(Language::getLanguages(false, false, true)) > 1 ? 9 : 7;
version_compare(_PS_VERSION_, '1.7.8', '<') or $col--;
$this->fields_form = [
'legend' => [
'title' => $this->l('Content'),
'icon' => 'icon-edit',
],
'input' => [
[
'type' => 'text',
'label' => $this->trans('Title', [], 'Admin.Global'),
'name' => 'title',
'lang' => true,
'col' => $col,
],
[
'type' => 'text',
'label' => $this->trans('Position', [], 'Admin.Global'),
'name' => 'hook',
'required' => true,
'col' => 3,
],
[
'type' => 'textarea',
'label' => $this->l('Content'),
'name' => 'content',
'lang' => true,
'col' => $col,
],
[
'type' => 'switch',
'label' => $this->trans('Displayed', [], 'Admin.Global'),
'name' => 'active',
'required' => false,
'is_bool' => true,
'values' => [
[
'id' => 'active_on',
'value' => 1,
'label' => $this->trans('Enabled', [], 'Admin.Global'),
],
[
'id' => 'active_off',
'value' => 0,
'label' => $this->trans('Disabled', [], 'Admin.Global'),
],
],
],
],
'submit' => [
'title' => $this->trans('Save', [], 'Admin.Actions'),
],
'buttons' => [
'save_and_stay' => [
'type' => 'submit',
'title' => $this->trans('Save and stay', [], 'Admin.Actions'),
'icon' => 'process-icon-save',
'name' => 'submitAddce_contentAndStay',
'class' => 'btn btn-default pull-right',
],
],
];
if (Shop::isFeatureActive()) {
$this->fields_form['input'][] = [
'type' => 'shop',
'label' => $this->trans('Shop association', [], 'Admin.Global'),
'name' => 'checkBoxShopAsso',
];
}
return parent::renderForm();
}
protected function trans($id, array $parameters = [], $domain = null, $locale = null)
{
return empty($this->translator) ? $this->l($id) : parent::trans($id, $parameters, $domain, $locale);
}
protected function l($string, $module = 'creativeelements', $addslashes = false, $htmlentities = true)
{
$str = Translate::getModuleTranslation($module, $string, '', null, $addslashes || !$htmlentities);
return $htmlentities ? $str : call_user_func('stripslashes', $str);
}
}

View File

@@ -0,0 +1,378 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class AdminCEEditorController extends ModuleAdminController
{
public $name = 'AdminCEEditor';
public $display_header = false;
public $content_only = true;
/** @var CE\UId */
protected $uid;
public function initShopContext()
{
require_once _PS_MODULE_DIR_ . 'creativeelements/classes/wrappers/UId.php';
Tools::getIsset('uid') && $this->uid = CE\UId::parse(Tools::getValue('uid'));
if (!empty($this->uid->id_shop) && $this->uid->id_type > CE\UId::TEMPLATE && Shop::getContext() > 1) {
${'_POST'}['setShopContext'] = 's-' . $this->uid->id_shop;
}
parent::initShopContext();
}
public function init()
{
if (isset($this->context->cookie->last_activity)) {
if ($this->context->cookie->last_activity + 900 < time()) {
$this->context->employee->logout();
} else {
$this->context->cookie->last_activity = time();
}
}
if (!isset($this->context->employee) || !$this->context->employee->isLoggedBack()) {
if (isset($this->context->employee)) {
$this->context->employee->logout();
}
Tools::redirectAdmin($this->context->link->getAdminLink('AdminLogin') . '&redirect=' . $this->controller_name);
}
$this->initProcess();
}
public function initCursedPage()
{
if ($this->ajax) {
CE\wp_send_json_error('token_expired');
}
parent::initCursedPage();
}
public function initProcess()
{
header('Cache-Control: no-store, no-cache');
$this->ajax = Tools::getIsset('ajax');
$this->action = Tools::getValue('action', '');
$this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, $this->id);
if (Shop::isFeatureActive() && $this->uid && !$this->ajax) {
$domain = Tools::getShopProtocol() === 'http://' ? 'domain' : 'domain_ssl';
if ($this->context->shop->$domain != $_SERVER['HTTP_HOST'] && $this->viewAccess()) {
CE\update_post_meta(0, 'cookie', $this->context->cookie->getAll());
$id_shop = $this->uid->id_shop ?: $this->uid->getDefaultShopId();
Tools::redirectAdmin(
$this->context->link->getModuleLink('creativeelements', 'preview', [
'id_employee' => $this->context->employee->id,
'adtoken' => Tools::getAdminTokenLite('AdminCEEditor'),
'redirect' => urlencode($_SERVER['REQUEST_URI']),
], true, $this->uid->id_lang, $id_shop)
);
}
}
CE\Plugin::instance();
}
public function postProcess()
{
$process = 'process' . Tools::toCamelCase($this->action, true);
if ($this->ajax) {
method_exists($this, "ajax$process") && $this->{"ajax$process"}();
if ('elementor_ajax' === $this->action) {
CE\add_action('elementor/ajax/register_actions', [$this, 'registerAjaxActions']);
}
CE\do_action('wp_ajax_' . $this->action);
} elseif ($this->action && method_exists($this, $process)) {
// Call process
return $this->$process();
}
return false;
}
public function initContent()
{
$this->viewAccess() or die(CE\Helper::transError('You do not have permission to view this.'));
empty($this->uid) && Tools::redirectAdmin($this->context->link->getAdminLink('AdminCEContent'));
CE\add_action('elementor/editor/before_enqueue_scripts', [$this, 'beforeEnqueueScripts']);
CE\Plugin::instance()->editor->init();
}
public function beforeEnqueueScripts()
{
$suffix = _PS_MODE_DEV_ ? '' : '.min';
// Enqueue CE assets
CE\wp_enqueue_style('ce-editor', _CE_ASSETS_URL_ . 'css/editor-ce.css', [], _CE_VERSION_);
CE\wp_register_script('ce-editor', _CE_ASSETS_URL_ . 'js/editor-ce.js', [], _CE_VERSION_, true);
CE\wp_localize_script('ce-editor', 'baseDir', __PS_BASE_URI__);
CE\wp_enqueue_script('ce-editor');
// Enqueue TinyMCE assets
CE\wp_enqueue_style('material-icons', _CE_ASSETS_URL_ . 'lib/material-icons/material-icons.css', [], '1.012');
CE\wp_enqueue_style('tinymce-theme', _CE_ASSETS_URL_ . "lib/tinymce/ps-theme{$suffix}.css", [], _CE_VERSION_);
CE\wp_register_script('tinymce', _PS_JS_DIR_ . 'tiny_mce/tinymce.min.js', ['jquery'], false, true);
CE\wp_register_script('tinymce-inc', _CE_ASSETS_URL_ . 'lib/tinymce/tinymce.inc.js', ['tinymce'], _CE_VERSION_, true);
CE\wp_localize_script('tinymce', 'baseAdminDir', __PS_BASE_URI__ . basename(_PS_ADMIN_DIR_) . '/');
CE\wp_localize_script('tinymce', 'iso_user', CE\get_locale());
CE\wp_enqueue_script('tinymce-inc');
}
public function processBackToPsEditor()
{
if (CE\current_user_can('edit', $this->uid)) {
CE\Plugin::instance()->db->setIsElementorPage($this->uid, false);
}
Tools::redirectAdmin($_SERVER['HTTP_REFERER']);
}
public function processAddFooterProduct()
{
if (!$this->uid->id || $this->uid->id_type != CE\UId::PRODUCT) {
Tools::redirectAdmin($_SERVER['HTTP_REFERER']);
}
$content = new CEContent();
$content->hook = 'displayFooterProduct';
$content->id_product = $this->uid->id;
$content->active = true;
$content->title = [];
$content->content = [];
foreach (Language::getLanguages(false) as $lang) {
$content->title[$lang['id_lang']] = 'Product Footer #' . $this->uid->id;
}
$content->save();
$uid = new CE\UId($content->id, CE\UId::CONTENT, $this->uid->id_lang, $this->uid->id_shop);
Tools::redirectAdmin(
$this->context->link->getAdminLink('AdminCEEditor') . "&uid=$uid&footerProduct={$content->id_product}"
);
}
public function processAddMaintenance()
{
if (!$uid = Tools::getValue('uid')) {
Tools::redirectAdmin($_SERVER['HTTP_REFERER']);
}
$content = new CEContent();
$content->hook = 'displayMaintenance';
$content->active = true;
$content->title = [];
$content->content = [];
foreach (Language::getLanguages(false) as $lang) {
$id_lang = $lang['id_lang'];
$content->title[$id_lang] = 'Maintenance';
$content->content[$id_lang] = (string) Configuration::get('PS_MAINTENANCE_TEXT', $id_lang);
}
$content->save();
$id_lang = Tools::substr($uid, -4, 2);
$id_shop = Tools::substr($uid, -2);
$uid = new CE\UId($content->id, CE\UId::CONTENT, $id_lang, $id_shop);
Tools::redirectAdmin($this->context->link->getAdminLink('AdminCEEditor') . "&uid=$uid");
}
public function ajaxProcessHeartbeat()
{
$response = [];
$data = isset(${'_POST'}['data']) ? (array) ${'_POST'}['data'] : [];
$screen_id = Tools::getValue('screen_id', 'front');
empty($data) or $response = CE\apply_filters('heartbeat_received', $response, $data, $screen_id);
$response = CE\apply_filters('heartbeat_send', $response, $screen_id);
CE\do_action('heartbeat_tick', $response, $screen_id);
$response['server_time'] = time();
CE\wp_send_json($response);
}
public function ajaxProcessAutocompleteLink()
{
$context = Context::getContext();
$db = Db::getInstance();
$ps = _DB_PREFIX_;
$search = $db->escape(Tools::getValue('search'));
$id_lang = (int) $context->language->id;
$id_shop = (int) $context->shop->id;
$limit = 10;
$rows = $db->executeS("(
SELECT m.`id_meta` AS `ID`, ml.`title`, m.`page` AS `permalink`, 'Page' AS `info` FROM `{$ps}meta` AS m
LEFT JOIN `{$ps}meta_lang` AS ml ON m.`id_meta` = ml.`id_meta`
WHERE ml.`id_lang` = $id_lang AND ml.`id_shop` = $id_shop AND ml.`title` LIKE '%$search%' LIMIT $limit
) UNION (
SELECT `id_cms` AS `ID`, `meta_title` AS `title`, `link_rewrite` AS `permalink`, 'CMS' AS `info` FROM `{$ps}cms_lang`
WHERE `id_lang` = $id_lang AND `id_shop` = $id_shop AND `meta_title` LIKE '%$search%' LIMIT $limit
) UNION (
SELECT `id_cms_category` AS `ID`, `name` AS `title`, `link_rewrite` AS `permalink`, 'CMS Category' AS `info` FROM `{$ps}cms_category_lang`
WHERE `id_lang` = $id_lang AND `id_shop` = $id_shop AND `name` LIKE '%$search%' LIMIT $limit
) UNION (
SELECT `id_product` AS `ID`, `name` AS `title`, '' AS `permalink`, 'Product' AS `info` FROM `{$ps}product_lang`
WHERE `id_lang` = $id_lang AND `id_shop` = $id_shop AND `name` LIKE '%$search%' LIMIT $limit
) UNION (
SELECT `id_category` AS `ID`, `name` AS `title`, `link_rewrite` AS `permalink`, 'Category' AS `info` FROM `{$ps}category_lang`
WHERE `id_lang` = $id_lang AND `id_shop` = $id_shop AND `name` LIKE '%$search%' LIMIT $limit
) UNION (
SELECT `id_manufacturer` AS `ID`, `name` AS `title`, '' AS `permalink`, 'Brand' AS `info` FROM `{$ps}manufacturer`
WHERE `active` = 1 AND `name` LIKE '%$search%' LIMIT $limit
) UNION (
SELECT `id_supplier` AS `ID`, `name` AS `title`, '' AS `permalink`, 'Supplier' AS `info` FROM `{$ps}supplier`
WHERE `active` = 1 AND `name` LIKE '%$search%' LIMIT $limit
)");
if ($rows) {
foreach ($rows as &$row) {
switch ($row['info']) {
case 'CMS':
$row['permalink'] = $context->link->getCMSLink($row['ID'], $row['permalink'], null, $id_lang, $id_shop);
break;
case 'CMS Category':
$row['permalink'] = $context->link->getCMSCategoryLink($row['ID'], $row['permalink'], $id_lang, $id_shop);
break;
case 'Product':
$product = new Product($row['ID'], false, $id_lang, $id_shop);
$row['permalink'] = $context->link->getProductLink($product);
break;
case 'Category':
$row['permalink'] = $context->link->getCategoryLink($row['ID'], $row['permalink'], $id_lang, null, $id_shop);
break;
case 'Brand':
$row['permalink'] = $context->link->getManufacturerLink($row['ID'], Tools::link_rewrite($row['title']), $id_lang, $id_shop);
break;
case 'Supplier':
$row['permalink'] = $context->link->getSupplierLink($row['ID'], Tools::link_rewrite($row['title']), $id_lang, $id_shop);
break;
default:
$row['permalink'] = $context->link->getPageLink($row['permalink'], null, $id_lang, null, false, $id_shop);
break;
}
$row['info'] = CE\__($row['info']);
}
}
die(json_encode($rows));
}
public function registerAjaxActions($ajax_manager)
{
$ajax_manager->registerAjaxAction('get_language_content', [$this, 'ajaxGetLanguageContent']);
$ajax_manager->registerAjaxAction('get_products_by_id', [$this, 'ajaxGetProductsById']);
CE\add_filter('elementor/api/get_templates/body_args', [$this, 'filterApiGetTemplateArgs']);
CE\add_filter('elementor/api/get_templates/content', [$this, 'filterApiGetTemplateContent']);
CE\add_action('elementor/document/after_save', [$this, 'onAfterSaveDocument']);
}
public function ajaxGetLanguageContent($request)
{
$data = null;
if (!empty($request['uid']) && $data = CE\get_post_meta($request['uid'], '_elementor_data', true)) {
CE\Plugin::$instance->db->iterateData($data, function ($element) {
$element['id'] = CE\Utils::generateRandomString();
return $element;
});
}
return is_array($data) ? $data : [];
}
public function ajaxGetProductsById($request)
{
if (empty($request['ids'])) {
return [];
}
$context = Context::getContext();
$results = [];
$ids = implode(',', array_map('intval', $request['ids']));
$items = Db::getInstance()->executeS('
SELECT p.`id_product`, pl.`link_rewrite`, p.`reference`, pl.`name`, image_shop.`id_image` id_image FROM `' . _DB_PREFIX_ . 'product` p
' . Shop::addSqlAssociation('product', 'p') . '
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (pl.id_product = p.id_product AND pl.id_lang = ' . (int) $context->language->id . Shop::addSqlRestrictionOnLang('pl') . ')
LEFT JOIN `' . _DB_PREFIX_ . 'image_shop` image_shop
ON (image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop=' . (int) $context->shop->id . ')
LEFT JOIN `' . _DB_PREFIX_ . 'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = ' . (int) $context->language->id . ')
WHERE p.id_product IN (' . $ids . ') GROUP BY p.id_product
');
if ($items) {
$protocol = Tools::getShopProtocol();
$image_size = ImageType::getFormattedName('home');
foreach ($items as &$item) {
$results[] = [
'id' => $item['id_product'],
'name' => $item['name'] . (!empty($item['reference']) ? ' (ref: ' . $item['reference'] . ')' : ''),
'ref' => (!empty($item['reference']) ? $item['reference'] : ''),
'image' => str_replace('http://', $protocol, $context->link->getImageLink($item['link_rewrite'], $item['id_image'], $image_size)),
];
}
}
return $results;
}
public function filterApiGetTemplateArgs($body_args)
{
$id_shop = Configuration::getGlobalValue('PS_SHOP_DEFAULT');
$license_key = Configuration::getGlobalValue('CE_LICENSE');
if ($license_key) {
$body_args['license'] = $license_key;
$body_args['domain'] = Tools::getShopProtocol() === 'http://'
? ShopUrl::getMainShopDomain($id_shop)
: ShopUrl::getMainShopDomainSSL($id_shop)
;
}
return $body_args;
}
public function filterApiGetTemplateContent($content)
{
if (isset($content['error'])) {
if (isset($content['code']) && 419 == $content['code']) {
Configuration::updateGlobalValue('CE_LICENSE', '');
}
CE\wp_send_json_error($content['error']);
}
return $content;
}
public function onAfterSaveDocument($document)
{
// Set edit mode to builder only at save
CE\Plugin::$instance->db->setIsElementorPage($document->getPost()->uid);
}
}

View File

@@ -0,0 +1,234 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
require_once _PS_MODULE_DIR_ . 'creativeelements/classes/CEFont.php';
class AdminCEFontsController extends ModuleAdminController
{
public $bootstrap = true;
public $table = 'ce_font';
public $identifier = 'id_ce_font';
public $className = 'CEFont';
protected $ce_font;
protected $_defaultOrderBy = 'family';
public function __construct()
{
parent::__construct();
$this->fields_list = [
'id_ce_font' => [
'title' => $this->trans('ID', [], 'Admin.Global'),
'class' => 'fixed-width-xs',
'align' => 'center',
],
'family' => [
'title' => $this->l('Font Name'),
],
'preview' => [
'title' => $this->l('Preview'),
'class' => 'ce-font-preview',
'orderby' => false,
'search' => false,
],
];
$this->bulk_actions = [
'delete' => [
'text' => $this->l('Delete'),
'icon' => 'icon-trash text-danger',
'confirm' => $this->trans('Delete selected items?', [], 'Admin.Notifications.Info'),
],
];
}
public function init()
{
if ($id_ce_font = (int) Tools::getValue('id_ce_font')) {
$this->ce_font = new CEFont($id_ce_font);
}
parent::init();
}
public function initToolBarTitle()
{
$this->context->smarty->assign('icon', 'icon-list');
$this->toolbar_title[] = $this->l(
'add' === $this->display ? 'Add New Font' : ('edit' === $this->display ? 'Edit Font' : 'Fonts List')
);
}
public function initPageHeaderToolbar()
{
if ('add' !== $this->display && 'edit' !== $this->display) {
$this->page_header_toolbar_btn['addce_font'] = [
'icon' => 'process-icon-new',
'desc' => $this->trans('Add new', [], 'Admin.Actions'),
'href' => self::$currentIndex . '&addce_font&token=' . $this->token,
];
}
parent::initPageHeaderToolbar();
}
public function initModal()
{
// Prevent modals
}
protected function _childValidation()
{
if (Validate::isImageTypeName($family = Tools::getValue('family')) &&
CEFont::familyAlreadyExists($family, Tools::getValue('id_ce_font'))
) {
$this->errors[] = $this->trans('This name already exists.', [], 'Admin.Design.Notification');
}
}
public function validateRules($class_name = false)
{
parent::validateRules($class_name);
if (empty($this->errors)) {
$font_face = &${'_POST'}['font_face'];
if (!empty($_FILES['font_face']['name'])) {
$upload_error = [];
$fonts_url = 'modules/creativeelements/views/fonts/';
$fonts_dir = _PS_ROOT_DIR_ . '/' . $fonts_url;
foreach ($_FILES['font_face']['name'] as $i => &$font_name) {
$tmp_name = &$_FILES['font_face']['tmp_name'][$i];
$error_code = &$_FILES['font_face']['error'][$i];
foreach (CEFont::getAllowedExt() as $ext) {
if (empty($font_name[$ext]['file']) || empty($tmp_name[$ext]['file'])) {
continue;
}
if (empty($error_code[$ext]['file']) &&
Tools::strtolower(pathinfo($font_name[$ext]['file'], PATHINFO_EXTENSION)) === $ext &&
move_uploaded_file($tmp_name[$ext]['file'], $fonts_dir . $font_name[$ext]['file'])
) {
$font_face[$i][$ext]['url'] = $fonts_url . $font_name[$ext]['file'];
} else {
$font_face[$i][$ext]['url'] = '';
$upload_error[] = $font_name[$ext]['file'];
}
}
}
if ($upload_error) {
$this->errors[] = $this->trans('An error occurred during the file upload process.', [], 'Admin.Notifications.Error') .
' (' . implode(', ', $upload_error) . ')';
}
}
${'_POST'}['files'] = json_encode($font_face);
}
}
public function setMedia($isNewTheme = false)
{
parent::setMedia($isNewTheme);
if ($font_face = (string) $this->ce_font) {
$font_face = str_replace('{{BASE}}', $this->context->link->getMediaLink(__PS_BASE_URI__), $font_face);
$font_face = str_replace(["\n", "\t"], '', $font_face);
$this->css_files['data:text/css,' . $font_face] = 'all';
}
$this->css_files[_MODULE_DIR_ . 'creativeelements/views/css/custom-fonts.css?v=' . _CE_VERSION_] = 'all';
$this->js_files[] = _MODULE_DIR_ . 'creativeelements/views/js/custom-fonts.js?v=' . _CE_VERSION_;
}
public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
{
parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop);
// Add font previews
if (!empty($this->_list)) {
foreach ($this->_list as &$row) {
$row['id'] = $row['id_ce_font'];
$row['preview'] = new CEFont($row['id']);
}
}
}
public function renderList()
{
$this->addRowAction('edit');
$this->addRowAction('delete');
return parent::renderList();
}
public function renderForm()
{
$this->fields_form = [
'legend' => [
'title' => $this->l('Font'),
'icon' => 'icon-font',
],
'input' => [
[
'type' => 'text',
'label' => $this->l('Font Name'),
'name' => 'family',
'placeholder' => $this->l('Enter Font Family'),
'required' => true,
'col' => 8,
],
[
'type' => 'hidden',
'name' => 'files',
],
[
'type' => 'html',
'label' => $this->l('Font Files'),
'name' => 'add_custom_font',
'html_content' => CESmarty::capture(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_add_custom_font'),
'col' => 8,
],
],
'submit' => [
'title' => $this->trans('Save', [], 'Admin.Actions'),
],
'buttons' => [
'save_and_stay' => [
'type' => 'submit',
'title' => $this->trans('Save and stay', [], 'Admin.Actions'),
'icon' => 'process-icon-save',
'name' => 'submitAddce_fontAndStay',
'class' => 'btn btn-default pull-right',
],
],
];
return parent::renderForm();
}
protected function trans($id, array $parameters = [], $domain = null, $locale = null)
{
return empty($this->translator) ? $this->l($id) : parent::trans($id, $parameters, $domain, $locale);
}
protected function l($string, $module = 'creativeelements', $addslashes = false, $htmlentities = true)
{
$str = Translate::getModuleTranslation($module, $string, '', null, $addslashes || !$htmlentities);
return $htmlentities ? $str : call_user_func('stripslashes', $str);
}
}

View File

@@ -0,0 +1,510 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class AdminCESettingsController extends ModuleAdminController
{
protected $activate_url = 'https://pagebuilder.webshopworks.com/?connect=activate';
protected $viewportChanged = false;
protected $clearCss = false;
public function __construct()
{
$this->bootstrap = true;
$this->className = 'CESettings';
$this->table = 'configuration';
parent::__construct();
$this->fields_options['general_settings'] = [
'icon' => 'icon-cog',
'title' => $this->l('General Settings'),
'fields' => [
'elementor_frontend_edit' => [
'title' => $this->l('Show Edit Icon on Frontend'),
'desc' => $this->l('Displays an edit icon on frontend while employee has active session. By clicking on this icon the live editor will open.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
'default' => '1',
],
'elementor_max_revisions' => [
'title' => $this->l('Limit Revisions'),
'desc' => $this->l('Sets the maximum number of revisions per content.'),
'validation' => 'isUnsignedInt',
'cast' => 'intval',
'type' => 'select',
'identifier' => 'value',
'list' => [
['value' => 0, 'name' => $this->l('Disable Revision History')],
['value' => 1, 'name' => 1],
['value' => 2, 'name' => 2],
['value' => 3, 'name' => 3],
['value' => 4, 'name' => 4],
['value' => 5, 'name' => 5],
['value' => 10, 'name' => 10],
['value' => 15, 'name' => 15],
['value' => 20, 'name' => 20],
['value' => 25, 'name' => 25],
['value' => 30, 'name' => 30],
],
],
'elementor_disable_color_schemes' => [
'title' => $this->l('Disable Default Colors'),
'desc' => $this->l('If you prefer to inherit the colors from your theme, you can disable this feature.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
'default' => '0',
],
'elementor_disable_typography_schemes' => [
'title' => $this->l('Disable Default Fonts'),
'desc' => $this->l('If you prefer to inherit the fonts from your theme, you can disable this feature here.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
'default' => '0',
],
],
'submit' => [
'title' => $this->l('Save'),
],
];
$this->fields_options['style_settings'] = [
'icon' => 'icon-adjust',
'title' => $this->l('Style Settings'),
'fields' => [
'elementor_default_generic_fonts' => [
'title' => $this->l('Default Generic Fonts'),
'desc' => $this->l('The list of fonts used if the chosen font is not available.'),
'cast' => 'strval',
'type' => 'text',
'class' => 'fixed-width-xxl',
],
'elementor_container_width' => [
'title' => $this->l('Content Width'),
'desc' => $this->l('Sets the default width of the content area (Default: 1140)'),
'suffix' => 'px',
'validation' => 'isUnsignedInt',
'cast' => 'intval',
'type' => 'text',
'class' => 'fixed-width-sm',
],
'elementor_space_between_widgets' => [
'title' => $this->l('Widgets Space'),
'desc' => $this->l('Sets the default space between widgets (Default: 20)'),
'suffix' => 'px',
'validation' => 'isUnsignedInt',
'cast' => 'intval',
'type' => 'text',
'class' => 'fixed-width-sm',
],
'elementor_stretched_section_container' => [
'title' => $this->l('Stretched Section Fit To'),
'desc' => $this->l('Enter parent element selector to which stretched sections will fit to (e.g. #primary / .wrapper / main etc). Leave blank to fit to page width.'),
'cast' => 'strval',
'type' => 'text',
'class' => 'fixed-width-xxl',
],
'elementor_page_title_selector' => [
'title' => $this->l('Page Title Selector'),
'desc' => sprintf(
$this->l("You can hide the title at document settings. This works for themes that have ”%s” selector. If your theme's selector is different, please enter it above."),
'header.page-header'
),
'cast' => 'strval',
'type' => 'text',
],
'elementor_page_wrapper_selector' => [
'title' => $this->l('Content Wrapper Selector'),
'desc' => sprintf(
$this->l("You can clear margin, padding, max-width from content wrapper at document settings. This works for themes that have ”%s” selector. If your theme's selector is different, please enter it above."),
'#content, #wrapper, #wrapper .container'
),
'cast' => 'strval',
'type' => 'text',
],
'elementor_viewport_lg' => [
'title' => $this->l('Tablet Breakpoint'),
'desc' => sprintf($this->l('Sets the breakpoint between desktop and tablet devices. Below this breakpoint tablet layout will appear (Default: %dpx).'), 1025),
'suffix' => 'px',
'validation' => 'isUnsignedInt',
'cast' => 'intval',
'type' => 'text',
'class' => 'fixed-width-sm',
],
'elementor_viewport_md' => [
'title' => $this->l('Mobile Breakpoint'),
'desc' => sprintf($this->l('Sets the breakpoint between tablet and mobile devices. Below this breakpoint mobile layout will appear (Default: %dpx).'), 768),
'suffix' => 'px',
'validation' => 'isUnsignedInt',
'cast' => 'intval',
'type' => 'text',
'class' => 'fixed-width-sm',
],
'elementor_global_image_lightbox' => [
'title' => $this->l('Image Lightbox'),
'desc' => $this->l('Open all image links in a lightbox popup window. The lightbox will automatically work on any link that leads to an image file.'),
'hint' => $this->l('You can customize the lightbox design by going to: Top-left hamburger icon > Global Settings > Lightbox.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
'default' => '1',
],
],
'submit' => [
'title' => $this->l('Save'),
],
];
$this->fields_options['advanced_settings'] = [
'class' => 'ce-adv-settings',
'icon' => 'icon-cogs',
'title' => $this->l('Advanced Settings'),
'info' => CESmarty::sprintf(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_alert', 'warning', $this->l(
'Do not change these options without experience, incorrect settings might break your site.'
)),
'fields' => [
'elementor_css_print_method' => [
'title' => $this->l('CSS Print Method'),
'desc' => $this->l('Use external CSS files for all generated stylesheets. Choose this setting for better performance (recommended).'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => [
['value' => 'external', 'name' => $this->l('External File')],
['value' => 'internal', 'name' => $this->l('Internal Embedding')],
],
],
'elementor_edit_buttons' => [
'title' => $this->l('Editing Handles'),
'desc' => $this->l('Show editing handles when hovering over the element edit button.'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => [
['value' => '', 'name' => $this->l('Hide')],
['value' => 'on', 'name' => $this->l('Show')],
],
],
'elementor_exclude_modules' => [
'title' => $this->l('Exclude Categories from Module widget'),
'type' => 'multiselect',
'class' => 'chosen',
'cast' => 'json_encode',
'auto_value' => false,
'identifier' => 'value',
'list' => [
['value' => 'administration', 'name' => $this->trans('Administration', [], 'Admin.Modules.Feature')],
['value' => 'advertising_marketing', 'name' => $this->trans('Advertising & Marketing', [], 'Admin.Modules.Feature')],
['value' => 'analytics_stats', 'name' => $this->trans('Analytics & Stats', [], 'Admin.Modules.Feature')],
['value' => 'billing_invoicing', 'name' => $this->trans('Taxes & Invoicing', [], 'Admin.Modules.Feature')],
['value' => 'checkout', 'name' => $this->trans('Checkout', [], 'Admin.Modules.Feature')],
['value' => 'content_management', 'name' => $this->trans('Content Management', [], 'Admin.Modules.Feature')],
['value' => 'customer_reviews', 'name' => $this->trans('Customer Reviews', [], 'Admin.Modules.Feature')],
['value' => 'export', 'name' => $this->trans('Export', [], 'Admin.Actions')],
['value' => 'front_office_features', 'name' => $this->trans('Front office Features', [], 'Admin.Modules.Feature')],
['value' => 'i18n_localization', 'name' => $this->trans('Internationalization & Localization', [], 'Admin.Modules.Feature')],
['value' => 'merchandizing', 'name' => $this->trans('Merchandising', [], 'Admin.Modules.Feature')],
['value' => 'migration_tools', 'name' => $this->trans('Migration Tools', [], 'Admin.Modules.Feature')],
['value' => 'payments_gateways', 'name' => $this->trans('Payments & Gateways', [], 'Admin.Modules.Feature')],
['value' => 'payment_security', 'name' => $this->trans('Site certification & Fraud prevention', [], 'Admin.Modules.Feature')],
['value' => 'pricing_promotion', 'name' => $this->trans('Pricing & Promotion', [], 'Admin.Modules.Feature')],
['value' => 'quick_bulk_update', 'name' => $this->trans('Quick / Bulk update', [], 'Admin.Modules.Feature')],
['value' => 'seo', 'name' => $this->trans('SEO', [], 'Admin.Catalog.Feature')],
['value' => 'shipping_logistics', 'name' => $this->trans('Shipping & Logistics', [], 'Admin.Modules.Feature')],
['value' => 'slideshows', 'name' => $this->trans('Slideshows', [], 'Admin.Modules.Feature')],
['value' => 'smart_shopping', 'name' => $this->trans('Comparison site & Feed management', [], 'Admin.Modules.Feature')],
['value' => 'market_place', 'name' => $this->trans('Marketplace', [], 'Admin.Modules.Feature')],
['value' => 'others', 'name' => $this->trans('Other Modules', [], 'Admin.Modules.Feature')],
['value' => 'mobile', 'name' => $this->trans('Mobile', [], 'Admin.Global')],
['value' => 'dashboard', 'name' => $this->trans('Dashboard', [], 'Admin.Global')],
['value' => 'emailing', 'name' => $this->trans('Emailing & SMS', [], 'Admin.Modules.Feature')],
['value' => 'social_networks', 'name' => $this->trans('Social Networks', [], 'Admin.Modules.Feature')],
['value' => 'social_community', 'name' => $this->trans('Social & Community', [], 'Admin.Modules.Feature')],
],
],
'elementor_load_fontawesome' => [
'title' => $this->l('Load FontAwesome Library'),
'desc' => $this->l('FontAwesome gives you scalable vector icons that can instantly be customized - size, color, drop shadow, and anything that can be done with the power of CSS.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
'default' => '1',
],
'elementor_load_waypoints' => [
'title' => $this->l('Load Waypoints Library'),
'desc' => $this->l('Waypoints library is the easiest way to trigger a function when you scroll to an element.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
'default' => '1',
],
'elementor_load_slick' => [
'title' => $this->l('Load Slick Library'),
'desc' => $this->l('Slick is a jQuery plugin for creating fully customizable, responsive and mobile friendly carousels/sliders that work with any html elements.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
'default' => '1',
],
],
'submit' => [
'title' => $this->l('Save'),
],
];
$this->fields_options['experiments'] = [
'class' => 'ce-experiments',
'icon' => 'icon-magic',
'title' => $this->l('Experiments'),
'info' => CESmarty::sprintf(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_alert', 'info', $this->l(
"Access new and experimental features from Creative Elements before they're officially released. As these features are still in development, they are likely to change, evolve or even be removed altogether."
)),
'fields' => [
'elementor_remove_hidden' => [
'title' => $this->l('Remove Hidden Elements'),
'desc' => $this->l('When you hide elements on "Advanced tab / Responsive section" their markup will be removed from DOM.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
],
'elementor_visibility' => [
'title' => $this->l('Visibility Section'),
'desc' => $this->l('If you would like to schedule elements or filter them by selected customer groups, then this feature will be handy. It will appear under Advanced tab.'),
'validation' => 'isBool',
'cast' => 'intval',
'type' => 'bool',
],
],
'submit' => [
'title' => $this->l('Save'),
],
];
}
public function initPageHeaderToolbar()
{
$this->page_header_toolbar_btn['license'] = [
'icon' => 'process-icon-file icon-file-text',
'desc' => $this->l('License'),
'js' => "$('#modal_license').modal()",
];
$this->page_header_toolbar_btn['regenerate-css'] = [
'icon' => 'process-icon-reload icon-rotate-right',
'desc' => $this->l('Regenerate CSS'),
'js' => '//' . Tools::safeOutput(
$this->l('Styles set in Creative Elements are saved in CSS files. Recreate those files, according to the most recent settings.')
),
];
if (Shop::getContext() === Shop::CONTEXT_SHOP) {
$this->page_header_toolbar_btn['replace-url'] = [
'icon' => 'process-icon-refresh',
'desc' => $this->l('Replace URL'),
'js' => "$('#modal_replace_url').modal()",
];
}
parent::initPageHeaderToolbar();
}
public function initModal()
{
$ce_license = Configuration::getGlobalValue('CE_LICENSE');
$this->modals[] = [
'modal_id' => 'modal_license',
'modal_class' => 'modal-md',
'modal_title' => $ce_license
? CESmarty::get(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_modal_license_status')
: $this->l('Activate License')
,
'modal_content' => CESmarty::sprintf(
_CE_TEMPLATES_ . 'admin/admin.tpl',
'ce_modal_license',
Tools::safeOutput($this->context->link->getAdminLink('AdminCESettings') . '&action=activate'),
$this->l(
$ce_license
? 'Your website is activated. Want to activate this website by a different license?'
: 'Please activate your license to get unlimited access to the template library.'
),
$this->l($ce_license ? 'Switch License' : 'Activate')
),
];
$this->modals[] = [
'modal_id' => 'modal_replace_url',
'modal_class' => 'modal-md',
'modal_title' => $this->l('Update Site Address (URL)'),
'modal_content' => CESmarty::sprintf(
_CE_TEMPLATES_ . 'admin/admin.tpl',
'ce_modal_replace_url',
$this->l('It is strongly recommended that you backup your database before using Replace URL.'),
$this->l('http://old-url.com'),
$this->l('http://new-url.com'),
$this->l('Enter your old and new URLs for your PrestaShop installation, to update all Creative Elements data (Relevant for domain transfers or move to \'HTTPS\').'),
$this->l('Replace URL')
),
];
}
protected function processActivate()
{
$url = $this->context->link->getAdminLink('AdminCESettings');
if (Tools::getIsset('license')) {
Configuration::updateGlobalValue('CE_LICENSE', Tools::getValue('license'));
$url .= '#license';
} else {
list($p, $r) = explode('://', CE\wp_referer());
$encode = 'base64_encode';
$url = $this->activate_url . '&' . http_build_query([
'response_type' => 'code',
'client_id' => Tools::substr($encode(_COOKIE_KEY_), 0, 32),
'auth_secret' => rtrim($encode("$r?" . Tools::passwdGen(23 - Tools::strlen($r))), '='),
'state' => Tools::substr($encode($this->module->module_key), 0, 12),
'redirect_uri' => urlencode($url),
]);
}
Tools::redirectAdmin($url);
}
public function setMedia($isNewTheme = false)
{
parent::setMedia($isNewTheme);
$this->css_files[_MODULE_DIR_ . 'creativeelements/views/css/settings.css?v=' . _CE_VERSION_] = 'all';
$this->js_files[] = _MODULE_DIR_ . 'creativeelements/views/js/settings.js?v=' . _CE_VERSION_;
}
protected function processUpdateOptions()
{
parent::processUpdateOptions();
if ($this->viewportChanged) {
CE\Plugin::instance();
CE\CoreXResponsiveXResponsive::compileStylesheetTemplates();
$this->clearCss = true;
}
empty($this->clearCss) or CE\Plugin::instance()->files_manager->clearCache();
}
protected function updateOptionElementorContainerWidth($val)
{
if (Configuration::get('elementor_container_width') != $val) {
Configuration::updateValue('elementor_container_width', $val);
$this->clearCss = true;
}
}
protected function updateOptionElementorPageTitleSelector($val)
{
$val = trim($val);
if (!empty($val) && Validate::isCleanHtml($val)) {
Configuration::updateValue('elementor_page_title_selector', $val);
} else {
$this->errors[] = $this->trans('Required field', [], 'Shop.Forms.Errors') . ': ' . $this->l('Page Title Selector');
}
}
protected function updateOptionElementorFullWidthSelector($val)
{
$val = trim($val);
if (!empty($val) && Validate::isCleanHtml($val)) {
Configuration::updateValue('elementor_full_width_selector', $val);
} else {
$this->errors[] = $this->trans('Required field', [], 'Shop.Forms.Errors') . ': ' . $this->l('Content Wrapper Selector');
}
}
protected function updateOptionElementorViewportLg($val)
{
if (Configuration::get('elementor_viewport_lg') != $val) {
Configuration::updateValue('elementor_viewport_lg', $val);
$this->viewportChanged = true;
}
}
protected function updateOptionElementorViewportMd($val)
{
if (Configuration::get('elementor_viewport_md') != $val) {
Configuration::updateValue('elementor_viewport_md', $val);
$this->viewportChanged = true;
}
}
protected function updateOptionElementorCssPrintMethod($val)
{
if (Configuration::get('elementor_css_print_method') != $val) {
Configuration::updateValue('elementor_css_print_method', $val);
$this->clearCss = true;
}
}
public function ajaxProcessRegenerateCss()
{
CE\Plugin::instance()->files_manager->clearCache();
CE\wp_send_json_success();
}
public function ajaxProcessReplaceUrl()
{
$from = trim(Tools::getValue('from'));
$to = trim(Tools::getValue('to'));
$is_valid_urls = filter_var($from, FILTER_VALIDATE_URL) && filter_var($to, FILTER_VALIDATE_URL);
if (!$is_valid_urls) {
CE\wp_send_json_error(CE\__("The `from` and `to` URL's must be a valid URL"));
}
if ($from === $to) {
CE\wp_send_json_error(CE\__("The `from` and `to` URL's must be different"));
}
$db = Db::getInstance();
$table = _DB_PREFIX_ . 'ce_meta';
$id = sprintf('%02d', $this->context->shop->id);
$old = str_replace('/', '\\\/', $from);
$new = str_replace('/', '\\\/', $to);
$result = $db->execute("
UPDATE $table SET `value` = REPLACE(`value`, '$old', '$new')
WHERE `name` = '_elementor_data' AND `id` LIKE '%$id' AND `value` <> '[]'
");
if (false === $result) {
CE\wp_send_json_error(CE\__('An error occurred'));
} else {
CE\wp_send_json_success(sprintf(CE\__('%d Rows Affected'), $db->affected_rows()));
}
}
protected function trans($id, array $parameters = [], $domain = null, $locale = null)
{
return empty($this->translator) ? $this->l($id) : parent::trans($id, $parameters, $domain, $locale);
}
protected function l($string, $module = 'creativeelements', $addslashes = false, $htmlentities = true)
{
$str = Translate::getModuleTranslation($module, $string, '', null, $addslashes || !$htmlentities);
return $htmlentities ? $str : call_user_func('stripslashes', $str);
}
}

View File

@@ -0,0 +1,415 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
require_once _PS_MODULE_DIR_ . 'creativeelements/classes/CETemplate.php';
class AdminCETemplatesController extends ModuleAdminController
{
public $bootstrap = true;
public $table = 'ce_template';
public $identifier = 'id_ce_template';
public $className = 'CETemplate';
protected $_defaultOrderBy = 'title';
public function __construct()
{
parent::__construct();
if ($type = Tools::getValue('type')) {
if ('all' == $type) {
unset($this->context->cookie->submitFilterce_template);
unset($this->context->cookie->cetemplatesce_templateFilter_type);
} else {
$this->context->cookie->submitFilterce_template = 1;
$this->context->cookie->cetemplatesce_templateFilter_type = $type;
}
}
$this->fields_options['import-template'] = [
'class' => 'ce-import-panel hide',
'icon' => 'icon-upload',
'title' => $this->l('Import Template'),
'description' => $this->l('Choose a JSON template file or a .zip archive of templates, and add them to the list of templates available in your library.'),
'fields' => [
'action' => [
'type' => 'hidden',
'value' => 'import_template',
'no_multishop_checkbox' => true,
],
'file' => [
'type' => 'file',
'title' => $this->l('Template file'),
'name' => 'file',
'no_multishop_checkbox' => true,
],
],
'submit' => [
'imgclass' => 'import',
'title' => $this->l('Import Now'),
],
];
$this->fields_list = [
'id_ce_template' => [
'title' => $this->trans('ID', [], 'Admin.Global'),
'class' => 'fixed-width-xs',
'align' => 'center',
],
'title' => [
'title' => $this->trans('Title', [], 'Admin.Global'),
],
'type' => [
'title' => $this->trans('Type', [], 'Admin.Catalog.Feature'),
'class' => 'fixed-width-lg',
'type' => 'select',
'list' => [
'page' => $this->l('Page'),
'section' => $this->l('Section'),
'header' => $this->l('Header'),
'footer' => $this->l('Footer'),
'page-index' => $this->l('Home Page'),
'page-contact' => $this->l('Contact Page'),
'product' => $this->l('Product Page'),
'product-quick-view' => $this->l('Quick View'),
'product-miniature' => $this->l('Product Miniature'),
'page-not-found' => $this->l('404 Page'),
],
'filter_key' => 'type',
],
'date_add' => [
'title' => $this->trans('Created on', [], 'Modules.Facetedsearch.Admin'),
'class' => 'fixed-width-lg',
'type' => 'datetime',
],
'date_upd' => [
'title' => $this->l('Modified on'),
'class' => 'fixed-width-lg',
'type' => 'datetime',
],
'active' => [
'title' => $this->trans('Active', [], 'Admin.Global'),
'class' => 'fixed-width-xs',
'align' => 'center',
'active' => 'status',
'type' => 'bool',
],
'shortcode' => [
'title' => $this->l('Shortcode'),
'class' => 'ce-shortcode',
'type' => 'editable',
'orderby' => false,
'search' => false,
],
];
$this->bulk_actions = [
'export' => [
'text' => $this->trans('Export', [], 'Admin.Actions'),
'icon' => 'icon-mail-forward',
],
'delete_divider' => [
'text' => 'divider',
],
'delete' => [
'text' => $this->l('Delete'),
'icon' => 'icon-trash text-danger',
'confirm' => $this->trans('Delete selected items?', [], 'Admin.Notifications.Info'),
],
];
$this->action_link = CESmarty::get(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_action_link');
}
public function processBulkExport()
{
$uids = [];
foreach ($this->boxes as $id) {
$uids[] = new CE\UId($id, CE\UId::TEMPLATE);
}
CE\Plugin::instance()->templates_manager->getSource('local')->exportMultipleTemplates($uids);
}
protected function processUpdateOptions()
{
// Process import template
CE\UId::$_ID = new CE\UId(0, CE\UId::TEMPLATE);
$res = CE\Plugin::instance()->templates_manager->directImportTemplate();
if ($res instanceof CE\WPError) {
$this->errors[] = $res->getMessage();
} elseif (isset($res[1]['template_id'])) {
// More templates
Tools::redirectAdmin($this->context->link->getAdminLink('AdminCETemplates') . '&conf=18');
} elseif (isset($res[0]['template_id'])) {
// Simple template
$id = Tools::substr($res[0]['template_id'], 0, -6);
Tools::redirectAdmin(
$this->context->link->getAdminLink('AdminCETemplates') . "&id_ce_template=$id&updatece_template&conf=18"
);
} else {
$this->errors[] = $this->l('Unknown error during import!');
}
}
public function ajaxProcessMigrate()
{
if ($ids = Tools::getValue('ids')) {
require_once _CE_PATH_ . 'classes/CEMigrate.php';
$done = [];
foreach ($ids as $id) {
CEMigrate::moveTemplate($id) && $done[] = (int) $id;
}
$res = CEMigrate::removeIds('template', $done);
die(json_encode($res));
}
}
public function initHeader()
{
parent::initHeader();
$id_lang = $this->context->language->id;
$link = $this->context->link;
$tabs = &$this->context->smarty->tpl_vars['tabs']->value;
$sections = [
'section',
'header',
'footer',
'product-quick-view',
'product-miniature',
];
foreach ($tabs as &$tab0) {
foreach ($tab0['sub_tabs'] as &$tab1) {
if ('AdminParentCEContent' === $tab1['class_name']) {
foreach ($tab1['sub_tabs'] as &$tab2) {
if ('AdminCETemplates' === $tab2['class_name']) {
$sub_tabs = &$tab2['sub_tabs'];
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminCETemplates'));
$new = Tools::getIsset('addce_template');
$href = $link->getAdminLink('AdminCETemplates');
$type = $this->context->cookie->cetemplatesce_templateFilter_type;
$tab['name'] = $this->l('Templates');
$tab['current'] = $new || (!in_array($type, ['section', 'page']) || !$type) && !$this->object;
$tab['href'] = "$href&type=all";
$sub_tabs[] = $tab;
$tab['name'] = $this->l('Page');
$tab['current'] = !$new && ($this->object ? !in_array($this->object->type, $sections) : 'page' === $type);
$tab['href'] = "$href&type=page";
$sub_tabs[] = $tab;
$tab['name'] = $this->l('Section');
$tab['current'] = !$new && ($this->object ? in_array($this->object->type, $sections) : 'section' === $type);
$tab['href'] = "$href&type=section";
$sub_tabs[] = $tab;
return;
}
}
}
}
}
}
public function initToolBarTitle()
{
$this->context->smarty->assign('icon', 'icon-list');
$this->toolbar_title[] = $this->l(
'add' === $this->display ? 'Add New Template' : ('edit' === $this->display ? 'Edit Template' : 'Templates List')
);
}
public function initPageHeaderToolbar()
{
if ('add' !== $this->display && 'edit' !== $this->display) {
$this->page_header_toolbar_btn['addce_template'] = [
'icon' => 'process-icon-new',
'desc' => $this->trans('Add new', [], 'Admin.Actions'),
'href' => self::$currentIndex . '&addce_template&token=' . $this->token,
];
$this->page_header_toolbar_btn['importce_template'] = [
'icon' => 'process-icon-import',
'desc' => $this->trans('Import', [], 'Admin.Actions'),
'href' => 'javascript:ceAdmin.onClickImport()',
];
}
parent::initPageHeaderToolbar();
}
public function initModal()
{
// Prevent modals
}
public function initContent()
{
$this->context->smarty->assign('current_tab_level', 3);
return parent::initContent();
}
public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
{
parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop);
// Translate template types
if (!empty($this->_list)) {
$type = &$this->fields_list['type']['list'];
foreach ($this->_list as &$row) {
$row['id'] = $row['id_ce_template'];
$row['shortcode'] = '{hook h="CETemplate" id="' . $row['id'] . '"}';
empty($type[$row['type']]) or $row['type'] = $type[$row['type']];
}
}
}
public function renderList()
{
$this->addRowAction('edit');
$this->addRowAction('preview');
$this->addRowAction('export');
$this->addRowAction('delete');
return parent::renderList();
}
public function displayPreviewLink($token, $id, $name = null)
{
$link = $this->context->link->getModuleLink('creativeelements', 'preview', [
'id_employee' => $this->context->employee->id,
'adtoken' => Tools::getAdminTokenLite('AdminCETemplates'),
'preview_id' => "{$id}010000",
], null, null, null, true);
return sprintf($this->action_link, Tools::safeOutput($link), '_blank', 'eye', $this->trans('Preview', [], 'Admin.Actions'));
}
public function displayExportLink($token, $id, $name = null)
{
$link = $this->context->link->getAdminLink('AdminCEEditor') . '&' . http_build_query([
'ajax' => 1,
'action' => 'elementor_library_direct_actions',
'library_action' => 'export_template',
'source' => 'local',
'template_id' => "{$id}010000",
]);
return sprintf($this->action_link, Tools::safeOutput($link), '_self', 'mail-forward', $this->trans('Export', [], 'Admin.Actions'));
}
protected function getTemplateType()
{
return ($type = $this->object->type) ? [
['value' => $type, 'label' => $this->fields_list['type']['list'][$type]],
] : [
['value' => 'page', 'label' => $this->l('Page')],
['value' => 'section', 'label' => $this->l('Section')],
];
}
public function renderForm()
{
$col = version_compare(_PS_VERSION_, '1.7.8', '<') ? 7 : 6;
$this->fields_form = [
'legend' => [
'title' => $this->l('Template'),
'icon' => 'icon-edit',
],
'input' => [
[
'type' => 'text',
'label' => $this->trans('Title', [], 'Admin.Global'),
'name' => 'title',
'col' => $col,
],
[
'type' => 'select',
'label' => $this->trans('Type', [], 'Admin.Catalog.Feature'),
'name' => 'type',
'options' => [
'query' => $this->getTemplateType(),
'id' => 'value',
'name' => 'label',
],
'col' => 3,
],
[
'type' => 'textarea',
'label' => $this->l('Content'),
'name' => 'content',
'col' => $col,
],
[
'type' => 'switch',
'label' => $this->trans('Active', [], 'Admin.Global'),
'name' => 'active',
'required' => false,
'is_bool' => true,
'values' => [
[
'id' => 'active_on',
'value' => 1,
'label' => $this->trans('Enabled', [], 'Admin.Global'),
],
[
'id' => 'active_off',
'value' => 0,
'label' => $this->trans('Disabled', [], 'Admin.Global'),
],
],
'default_value' => 1,
],
],
'submit' => [
'title' => $this->trans('Save', [], 'Admin.Actions'),
],
'buttons' => [
'save_and_stay' => [
'type' => 'submit',
'title' => $this->trans('Save and stay', [], 'Admin.Actions'),
'icon' => 'process-icon-save',
'name' => 'submitAddce_templateAndStay',
'class' => 'btn btn-default pull-right',
],
],
];
return parent::renderForm();
}
protected function trans($id, array $parameters = [], $domain = null, $locale = null)
{
return empty($this->translator) ? $this->l($id) : parent::trans($id, $parameters, $domain, $locale);
}
protected function l($string, $module = 'creativeelements', $addslashes = false, $htmlentities = true)
{
$str = Translate::getModuleTranslation($module, $string, '', null, $addslashes || !$htmlentities);
return $htmlentities ? $str : call_user_func('stripslashes', $str);
}
}

View File

@@ -0,0 +1,462 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
require_once _PS_MODULE_DIR_ . 'creativeelements/classes/CETheme.php';
class AdminCEThemesController extends ModuleAdminController
{
public $bootstrap = true;
public $table = 'ce_theme';
public $identifier = 'id_ce_theme';
public $className = 'CETheme';
public $lang = true;
protected $_defaultOrderBy = 'title';
public function __construct()
{
parent::__construct();
if ($type = Tools::getValue('type')) {
if ('all' == $type) {
unset($this->context->cookie->submitFilterce_template);
unset($this->context->cookie->cethemesce_themeFilter_type);
} else {
$this->context->cookie->submitFilterce_theme = 1;
$this->context->cookie->cethemesce_themeFilter_type = $type;
}
}
if ((Tools::getIsset('updatece_theme') || Tools::getIsset('addce_theme')) && Shop::getContextShopID() === null) {
$this->displayWarning(
$this->trans('You are in a multistore context: any modification will impact all your shops, or each shop of the active group.', [], 'Admin.Catalog.Notification')
);
}
$table_shop = _DB_PREFIX_ . $this->table . '_shop';
$this->_select = 'sa.*';
$this->_join = "LEFT JOIN $table_shop sa ON sa.id_ce_theme = a.id_ce_theme AND b.id_shop = sa.id_shop";
$this->_where = "AND sa.id_shop = " . (int) $this->context->shop->id;
$this->fields_list = [
'id_ce_theme' => [
'title' => $this->trans('ID', [], 'Admin.Global'),
'class' => 'fixed-width-xs',
'align' => 'center',
],
'title' => [
'title' => $this->trans('Title', [], 'Admin.Global'),
],
'type' => [
'title' => $this->trans('Type', [], 'Admin.Catalog.Feature'),
'class' => 'fixed-width-xl',
'type' => 'select',
'list' => [
'header' => $this->l('Header'),
'footer' => $this->l('Footer'),
'page' => $this->l('Page'),
'page-index' => $this->l('Home Page'),
'page-contact' => $this->l('Contact Page'),
'prod' => $this->l('Product'),
'product' => $this->l('Product Page'),
'product-quick-view' => $this->l('Quick View'),
'product-miniature' => $this->l('Product Miniature'),
'page-not-found' => $this->l('404 Page'),
],
'filter_key' => 'type',
],
'date_add' => [
'title' => $this->trans('Created on', [], 'Modules.Facetedsearch.Admin'),
'filter_key' => 'sa!date_add',
'class' => 'fixed-width-lg',
'type' => 'datetime',
],
'date_upd' => [
'title' => $this->l('Modified on'),
'filter_key' => 'sa!date_upd',
'class' => 'fixed-width-lg',
'type' => 'datetime',
],
'active' => [
'title' => $this->trans('Active', [], 'Admin.Global'),
'filter_key' => 'sa!active',
'class' => 'fixed-width-xs',
'align' => 'center',
'active' => 'status',
'type' => 'bool',
],
];
$this->bulk_actions = [
'delete' => [
'text' => $this->trans('Delete selected', [], 'Admin.Notifications.Info'),
'icon' => 'fa fa-icon-trash',
'confirm' => $this->trans('Delete selected items?', [], 'Admin.Notifications.Info'),
],
];
$this->fields_options['theme_settings'] = [
'class' => 'ce-theme-panel',
'icon' => 'icon-cog',
'title' => $this->l('Theme Settings'),
'fields' => [
'CE_HEADER' => [
'title' => $this->l('Header'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('header', $this->context->language->id, $this->context->shop->id)
),
],
'CE_PAGE_INDEX' => [
'title' => $this->l('Home Page'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('page-index', $this->context->language->id, $this->context->shop->id)
),
],
'CE_PRODUCT' => [
'title' => $this->l('Product Page'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('product', $this->context->language->id, $this->context->shop->id)
),
],
'CE_FOOTER' => [
'title' => $this->l('Footer'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('footer', $this->context->language->id, $this->context->shop->id)
),
],
'CE_PAGE_CONTACT' => [
'title' => $this->l('Contact Page'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('page-contact', $this->context->language->id, $this->context->shop->id)
),
],
'CE_PRODUCT_QUICK_VIEW' => [
'title' => $this->l('Quick View'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('product-quick-view', $this->context->language->id, $this->context->shop->id)
),
],
'CE_PAGE_NOT_FOUND' => [
'title' => $this->l('404 Page'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('page-not-found', $this->context->language->id, $this->context->shop->id)
),
],
'CE_PRODUCT_MINIATURE' => [
'title' => $this->l('Product Miniature'),
'cast' => 'strval',
'type' => 'select',
'identifier' => 'value',
'list' => array_merge(
[
['value' => '', 'name' => $this->l('Default')],
],
CETheme::getOptions('product-miniature', $this->context->language->id, $this->context->shop->id)
),
],
],
'submit' => [
'title' => $this->l('Save'),
],
];
}
public function initHeader()
{
parent::initHeader();
$id_lang = $this->context->language->id;
$link = $this->context->link;
$tabs = &$this->context->smarty->tpl_vars['tabs']->value;
foreach ($tabs as &$tab0) {
foreach ($tab0['sub_tabs'] as &$tab1) {
if ($tab1['class_name'] == 'AdminParentCEContent') {
foreach ($tab1['sub_tabs'] as &$tab2) {
if ($tab2['class_name'] == 'AdminCEThemes') {
$sub_tabs = &$tab2['sub_tabs'];
$tab = Tab::getTab($id_lang, Tab::getIdFromClassName('AdminCEThemes'));
$new = Tools::getIsset('addce_theme');
$href = $link->getAdminLink('AdminCEThemes');
$type = Tools::getValue('type', $this->context->cookie->cethemesce_themeFilter_type);
$tab['name'] = $this->l('Templates');
$tab['current'] = $new || (!$type || 'all' === $type) && !$this->object;
$tab['href'] = "$href&type=all";
$sub_tabs[] = $tab;
$type = $this->object ? $this->object->type : $type;
$tab['name'] = $this->l('Header');
$tab['current'] = !$new && 'header' === $type;
$tab['href'] = "$href&type=header";
$sub_tabs[] = $tab;
$tab['name'] = $this->l('Footer');
$tab['current'] = !$new && 'footer' === $type;
$tab['href'] = "$href&type=footer";
$sub_tabs[] = $tab;
$tab['name'] = $this->l('Page');
$tab['current'] = !$new && stripos($type, 'page') === 0;
$tab['href'] = "$href&type=page";
$sub_tabs[] = $tab;
$tab['name'] = $this->l('Product');
$tab['current'] = !$new && 'product-miniature' !== $type && stripos($type, 'prod') === 0;
$tab['href'] = "$href&type=prod";
$sub_tabs[] = $tab;
$tab['name'] = $this->l('Miniature');
$tab['current'] = !$new && 'product-miniature' === $type;
$tab['href'] = "$href&type=product-miniature";
$sub_tabs[] = $tab;
break;
}
}
}
}
}
}
public function initToolBarTitle()
{
$this->page_header_toolbar_title = $this->l('Theme Builder');
$this->context->smarty->assign('icon', 'icon-list');
$this->toolbar_title[] = $this->l(
'add' === $this->display ? 'Add New Template' : ('edit' === $this->display ? 'Edit Template' : 'Templates List')
);
}
public function initPageHeaderToolbar()
{
if (empty($this->display) || 'options' === $this->display) {
$this->page_header_toolbar_btn['addce_theme'] = [
'href' => self::$currentIndex . '&addce_theme&token=' . $this->token,
'desc' => $this->trans('Add new', [], 'Admin.Actions'),
'icon' => 'process-icon-new',
];
}
parent::initPageHeaderToolbar();
}
public function initModal()
{
// Prevent modals
}
public function initContent()
{
$this->context->smarty->assign('current_tab_level', 3);
return parent::initContent();
}
public function processFilter()
{
$type = Tools::getValue('type', $this->context->cookie->cethemesce_themeFilter_type);
if ('page' === $type || 'prod' === $type) {
// Trick for type filtering, use LIKE instead of =
$this->fields_list['type']['type'] = 'text';
}
parent::processFilter();
$this->fields_list['type']['type'] = 'select';
}
public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
{
parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop);
// Translate template types
if (!empty($this->_list)) {
$type = &$this->fields_list['type']['list'];
foreach ($this->_list as &$row) {
empty($type[$row['type']]) or $row['type'] = $type[$row['type']];
}
}
}
public function renderList()
{
$this->addRowAction('edit');
$this->addRowAction('delete');
return parent::renderList();
}
protected function getThemeType()
{
$theme_types = [
['value' => '', 'label' => $this->l('Select...')],
['value' => 'header', 'label' => $this->l('Header')],
['value' => 'footer', 'label' => $this->l('Footer')],
['value' => 'page-index', 'label' => $this->l('Home Page')],
['value' => 'page-contact', 'label' => $this->l('Contact Page')],
['value' => 'product', 'label' => $this->l('Product Page')],
['value' => 'product-quick-view', 'label' => $this->l('Quick View')],
['value' => 'product-miniature', 'label' => $this->l('Product Miniature')],
['value' => 'page-not-found', 'label' => $this->l('404 Page')],
];
if (!empty($this->object->type)) {
return array_filter($theme_types, function ($option) {
return ${'this'}->object->type === $option['value'];
});
}
return $theme_types;
}
public function renderForm()
{
$col = count(Language::getLanguages(false, false, true)) > 1 ? 9 : 7;
version_compare(_PS_VERSION_, '1.7.8', '<') or $col--;
$this->fields_form = [
'legend' => [
'title' => $this->l('Template'),
'icon' => 'icon-edit',
],
'input' => [
[
'type' => 'text',
'label' => $this->trans('Title', [], 'Admin.Global'),
'name' => 'title',
'lang' => true,
'col' => $col,
],
[
'type' => 'select',
'label' => $this->trans('Type', [], 'Admin.Catalog.Feature'),
'name' => 'type',
'required' => true,
'options' => [
'id' => 'value',
'name' => 'label',
'query' => $this->getThemeType(),
],
'col' => 3,
],
[
'type' => 'textarea',
'label' => $this->l('Content'),
'name' => 'content',
'lang' => true,
'col' => $col,
],
[
'type' => 'switch',
'label' => $this->trans('Active', [], 'Admin.Global'),
'name' => 'active',
'required' => false,
'is_bool' => true,
'values' => [
[
'id' => 'active_on',
'value' => 1,
'label' => $this->trans('Enabled', [], 'Admin.Global'),
],
[
'id' => 'active_off',
'value' => 0,
'label' => $this->trans('Disabled', [], 'Admin.Global'),
],
],
],
],
'submit' => [
'title' => $this->trans('Save', [], 'Admin.Actions'),
],
'buttons' => [
'save_and_stay' => [
'type' => 'submit',
'title' => $this->trans('Save and stay', [], 'Admin.Actions'),
'icon' => 'process-icon-save',
'name' => 'submitAddce_themeAndStay',
'class' => 'btn btn-default pull-right',
],
],
];
if (Shop::isFeatureActive()) {
$this->fields_form['input'][] = [
'type' => 'shop',
'label' => $this->trans('Shop association', [], 'Admin.Global'),
'name' => 'checkBoxShopAsso',
];
}
return parent::renderForm();
}
protected function trans($id, array $parameters = [], $domain = null, $locale = null)
{
return empty($this->translator) ? $this->l($id) : parent::trans($id, $parameters, $domain, $locale);
}
protected function l($string, $module = 'creativeelements', $addslashes = false, $htmlentities = true)
{
$str = Translate::getModuleTranslation($module, $string, '', null, $addslashes || !$htmlentities);
return $htmlentities ? $str : call_user_func('stripslashes', $str);
}
}

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,112 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or exit;
class CreativeElementsAjaxModuleFrontController extends ModuleFrontController
{
protected $content_only = true;
public function postProcess()
{
$this->action = Tools::getValue('action');
Tools::getValue('submitMessage') && $this->ajaxProcessSubmitMessage();
Tools::getValue('submitNewsletter') && $this->ajaxProcessSubmitNewsletter();
method_exists($this, "ajaxProcess{$this->action}") && $this->{"ajaxProcess{$this->action}"}();
}
public function ajaxProcessSubmitMessage()
{
if ($contact = Module::getInstanceByName('contactform')) {
$contact->sendMessage();
$this->ajaxDie([
'success' => implode(nl2br("\n", false), $this->success),
'errors' => $this->errors,
]);
}
$this->ajaxDie([
'errors' => ['Error: Contact Form module should be enabled!'],
]);
}
public function ajaxProcessSubmitNewsletter()
{
$name = 'ps_emailsubscription';
$newsletter = Module::getInstanceByName($name);
if (!$newsletter) {
$this->ajaxDie([
'errors' => ["Error: $name module should be enabled!"],
]);
}
$newsletter->newsletterRegistration(${'_POST'}['blockHookName'] = 'displayCE');
$this->ajaxDie([
'success' => empty($newsletter->valid) ? '' : [$newsletter->valid],
'errors' => empty($newsletter->error) ? [] : [$newsletter->error],
]);
}
public function ajaxProcessAddToCartModal()
{
$cart = $this->cart_presenter->present($this->context->cart, true);
$product = null;
$id_product = (int) Tools::getValue('id_product');
$id_product_attribute = (int) Tools::getValue('id_product_attribute');
$id_customization = (int) Tools::getValue('id_customization');
foreach ($cart['products'] as &$p) {
if ($id_product === (int) $p['id_product'] &&
$id_product_attribute === (int) $p['id_product_attribute'] &&
$id_customization === (int) $p['id_customization']
) {
$product = $p;
break;
}
}
$this->context->smarty->assign([
'configuration' => $this->getTemplateVarConfiguration(),
'product' => $product,
'cart' => $cart,
'cart_url' => $this->context->link->getPageLink('cart', null, $this->context->language->id, [
'action' => 'show',
], false, null, true),
]);
$this->ajaxDie([
'modal' => $this->context->smarty->fetch('module:ps_shoppingcart/modal.tpl'),
]);
}
protected function ajaxDie($value = null, $controller = null, $method = null)
{
if (null === $controller) {
$controller = get_class($this);
}
if (null === $method) {
$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
$method = $bt[1]['function'];
}
if (version_compare(_PS_VERSION_, '1.6.1.1', '<')) {
Hook::exec('actionBeforeAjaxDie', ['controller' => $controller, 'method' => $method, 'value' => $value]);
Hook::exec('actionBeforeAjaxDie' . $controller . $method, ['value' => $value]);
} else {
Hook::exec('actionAjaxDie' . $controller . $method . 'Before', ['value' => $value]);
}
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
die(json_encode($value));
}
}

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,96 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
class CreativeElementsPreviewModuleFrontController extends ModuleFrontController
{
protected $uid;
protected $title;
public function init()
{
if (Tools::getIsset('redirect') && CreativeElements::hasAdminToken('AdminCEEditor')) {
$cookie = CE\get_post_meta(0, 'cookie', true);
CE\delete_post_meta(0, 'cookie');
if (!empty($cookie)) {
$lifetime = max(1, (int) Configuration::get('PS_COOKIE_LIFETIME_BO')) * 3600 + time();
$admin = new Cookie('psAdmin', '', $lifetime);
foreach ($cookie as $key => &$value) {
$admin->$key = $value;
}
unset($admin->remote_addr);
$admin->write();
}
Tools::redirectAdmin(urldecode(Tools::getValue('redirect')));
}
$this->uid = CreativeElements::getPreviewUId(false);
if (!$this->uid) {
Tools::redirect('index.php?controller=404');
}
parent::init();
}
public function initContent()
{
$model = $this->uid->getModel();
if ('CETemplate' != $model) {
$this->warning[] = CESmarty::get(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_undefined_position');
}
$post = CE\get_post($this->uid);
$this->title = $post->post_title;
$this->context->smarty->assign($model::${'definition'}['table'], [
'id' => $post->_obj->id,
'content' => '',
]);
parent::initContent();
$this->title = $post->post_title;
$this->context->smarty->addTemplateDir(_CE_TEMPLATES_);
$this->context->smarty->assign([
'HOOK_LEFT_COLUMN' => '',
'HOOK_RIGHT_COLUMN' => '',
'breadcrumb' => $this->getBreadcrumb(),
]);
$this->template = 'front/preview.tpl';
}
public function getBreadcrumbLinks()
{
$breadcrumb = [
'links' => [
['url' => 'javascript:;', 'title' => 'Creative Elements'],
['url' => 'javascript:;', 'title' => CE\__('Preview')],
],
];
if (!empty($this->title)) {
$breadcrumb['links'][] = ['url' => 'javascript:;', 'title' => $this->title];
}
return $breadcrumb;
}
public function getBreadcrumbPath()
{
$breadcrumb = $this->getBreadcrumbLinks();
return CESmarty::capture(_CE_TEMPLATES_ . 'admin/admin.tpl', 'ce_preview_breadcrumb', [
'links' => $breadcrumb['links'],
]);
}
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
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,60 @@
<?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;
/**
* Base App
*
* Base app utility class that provides shared functionality of apps.
*
* @since 2.3.0
*/
abstract class CoreXBaseXApp extends CoreXBaseXModule
{
/**
* Print config.
*
* Used to print the app and its components settings as a JavaScript object.
*
* @since 2.3.0
* @access protected
*/
final protected function printConfig()
{
$name = $this->getName();
$js_var = 'frontend' === $name ? 'ceFrontendConfig' : 'elementor' . call_user_func('ucfirst', $name) . 'Config';
$config = $this->getSettings() + $this->getComponentsConfig();
wp_localize_script('elementor-' . $name, $js_var, $config);
}
/**
* Get components config.
*
* Retrieves the app components settings.
*
* @since 2.3.0
* @access private
*
* @return array
*/
private function getComponentsConfig()
{
$settings = [];
foreach ($this->getComponents() as $id => $instance) {
$settings[$id] = $instance->getSettings();
}
return $settings;
}
}

View File

@@ -0,0 +1,146 @@
<?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;
/**
* Base Object
*
* Base class that provides basic settings handling functionality.
*
* @since 2.3.0
*/
class CoreXBaseXBaseObject
{
/**
* Settings.
*
* Holds the object settings.
*
* @access private
*
* @var array
*/
private $settings;
/**
* Get Settings.
*
* @since 2.3.0
* @access public
*
* @param string $setting Optional. The key of the requested setting. Default is null.
*
* @return mixed An array of all settings, or a single value if `$setting` was specified.
*/
final public function getSettings($setting = null)
{
$this->ensureSettings();
return self::getItems($this->settings, $setting);
}
/**
* Set settings.
*
* @since 2.3.0
* @access public
*
* @param array|string $key If key is an array, the settings are overwritten by that array. Otherwise, the
* settings of the key will be set to the given `$value` param.
*
* @param mixed $value Optional. Default is null.
*/
final public function setSettings($key, $value = null)
{
$this->ensureSettings();
if (is_array($key)) {
$this->settings = $key;
} else {
$this->settings[$key] = $value;
}
}
/**
* Delete setting.
*
* Deletes the settings array or a specific key of the settings array if `$key` is specified.
* @since 2.3.0
* @access public
*
* @param string $key Optional. Default is null.
*/
public function deleteSetting($key = null)
{
if ($key) {
unset($this->settings[$key]);
} else {
$this->settings = [];
}
}
/**
* Get items.
*
* Utility method that receives an array with a needle and returns all the
* items that match the needle. If needle is not defined the entire haystack
* will be returned.
*
* @since 2.3.0
* @access protected
* @static
*
* @param array $haystack An array of items.
* @param string $needle Optional. Needle. Default is null.
*
* @return mixed The whole haystack or the needle from the haystack when requested.
*/
final protected static function getItems(array $haystack, $needle = null)
{
if ($needle) {
return isset($haystack[$needle]) ? $haystack[$needle] : null;
}
return $haystack;
}
/**
* Get init settings.
*
* Used to define the default/initial settings of the object. Inheriting classes may implement this method to define
* their own default/initial settings.
*
* @since 2.3.0
* @access protected
*
* @return array
*/
protected function getInitSettings()
{
return [];
}
/**
* Ensure settings.
*
* Ensures that the `$settings` member is initialized
*
* @since 2.3.0
* @access private
*/
private function ensureSettings()
{
if (null === $this->settings) {
$this->settings = $this->getInitSettings();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
<?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\CoreXDocumentTypesXPost as Post;
use CE\CoreXBaseXThemeDocument as ThemeDocument;
abstract class CoreXBaseXHeaderFooterBase extends ThemeDocument
{
public function getCssWrapperSelector()
{
return '#' . $this->getName();
}
public function getElementUniqueSelector(ElementBase $element)
{
return '#' . $this->getName() . ' .elementor-element' . $element->getUniqueSelector();
}
protected static function getEditorPanelCategories()
{
// Move to top as active.
$categories = [
'theme-elements' => [
'title' => __('Site'),
'active' => true,
],
];
return $categories + parent::getEditorPanelCategories();
}
protected function _registerControls()
{
parent::_registerControls();
Post::registerStyleControls($this);
$this->updateControl(
'section_page_style',
[
'label' => __('Style'),
]
);
}
}

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,282 @@
<?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 module.
*
* An abstract class that provides the needed properties and methods to
* manage and handle modules in inheriting classes.
*
* @since 1.7.0
* @abstract
*/
abstract class CoreXBaseXModule extends CoreXBaseXBaseObject
{
/**
* Module components.
*
* Holds the module components.
*
* @since 1.7.0
* @access private
*
* @var array
*/
private $components = [];
/**
* Module instance.
*
* Holds the module instance.
*
* @since 1.7.0
* @access protected
*
* @var Module
*/
protected static $_instances = [];
/**
* Get module name.
*
* Retrieve the module name.
*
* @since 1.7.0
* @access public
* @abstract
*
* @return string Module name.
*/
abstract public function getName();
/**
* Instance.
*
* Ensures only one instance of the module class is loaded or can be loaded.
*
* @since 1.7.0
* @access public
* @static
*
* @return Module An instance of the class.
*/
public static function instance()
{
$class_name = static::className();
if (empty(static::$_instances[$class_name])) {
static::$_instances[$class_name] = new static();
}
return static::$_instances[$class_name];
}
/**
* @since 2.0.0
* @access public
* @static
*/
public static function isActive()
{
return true;
}
/**
* Class name.
*
* Retrieve the name of the class.
*
* @since 1.7.0
* @access public
* @static
*/
public static function className()
{
return get_called_class();
}
/**
* Clone.
*
* Disable class cloning and throw an error on object clone.
*
* The whole idea of the singleton design pattern is that there is a single
* object. Therefore, we don't want the object to be cloned.
*
* @since 1.7.0
* @access public
*/
public function __clone()
{
// Cloning instances of the class is forbidden
_doing_it_wrong(__FUNCTION__, __('Something went wrong.'), '1.0.0');
}
/**
* Wakeup.
*
* Disable unserializing of the class.
*
* @since 1.7.0
* @access public
*/
public function __wakeup()
{
// Unserializing instances of the class is forbidden
_doing_it_wrong(__FUNCTION__, __('Something went wrong.'), '1.0.0');
}
/**
* Add module component.
*
* Add new component to the current module.
*
* @since 1.7.0
* @access public
*
* @param string $id Component ID.
* @param mixed $instance An instance of the component.
*/
public function addComponent($id, $instance)
{
$this->components[$id] = $instance;
}
/**
* @since 2.3.0
* @access public
* @return Module[]
*/
public function getComponents()
{
return $this->components;
}
/**
* Get module component.
*
* Retrieve the module component.
*
* @since 1.7.0
* @access public
*
* @param string $id Component ID.
*
* @return mixed An instance of the component, or `false` if the component
* doesn't exist.
*/
public function getComponent($id)
{
if (isset($this->components[$id])) {
return $this->components[$id];
}
return false;
}
/**
* Get assets url.
*
* @since 2.3.0
* @access protected
*
* @param string $file_name
* @param string $file_extension
* @param string $relative_url Optional. Default is null.
* @param string $add_min_suffix Optional. Default is 'default'.
*
* @return string
*/
final protected function getAssetsUrl($file_name, $file_extension, $relative_url = null, $add_min_suffix = 'default')
{
static $is_test_mode = null;
if (null === $is_test_mode) {
$is_test_mode = _PS_MODE_DEV_ || defined('ELEMENTOR_TESTS') && ELEMENTOR_TESTS;
}
if (!$relative_url) {
$relative_url = $this->getAssetsRelativeUrl() . $file_extension . '/';
}
$url = _CE_URL_ . $relative_url . $file_name;
if ('default' === $add_min_suffix) {
$add_min_suffix = !$is_test_mode;
}
if ($add_min_suffix) {
$url .= '.min';
}
return $url . '.' . $file_extension;
}
/**
* Get js assets url
*
* @since 2.3.0
* @access protected
*
* @param string $file_name
* @param string $relative_url Optional. Default is null.
* @param string $add_min_suffix Optional. Default is 'default'.
*
* @return string
*/
final protected function getJsAssetsUrl($file_name, $relative_url = null, $add_min_suffix = 'default')
{
return $this->getAssetsUrl($file_name, 'js', $relative_url, $add_min_suffix);
}
/**
* Get css assets url
*
* @since 2.3.0
* @access protected
*
* @param string $file_name
* @param string $relative_url Optional. Default is null.
* @param string $add_min_suffix Optional. Default is 'default'.
* @param bool $add_direction_suffix Optional. Default is `false`
*
* @return string
*/
final protected function getCssAssetsUrl($file_name, $relative_url = null, $add_min_suffix = 'default', $add_direction_suffix = false)
{
static $direction_suffix = null;
if (!$direction_suffix) {
$direction_suffix = is_rtl() ? '-rtl' : '';
}
if ($add_direction_suffix) {
$file_name .= $direction_suffix;
}
return $this->getAssetsUrl($file_name, 'css', $relative_url, $add_min_suffix);
}
/**
* Get assets relative url
*
* @since 2.3.0
* @access protected
*
* @return string
*/
protected function getAssetsRelativeUrl()
{
return 'views/';
}
}

View File

@@ -0,0 +1,51 @@
<?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;
abstract class CoreXBaseXThemeDocument extends Document
{
/*
public static function getPreviewAsDefault()
{
return '';
}
public static function getPreviewAsOptions()
{
return [];
}
*/
public static function getProperties()
{
$properties = parent::getProperties();
$properties['show_in_library'] = true;
$properties['register_type'] = true;
return $properties;
}
public function _getInitialConfig()
{
$config = parent::_getInitialConfig();
$config['library'] = [
'save_as_same_type' => true,
];
return $config;
}
// protected function _registerControls()
}

View File

@@ -0,0 +1,35 @@
<?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\CoreXBaseXThemeDocument as ThemeDocument;
use CE\CoreXDocumentTypesXPost as Post;
use CE\TemplateLibraryXSourceLocal as SourceLocal;
abstract class CoreXBaseXThemePageDocument extends ThemeDocument
{
public function getCssWrapperSelector()
{
return 'body.ce-theme-' . \Tools::substr($this->getMainId(), 0, -6);
}
protected function _registerControls()
{
parent::_registerControls();
if ('product' !== $this->getName()) {
Post::registerPostFieldsControl($this);
}
Post::registerStyleControls($this);
}
}

View File

@@ -0,0 +1,269 @@
<?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\CoreXCommonXModulesXFinderXModule as Finder;
use CE\CoreXBaseXApp as BaseApp;
use CE\CoreXCommonXModulesXAjaxXModule as Ajax;
use CE\CoreXCommonXModulesXConnectXModule as Connect;
/**
* App
*
* Elementor's common app that groups shared functionality, components and configuration
*
* @since 2.3.0
*/
class CoreXCommonXApp extends BaseApp
{
private $templates = [];
/**
* App constructor.
*
* @since 2.3.0
* @access public
*/
public function __construct()
{
$this->addDefaultTemplates();
add_action('elementor/editor/before_enqueue_scripts', [$this, 'register_scripts']);
// add_action('admin_enqueue_scripts', [$this, 'register_scripts']);
add_action('wp_enqueue_scripts', [$this, 'register_scripts']);
add_action('elementor/editor/before_enqueue_styles', [$this, 'register_styles']);
// add_action('admin_enqueue_scripts', [$this, 'register_styles']);
add_action('wp_enqueue_scripts', [$this, 'register_styles'], 9);
add_action('elementor/editor/footer', [$this, 'print_templates']);
// add_action('admin_footer', [$this, 'print_templates']);
add_action('wp_footer', [$this, 'print_templates']);
}
/**
* Init components
*
* Initializing common components.
*
* @since 2.3.0
* @access public
*/
public function initComponents()
{
$this->addComponent('ajax', new Ajax());
// if (current_user_can('manage_options')) {
// if (!is_customize_preview()) {
// $this->addComponent('finder', new Finder());
// }
// $this->addComponent('connect', new Connect());
// }
}
/**
* Get name.
*
* Retrieve the app name.
*
* @since 2.3.0
* @access public
*
* @return string Common app name.
*/
public function getName()
{
return 'common';
}
/**
* Register scripts.
*
* Register common scripts.
*
* @since 2.3.0
* @access public
*/
public function registerScripts()
{
wp_register_script(
'elementor-common-modules',
$this->getJsAssetsUrl('common-modules'),
[],
_CE_VERSION_,
true
);
wp_register_script(
'backbone-marionette',
$this->getJsAssetsUrl('backbone.marionette', 'views/lib/backbone/'),
[
'backbone',
],
'2.4.5',
true
);
wp_register_script(
'backbone-radio',
$this->getJsAssetsUrl('backbone.radio', 'views/lib/backbone/'),
[
'backbone',
],
'1.0.4',
true
);
wp_register_script(
'elementor-dialog',
$this->getJsAssetsUrl('dialog', 'views/lib/dialog/'),
[
'jquery-ui-position',
],
'4.7.1',
true
);
wp_register_script(
'elementor-common',
$this->getJsAssetsUrl('common'),
[
'jquery',
'jquery-ui-draggable',
'backbone-marionette',
'backbone-radio',
'elementor-common-modules',
'elementor-dialog',
],
_CE_VERSION_,
true
);
$this->printConfig();
wp_enqueue_script('elementor-common');
}
/**
* Register styles.
*
* Register common styles.
*
* @since 2.3.0
* @access public
*/
public function registerStyles()
{
wp_register_style(
'elementor-icons',
$this->getCssAssetsUrl('elementor-icons', 'views/lib/eicons/css/'),
[],
'4.3.1'
);
wp_register_style(
'ce-icons',
$this->getCssAssetsUrl('ceicons', 'views/lib/ceicons/'),
[],
_CE_VERSION_
);
wp_enqueue_style(
'elementor-common',
$this->getCssAssetsUrl('common', null, 'default', true),
[
'elementor-icons',
],
_CE_VERSION_
);
}
/**
* Add template.
*
* @since 2.3.0
* @access public
*
* @param string $template Can be either a link to template file or template
* HTML content.
* @param string $type Optional. Whether to handle the template as path
* or text. Default is `path`.
*/
public function addTemplate($template, $type = 'path')
{
if ('path' === $type) {
ob_start();
include $template;
$template = ob_get_clean();
}
$this->templates[] = $template;
}
/**
* Print Templates
*
* Prints all registered templates.
*
* @since 2.3.0
* @access public
*/
public function printTemplates()
{
foreach ($this->templates as $template) {
echo $template;
}
}
/**
* Get init settings.
*
* Define the default/initial settings of the common app.
*
* @since 2.3.0
* @access protected
*
* @return array
*/
protected function getInitSettings()
{
return [
'version' => _CE_VERSION_,
'isRTL' => is_rtl(),
'activeModules' => array_keys($this->getComponents()),
'urls' => [
'assets' => _MODULE_DIR_ . 'creativeelements/views/',
],
];
}
/**
* Add default templates.
*
* Register common app default templates.
* @since 2.3.0
* @access private
*/
private function addDefaultTemplates()
{
$default_templates = [
'includes/editor-templates/library-layout.php',
];
foreach ($default_templates as $template) {
$this->addTemplate(_CE_PATH_ . $template);
}
}
}

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,320 @@
<?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\CoreXBaseXModule as BaseModule;
use CE\CoreXUtilsXExceptions as Exceptions;
/**
* Elementor ajax manager.
*
* Elementor ajax manager handler class is responsible for handling Elementor
* ajax requests, ajax responses and registering actions applied on them.
*
* @since 2.0.0
*/
class CoreXCommonXModulesXAjaxXModule extends BaseModule
{
const NONCE_KEY = 'elementor_ajax';
/**
* Ajax actions.
*
* Holds all the register ajax action.
*
* @since 2.0.0
* @access private
*
* @var array
*/
private $ajax_actions = [];
/**
* Ajax requests.
*
* Holds all the register ajax requests.
*
* @since 2.0.0
* @access private
*
* @var array
*/
private $requests = [];
/**
* Ajax response data.
*
* Holds all the response data for all the ajax requests.
*
* @since 2.0.0
* @access private
*
* @var array
*/
private $response_data = [];
/**
* Current ajax action ID.
*
* Holds all the ID for the current ajax action.
*
* @since 2.0.0
* @access private
*
* @var string|null
*/
private $current_action_id = null;
/**
* Ajax manager constructor.
*
* Initializing Elementor ajax manager.
*
* @since 2.0.0
* @access public
*/
public function __construct()
{
add_action('wp_ajax_elementor_ajax', [$this, 'handle_ajax_request']);
}
/**
* Get module name.
*
* Retrieve the module name.
*
* @since 1.7.0
* @access public
*
* @return string Module name.
*/
public function getName()
{
return 'ajax';
}
/**
* Register ajax action.
*
* Add new actions for a specific ajax request and the callback function to
* be handle the response.
*
* @since 2.0.0
* @access public
*
* @param string $tag Ajax request name/tag.
* @param callable $callback The callback function.
*/
public function registerAjaxAction($tag, $callback)
{
if (!did_action('elementor/ajax/register_actions')) {
_doing_it_wrong(__METHOD__, esc_html(sprintf('Use `%s` hook to register ajax action.', 'elementor/ajax/register_actions')), '2.0.0');
}
if (is_array($callback) && isset($callback[1]) && strpos($callback[1], '_') !== false) {
$callback[1] = \Tools::toCamelCase($callback[1]);
}
$this->ajax_actions[$tag] = compact('tag', 'callback');
}
/**
* Handle ajax request.
*
* Verify ajax nonce, and run all the registered actions for this request.
*
* Fired by `wp_ajax_elementor_ajax` action.
*
* @since 2.0.0
* @access public
*/
public function handleAjaxRequest()
{
if (!$this->verifyRequestNonce()) {
$this->addResponseData(false, __('Token Expired.'))
->sendError(Exceptions::UNAUTHORIZED);
}
$editor_post_id = 0;
if (!empty($_REQUEST['editor_post_id'])) {
$editor_post_id = absint($_REQUEST['editor_post_id']);
Plugin::$instance->db->switchToPost($editor_post_id);
}
/**
* Register ajax actions.
*
* Fires when an ajax request is received and verified.
*
* Used to register new ajax action handles.
*
* @since 2.0.0
*
* @param self $this An instance of ajax manager.
*/
do_action('elementor/ajax/register_actions', $this);
$this->requests = json_decode(${'_POST'}['actions'], true);
foreach ($this->requests as $id => $action_data) {
$this->current_action_id = $id;
if (!isset($this->ajax_actions[$action_data['action']])) {
$this->addResponseData(false, __('Action not found.'), Exceptions::BAD_REQUEST);
continue;
}
if ($editor_post_id) {
$action_data['data']['editor_post_id'] = $editor_post_id;
}
// try {
$results = call_user_func($this->ajax_actions[$action_data['action']]['callback'], $action_data['data'], $this);
if (false === $results) {
$this->addResponseData(false);
} else {
$this->addResponseData(true, $results);
}
// } catch (\Exception $e) {
// $this->addResponseData(false, $e->getMessage(), $e->getCode());
// }
}
$this->current_action_id = null;
$this->sendSuccess();
}
/**
* Get current action data.
*
* Retrieve the data for the current ajax request.
*
* @since 2.0.1
* @access public
*
* @return bool|mixed Ajax request data if action exist, False otherwise.
*/
public function getCurrentActionData()
{
if (!$this->current_action_id) {
return false;
}
return $this->requests[$this->current_action_id];
}
/**
* Create nonce.
*
* Creates a cryptographic token to
* give the user an access to Elementor ajax actions.
*
* @since 2.3.0
* @access public
*
* @return string The nonce token.
*/
public function createNonce()
{
return wp_create_nonce(self::NONCE_KEY);
}
/**
* Verify request nonce.
*
* Whether the request nonce verified or not.
*
* @since 2.3.0
* @access public
*
* @return bool True if request nonce verified, False otherwise.
*/
public function verifyRequestNonce()
{
return !empty($_REQUEST['_nonce']) && wp_verify_nonce($_REQUEST['_nonce'], self::NONCE_KEY);
}
protected function getInitSettings()
{
return [
'url' => Helper::getAjaxLink(),
'nonce' => $this->createNonce(),
];
}
/**
* Ajax success response.
*
* Send a JSON response data back to the ajax request, indicating success.
*
* @since 2.0.0
* @access private
*/
private function sendSuccess()
{
$response = [
'success' => true,
'data' => [
'responses' => $this->response_data,
],
];
die(str_replace('}},"', "}},\n\"", json_encode($response)));
}
/**
* Ajax failure response.
*
* Send a JSON response data back to the ajax request, indicating failure.
*
* @since 2.0.0
* @access private
*
* @param null $code
*/
private function sendError($code = null)
{
wp_send_json_error([
'responses' => $this->response_data,
], $code);
}
/**
* Add response data.
*
* Add new response data to the array of all the ajax requests.
*
* @since 2.0.0
* @access private
*
* @param bool $success True if the requests returned successfully, False otherwise.
* @param mixed $data Optional. Response data. Default is null.
* @param int $code Optional. Response code. Default is 200.
*
* @return Module An instance of ajax manager.
*/
private function addResponseData($success, $data = null, $code = 200)
{
$this->response_data[$this->current_action_id] = [
'success' => $success,
'code' => $code,
'data' => $data,
];
return $this;
}
}

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,132 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXDocumentTypesXPost as Post;
use CE\CoreXBaseXDocument as Document;
class CoreXDocumentTypesXContent extends Document
{
protected static $maintenance = false;
/**
* @since 2.0.0
* @access public
*/
public function getName()
{
return 'content';
}
/**
* @since 2.0.0
* @access public
* @static
*/
public static function getTitle()
{
return __('Content');
}
/**
* @since 2.1.2
* @access protected
* @static
*/
protected static function getEditorPanelCategories()
{
$categories = parent::getEditorPanelCategories();
if (self::$maintenance) {
$categories['maintenance-premium'] = $categories['premium'];
$categories['maintenance-theme-elements'] = $categories['theme-elements'];
unset($categories['premium'], $categories['theme-elements']);
}
return $categories;
}
/**
* @since 2.0.0
* @access public
*/
public function getCssWrapperSelector()
{
return '.elementor.elementor-' . uidval($this->getMainId())->toDefault();
}
/**
* @since 2.0.0
* @access protected
*/
protected function _registerControls()
{
parent::_registerControls();
$this->startInjection([
'of' => 'post_title',
]);
$this->addControl(
'full_width',
[
'label' => __('Clear Content Wrapper'),
'type' => ControlsManager::SWITCHER,
'description' => sprintf(__(
'Not working? You can set a different selector for the content wrapper ' .
'in the <a href="%s" target="_blank">Settings page</a>.'
), Helper::getSettingsLink()),
'selectors' => [
\Configuration::get('elementor_page_wrapper_selector') => 'min-width: 100%; margin: 0; padding: 0;',
],
]
);
$this->endInjection();
Post::registerStyleControls($this);
$this->updateControl(
'section_page_style',
[
'label' => __('Style'),
]
);
}
/**
* @since 2.0.0
* @access public
*
* @param array $data
*
* @throws \Exception
*/
public function __construct(array $data = [])
{
parent::__construct($data);
if (isset($this->post->_obj->hook) && stripos($this->post->_obj->hook, 'displayMaintenance') === 0) {
self::$maintenance = true;
}
}
protected function getRemoteLibraryConfig()
{
$config = parent::getRemoteLibraryConfig();
$config['type'] = 'page';
return $config;
}
}

View File

@@ -0,0 +1,36 @@
<?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\CoreXBaseXHeaderFooterBase as HeaderFooterBase;
class CoreXDocumentTypesXFooter extends HeaderFooterBase
{
public static function getProperties()
{
$properties = parent::getProperties();
$properties['location'] = 'footer';
return $properties;
}
public function getName()
{
return 'footer';
}
public static function getTitle()
{
return __('Footer');
}
}

View File

@@ -0,0 +1,36 @@
<?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\CoreXBaseXHeaderFooterBase as HeaderFooterBase;
class CoreXDocumentTypesXHeader extends HeaderFooterBase
{
public static function getProperties()
{
$properties = parent::getProperties();
$properties['location'] = 'header';
return $properties;
}
public function getName()
{
return 'header';
}
public static function getTitle()
{
return __('Header');
}
}

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,36 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXBaseXThemePageDocument as ThemePageDocument;
class CoreXDocumentTypesXPageContact extends ThemePageDocument
{
public function getName()
{
return 'page-contact';
}
public static function getTitle()
{
return __('Contact Page');
}
protected function getRemoteLibraryConfig()
{
$config = parent::getRemoteLibraryConfig();
$config['type'] = 'page';
return $config;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXBaseXThemePageDocument as ThemePageDocument;
class CoreXDocumentTypesXPageIndex extends ThemePageDocument
{
public function getName()
{
return 'page-index';
}
public static function getTitle()
{
return __('Home Page');
}
protected function getRemoteLibraryConfig()
{
$config = parent::getRemoteLibraryConfig();
$config['type'] = 'page';
return $config;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXBaseXThemePageDocument as ThemePageDocument;
class CoreXDocumentTypesXPageNotFound extends ThemePageDocument
{
public function getName()
{
return 'page-not-found';
}
public static function getTitle()
{
return __('404 Page');
}
protected function getRemoteLibraryConfig()
{
$config = parent::getRemoteLibraryConfig();
$config['category'] = '404 error';
return $config;
}
}

View File

@@ -0,0 +1,264 @@
<?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;
class CoreXDocumentTypesXPost extends Document
{
/**
* @since 2.0.8
* @access public
* @static
*/
public static function getProperties()
{
$properties = parent::getProperties();
// $properties['admin_tab_group'] = '';
$properties['support_wp_page_templates'] = true;
return $properties;
}
/**
* @since 2.1.2
* @access protected
* @static
*/
protected static function getEditorPanelCategories()
{
return Utils::arrayInject(
parent::getEditorPanelCategories(),
'theme-elements',
[
'theme-elements-single' => [
'title' => __('Single'),
'active' => false,
],
]
);
}
/**
* @since 2.0.0
* @access public
*/
public function getName()
{
return 'post';
}
/**
* @since 2.0.0
* @access public
* @static
*/
public static function getTitle()
{
return __('Page');
}
/**
* @since 2.0.0
* @access public
*/
public function getCssWrapperSelector()
{
return 'body.elementor-page-' . $this->getMainId();
}
/**
* @since 2.0.0
* @access protected
*/
protected function _registerControls()
{
parent::_registerControls();
self::registerHideTitleControl($this);
self::registerPostFieldsControl($this);
self::registerStyleControls($this);
}
/**
* @since 2.0.0
* @access public
* @static
* @param Document $document
*/
public static function registerHideTitleControl($document)
{
$page_title_selector = SettingsManager::getSettingsManagers('general')->getModel()->getSettings('elementor_page_title_selector');
if (!$page_title_selector) {
$page_title_selector = 'header.page-header';
}
$page_title_selector .= ', .elementor-page-title';
$document->startInjection([
'of' => 'post_title',
]);
$document->addControl(
'hide_title',
[
'label' => __('Hide Title'),
'type' => ControlsManager::SWITCHER,
'description' => sprintf(__(
'Not working? You can set a different selector for the title ' .
'in the <a href="%s" target="_blank">Settings page</a>.'
), Helper::getSettingsLink()),
'selectors' => [
'{{WRAPPER}} ' . $page_title_selector => 'display: none',
],
]
);
$document->endInjection();
}
/**
* @since 2.0.0
* @access public
* @static
* @param Document $document
*/
public static function registerStyleControls($document)
{
$type = $document->getTemplateType();
if ('product-quick-view' === $type || 'product-miniature' === $type) {
return;
}
$document->startControlsSection(
'section_page_style',
[
'label' => __('Body Style'),
'tab' => ControlsManager::TAB_STYLE,
]
);
$document->addGroupControl(
GroupControlBackground::getType(),
[
'name' => 'background',
'fields_options' => [
'image' => [
// Currently isn't supported.
'dynamic' => [
'active' => false,
],
],
],
'selector' => '{{WRAPPER}}',
]
);
$document->addResponsiveControl(
'padding',
[
'label' => __('Padding'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', 'em', '%'],
'selectors' => [
'{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}',
],
]
);
$document->endControlsSection();
Plugin::$instance->controls_manager->addCustomCssControls($document);
}
/**
* @since 2.0.0
* @access public
* @static
* @param Document $document
*/
public static function registerPostFieldsControl($document)
{
$document->startInjection([
'of' => 'post_status',
]);
// if (post_type_supports($document->post->post_type, 'excerpt')) {
// $document->addControl(
// 'post_excerpt',
// [
// 'label' => __('Excerpt'),
// 'type' => ControlsManager::TEXTAREA,
// 'default' => $document->post->post_excerpt,
// 'label_block' => true,
// ]
// );
// }
$uid = UId::parse($document->getMainId());
if (UId::CMS === $uid->id_type ||
UId::THEME === $uid->id_type && stripos($document->getTemplateType(), 'page-') === 0
) {
$document->addControl(
'post_featured_image',
[
'label' => __('Featured Image'),
'type' => ControlsManager::MEDIA,
'default' => [
'url' => $document->getMeta('_og_image'),
],
]
);
}
$document->endInjection();
}
/**
* @since 2.0.0
* @access public
*
* @param array $data
*
* @throws \Exception
*/
public function __construct(array $data = [])
{
if ($data) {
$template = get_post_meta($data['post_id'], '_wp_page_template', true);
if (empty($template)) {
$template = 'default';
}
$data['settings']['template'] = $template;
}
parent::__construct($data);
}
protected function getRemoteLibraryConfig()
{
$config = parent::getRemoteLibraryConfig();
$config['type'] = 'page';
return $config;
}
}

View File

@@ -0,0 +1,378 @@
<?php
/**
* Creative Elements - live PageBuilder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXDocumentTypesXProduct as ProductDocument;
class CoreXDocumentTypesXProductMiniature extends ProductDocument
{
public function getName()
{
return 'product-miniature';
}
public static function getTitle()
{
return __('Product Miniature');
}
protected static function getEditorPanelCategories()
{
$categories = [
'product-elements' => [
'title' => __('Product Miniature'),
],
];
$categories += parent::getEditorPanelCategories();
return $categories;
}
protected function getRemoteLibraryConfig()
{
$config = parent::getRemoteLibraryConfig();
$config['category'] = 'miniature';
return $config;
}
public function getCssWrapperSelector()
{
return '.elementor.elementor-' . uidval($this->getMainId())->toDefault();
}
protected function _registerControls()
{
parent::_registerControls();
$this->startInjection([
'of' => 'preview_id',
'at' => 'before',
]);
$this->addResponsiveControl(
'preview_width',
[
'label' => __('Width') . ' (px)',
'type' => ControlsManager::NUMBER,
'min' => 150,
'default' => 360,
'tablet_default' => 360,
'mobile_default' => 360,
]
);
$this->endInjection();
$this->startControlsSection(
'section_style',
[
'label' => __('Background'),
'tab' => ControlsManager::TAB_STYLE,
]
);
$this->startControlsTabs('tabs_background');
$this->startControlsTab(
'tab_background_normal',
[
'label' => __('Normal'),
]
);
$this->addGroupControl(
GroupControlBackground::getType(),
[
'name' => 'background',
'selector' => '{{WRAPPER}} .elementor-section-wrap',
]
);
$this->endControlsTab();
$this->startControlsTab(
'tab_background_hover',
[
'label' => __('Hover'),
]
);
$this->addGroupControl(
GroupControlBackground::getType(),
[
'name' => 'background_hover',
'selector' => '{{WRAPPER}} .elementor-section-wrap:hover',
]
);
$this->addControl(
'background_hover_transition',
[
'label' => __('Transition Duration'),
'type' => ControlsManager::SLIDER,
'default' => [
'size' => 0.3,
],
'range' => [
'px' => [
'max' => 3,
'step' => 0.1,
],
],
'separator' => [
'{{WRAPPER}} .elementor-section-wrap' => '--e-background-transition-duration: {{SIZE}}s;',
],
'condition' => [
'background_hover_background!' => '',
],
'separator' => 'before',
]
);
$this->endControlsTab();
$this->endControlsTabs();
$this->endControlsSection();
$this->startControlsSection(
'section_border',
[
'label' => __('Border'),
'tab' => ControlsManager::TAB_STYLE,
]
);
$this->startControlsTabs('tabs_border');
$this->startControlsTab(
'tab_border_normal',
[
'label' => __('Normal'),
]
);
$this->addGroupControl(
GroupControlBorder::getType(),
[
'name' => 'border',
'selector' => '{{WRAPPER}} .elementor-section-wrap',
]
);
$this->addResponsiveControl(
'border_radius',
[
'label' => __('Border Radius'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', '%'],
'selectors' => [
'{{WRAPPER}} .elementor-section-wrap' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->addGroupControl(
GroupControlBoxShadow::getType(),
[
'name' => 'box_shadow',
'selector' => '{{WRAPPER}} .elementor-section-wrap',
]
);
$this->endControlsTab();
$this->startControlsTab(
'tab_border_hover',
[
'label' => __('Hover'),
]
);
$this->addGroupControl(
GroupControlBorder::getType(),
[
'name' => 'border_hover',
'selector' => '{{WRAPPER}} .elementor-section-wrap:hover',
]
);
$this->addResponsiveControl(
'border_radius_hover',
[
'label' => __('Border Radius'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', '%'],
'selectors' => [
'{{WRAPPER}} .elementor-section-wrap:hover' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->addGroupControl(
GroupControlBoxShadow::getType(),
[
'name' => 'box_shadow_hover',
'selector' => '{{WRAPPER}} .elementor-section-wrap:hover',
]
);
$this->addControl(
'border_hover_transition',
[
'label' => __('Transition Duration'),
'type' => ControlsManager::SLIDER,
'separator' => 'before',
'default' => [
'size' => 0.3,
],
'range' => [
'px' => [
'max' => 3,
'step' => 0.1,
],
],
'conditions' => [
'relation' => 'or',
'terms' => [
[
'name' => 'background_hover_background',
'operator' => '!==',
'value' => '',
],
[
'name' => 'border_hover_border',
'operator' => '!==',
'value' => '',
],
],
],
'selectors' => [
'{{WRAPPER}} .elementor-section-wrap' => '--e-border-transition-duration: {{SIZE}}s;',
],
]
);
$this->endControlsTab();
$this->endControlsTabs();
$this->endControlsSection();
$this->startControlsSection(
'section_advanced',
[
'label' => __('Advanced'),
'tab' => ControlsManager::TAB_ADVANCED,
]
);
$this->addResponsiveControl(
'margin',
[
'label' => __('Margin'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', '%'],
'allowed_dimensions' => 'vertical',
'placeholder' => [
'top' => '',
'right' => 'auto',
'bottom' => '',
'left' => 'auto',
],
'selectors' => [
'{{WRAPPER}}' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->addResponsiveControl(
'padding',
[
'label' => __('Padding'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', '%'],
'selectors' => [
'{{WRAPPER}}' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->addControl(
'css_classes',
[
'label' => __('CSS Classes'),
'type' => ControlsManager::TEXT,
'label_block' => false,
'title' => __('Add your custom class WITHOUT the dot. e.g: my-class'),
]
);
$this->addControl(
'overflow',
[
'label' => __('Overflow'),
'type' => ControlsManager::SELECT,
'default' => 'hidden',
'options' => [
'' => __('Default'),
'hidden' => __('Hidden'),
],
'selectors' => [
'{{WRAPPER}} .elementor-section-wrap' => 'overflow: {{VALUE}}',
],
]
);
$this->endControlsSection();
Plugin::$instance->controls_manager->addCustomCssControls($this);
}
public function printSmartyElementsWithWrapper(&$elements_data)
{
$container = $this->getContainerAttributes();
$container['class'] .= '{if !empty($productClasses)} {$productClasses}{/if}';
if ($css_classes = $this->getSettings('css_classes')) {
$container['class'] .= " $css_classes";
}
if (strrpos($container['data-elementor-settings'], '}') !== false) {
$container['data-elementor-settings'] = "{literal}{$container['data-elementor-settings']}{/literal}";
}
$uid = $this->getMainId();
$article = [
'class' => 'elementor-section-wrap',
'data-id-product' => '{$product.id_product}',
'data-id-product-attribute' => '{$product.id_product_attribute}',
'itemprop' => 'item',
];
?>
{* Generated by Creative Elements, do not modify it *}
{ce_enqueue_miniature(<?= $uid ?>)}
<div <?= Utils::renderHtmlAttributes($container) ?>>
<article <?= Utils::renderHtmlAttributes($article) ?> itemscope itemtype="http://schema.org/Product">
<?php
foreach ($elements_data as &$element_data) {
if ($element = Plugin::$instance->elements_manager->createElementInstance($element_data)) {
$element->printElement();
}
}
?>
</article>
</div>
<?php
}
}

View File

@@ -0,0 +1,597 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXDocumentTypesXProduct as ProductDocument;
class CoreXDocumentTypesXProductQuickView extends ProductDocument
{
public function getName()
{
return 'product-quick-view';
}
public static function getTitle()
{
return __('Quick View');
}
public function getCssWrapperSelector()
{
return '#ce-product-quick-view';
}
protected static function getEditorPanelCategories()
{
$categories = [
'product-elements' => [
'title' => __('Product'),
],
];
$categories += parent::getEditorPanelCategories();
return $categories;
}
protected function getRemoteLibraryConfig()
{
$config = parent::getRemoteLibraryConfig();
$config['category'] = 'quick view';
return $config;
}
protected function _registerControls()
{
$this->startControlsSection(
'popup_layout',
[
'label' => __('Layout'),
'tab' => ControlsManager::TAB_SETTINGS,
]
);
$this->addResponsiveControl(
'width',
[
'label' => __('Width'),
'type' => ControlsManager::SLIDER,
'range' => [
'px' => [
'min' => 100,
'max' => 1600,
],
'vw' => [
'min' => 10,
'max' => 100,
],
],
'size_units' => ['px', 'vw'],
'default' => [
'size' => 1200,
],
'selectors' => [
'{{WRAPPER}} .dialog-widget-content' => 'width: {{SIZE}}{{UNIT}};',
],
]
);
$this->addControl(
'height_type',
[
'label' => __('Height'),
'type' => ControlsManager::SELECT,
'default' => 'auto',
'options' => [
'auto' => __('Fit To Content'),
'fit_to_screen' => __('Fit To Screen'),
'custom' => __('Custom'),
],
'selectors_dictionary' => [
'fit_to_screen' => '100vh',
'custom' => '',
],
'selectors' => [
'{{WRAPPER}} .dialog-widget-content' => 'height: {{VALUE}};',
],
]
);
$this->addResponsiveControl(
'height',
[
'label' => __('Custom Height'),
'type' => ControlsManager::SLIDER,
'range' => [
'px' => [
'min' => 100,
'max' => 1600,
],
'vh' => [
'min' => 10,
'max' => 100,
],
],
'size_units' => ['px', 'vh'],
'condition' => [
'height_type' => 'custom',
],
'default' => [
'size' => 700,
],
'selectors' => [
'{{WRAPPER}} .dialog-widget-content' => 'height: {{SIZE}}{{UNIT}};',
],
]
);
$this->addControl(
'content_position',
[
'label' => __('Content Position'),
'type' => ControlsManager::SELECT,
'default' => 'top',
'options' => [
'top' => __('Top'),
'center' => __('Center'),
'bottom' => __('Bottom'),
],
'condition' => [
'height_type!' => 'auto',
],
'selectors_dictionary' => [
'top' => 'flex-start',
'bottom' => 'flex-end',
],
'selectors' => [
'{{WRAPPER}}' => 'align-items: {{VALUE}};',
],
]
);
$this->addControl(
'position_heading',
[
'label' => __('Position'),
'type' => ControlsManager::HEADING,
'separator' => 'before',
]
);
$this->addResponsiveControl(
'horizontal_position',
[
'label' => __('Horizontal'),
'type' => ControlsManager::CHOOSE,
'label_block' => false,
'toggle' => false,
'default' => 'center',
'options' => [
'left' => [
'title' => __('Left'),
'icon' => 'eicon-h-align-left',
],
'center' => [
'title' => __('Center'),
'icon' => 'eicon-h-align-center',
],
'right' => [
'title' => __('Right'),
'icon' => 'eicon-h-align-right',
],
],
'selectors' => [
'{{WRAPPER}}' => 'justify-content: {{VALUE}}',
],
'selectors_dictionary' => [
'left' => 'flex-start',
'right' => 'flex-end',
],
]
);
$this->addResponsiveControl(
'vertical_position',
[
'label' => __('Vertical'),
'type' => ControlsManager::CHOOSE,
'label_block' => false,
'toggle' => false,
'default' => 'center',
'options' => [
'top' => [
'title' => __('Top'),
'icon' => 'eicon-v-align-top',
],
'center' => [
'title' => __('Center'),
'icon' => 'eicon-v-align-middle',
],
'bottom' => [
'title' => __('Bottom'),
'icon' => 'eicon-v-align-bottom',
],
],
'selectors_dictionary' => [
'top' => 'flex-start',
'bottom' => 'flex-end',
],
'selectors' => [
'{{WRAPPER}}' => 'align-items: {{VALUE}}',
],
]
);
$this->addControl(
'close_button',
[
'label' => __('Close Button'),
'type' => ControlsManager::SWITCHER,
'label_off' => __('Hide'),
'label_on' => __('Show'),
'default' => 'yes',
'selectors' => [
'{{WRAPPER}} .dialog-close-button' => 'display: block',
],
'separator' => 'before',
]
);
$this->addResponsiveControl(
'entrance_animation',
[
'label' => __('Entrance Animation'),
'type' => ControlsManager::ANIMATION,
'label_block' => true,
'frontend_available' => true,
'separator' => 'before',
]
);
$this->addControl(
'entrance_animation_duration',
[
'label' => __('Animation Duration') . ' (sec)',
'type' => ControlsManager::SLIDER,
'range' => [
'px' => [
'min' => 0.1,
'max' => 3,
'step' => 0.1,
],
],
'default' => [
'size' => 0.5,
],
'selectors' => [
'{{WRAPPER}} .dialog-message' => 'animation-duration: {{SIZE}}s',
],
'condition' => [
'entrance_animation!' => 'none',
],
]
);
$this->endControlsSection();
parent::_registerControls();
$this->startControlsSection(
'section_page_style',
[
'label' => __('Popup'),
'tab' => ControlsManager::TAB_STYLE,
]
);
$this->addGroupControl(
GroupControlBackground::getType(),
[
'name' => 'background',
'selector' => '{{WRAPPER}} .dialog-message',
]
);
$this->addGroupControl(
GroupControlBorder::getType(),
[
'name' => 'border',
'selector' => '{{WRAPPER}} .dialog-message',
]
);
$this->addResponsiveControl(
'border_radius',
[
'label' => __('Border Radius'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', '%'],
'selectors' => [
'{{WRAPPER}} .dialog-message' => 'border-radius: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}',
],
]
);
$this->addGroupControl(
GroupControlBoxShadow::getType(),
[
'name' => 'box_shadow',
'selector' => '{{WRAPPER}} .dialog-message',
'fields_options' => [
'box_shadow_type' => [
'default' => 'yes',
],
'box_shadow' => [
'default' => [
'horizontal' => 2,
'vertical' => 8,
'blur' => 23,
'spread' => 3,
'color' => 'rgba(0,0,0,0.2)',
],
],
],
]
);
$this->endControlsSection();
$this->startControlsSection(
'section_overlay',
[
'label' => __('Overlay'),
'tab' => ControlsManager::TAB_STYLE,
]
);
$this->addGroupControl(
GroupControlBackground::getType(),
[
'name' => 'overlay_background',
'types' => ['classic', 'gradient'],
'selector' => '{{WRAPPER}}',
'fields_options' => [
'background' => [
'default' => 'classic',
],
'color' => [
'default' => 'rgba(0,0,0,.8)',
],
],
]
);
$this->endControlsSection();
$this->startControlsSection(
'section_close_button',
[
'label' => __('Close Button'),
'tab' => ControlsManager::TAB_STYLE,
'condition' => [
'close_button!' => '',
],
]
);
$this->addControl(
'close_button_position',
[
'label' => __('Position'),
'type' => ControlsManager::SELECT,
'options' => [
'inside' => __('Inside'),
'outside' => __('Outside'),
],
'default' => 'outside',
'frontend_available' => true,
]
);
$this->addResponsiveControl(
'close_button_vertical',
[
'label' => __('Vertical Position'),
'type' => ControlsManager::SLIDER,
'size_units' => ['%', 'px'],
'range' => [
'%' => [
'max' => 100,
'min' => 0,
'step' => 0.1,
],
'px' => [
'max' => 500,
'min' => -500,
],
],
'default' => [
'unit' => '%',
],
'tablet_default' => [
'unit' => '%',
],
'mobile_default' => [
'unit' => '%',
],
'selectors' => [
'{{WRAPPER}} .dialog-close-button' => 'top: {{SIZE}}{{UNIT}}',
],
]
);
$this->addResponsiveControl(
'close_button_horizontal',
[
'label' => __('Horizontal Position'),
'type' => ControlsManager::SLIDER,
'size_units' => ['%', 'px'],
'range' => [
'%' => [
'max' => 100,
'min' => 0,
'step' => 0.1,
],
'px' => [
'max' => 500,
'min' => -500,
],
],
'default' => [
'unit' => '%',
],
'tablet_default' => [
'unit' => '%',
],
'mobile_default' => [
'unit' => '%',
],
'selectors' => [
'{{WRAPPER}} .dialog-close-button' => is_rtl() ? 'left: {{SIZE}}{{UNIT}}' : 'right: {{SIZE}}{{UNIT}}',
],
'separator' => 'after',
]
);
$this->startControlsTabs('close_button_style_tabs');
$this->startControlsTab(
'tab_x_button_normal',
[
'label' => __('Normal'),
]
);
$this->addControl(
'close_button_color',
[
'label' => __('Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'{{WRAPPER}} .dialog-close-button i' => 'color: {{VALUE}}',
],
]
);
$this->addControl(
'close_button_background_color',
[
'label' => __('Background Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'{{WRAPPER}} .dialog-close-button' => 'background-color: {{VALUE}}',
],
]
);
$this->endControlsTab();
$this->startControlsTab(
'tab_x_button_hover',
[
'label' => __('Hover'),
]
);
$this->addControl(
'close_button_hover_color',
[
'label' => __('Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'{{WRAPPER}} .dialog-close-button:hover i' => 'color: {{VALUE}}',
],
]
);
$this->addControl(
'close_button_hover_background_color',
[
'label' => __('Background Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'{{WRAPPER}} .dialog-close-button:hover' => 'background-color: {{VALUE}}',
],
]
);
$this->endControlsTab();
$this->endControlsTabs();
$this->addResponsiveControl(
'icon_size',
[
'label' => __('Size'),
'type' => ControlsManager::SLIDER,
'selectors' => [
'{{WRAPPER}} .dialog-close-button' => 'font-size: {{SIZE}}{{UNIT}}',
],
'separator' => 'before',
]
);
$this->endControlsSection();
$this->startControlsSection(
'section_advanced',
[
'label' => __('Advanced'),
'tab' => ControlsManager::TAB_ADVANCED,
]
);
$this->addResponsiveControl(
'margin',
[
'label' => __('Margin'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', '%'],
'selectors' => [
'{{WRAPPER}} .dialog-message' =>
'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}}; ' .
'max-height: calc(100vh - {{TOP}}{{UNIT}} - {{BOTTOM}}{{UNIT}})',
],
]
);
$this->addResponsiveControl(
'padding',
[
'label' => __('Padding'),
'type' => ControlsManager::DIMENSIONS,
'size_units' => ['px', '%'],
'selectors' => [
'{{WRAPPER}} .dialog-message' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};',
],
]
);
$this->addControl(
'z_index',
[
'label' => __('Z-Index'),
'type' => ControlsManager::NUMBER,
'min' => 0,
'selectors' => [
'{{WRAPPER}}' => 'z-index: {{VALUE}};',
],
]
);
$this->endControlsSection();
Plugin::$instance->controls_manager->addCustomCssControls($this);
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
namespace CE;
defined('_PS_VERSION_') or die;
use CE\CoreXBaseXThemePageDocument as ThemePageDocument;
class CoreXDocumentTypesXProduct extends ThemePageDocument
{
public function getName()
{
return 'product';
}
public static function getTitle()
{
return __('Product Page');
}
protected static function getEditorPanelCategories()
{
$categories = [
'product-elements' => [
'title' => __('Product'),
],
];
$categories += parent::getEditorPanelCategories();
return $categories;
}
protected function _registerControls()
{
parent::_registerControls();
$this->startControlsSection(
'preview_settings',
[
'label' => __('Preview Settings'),
'tab' => ControlsManager::TAB_SETTINGS,
]
);
if (is_admin()) {
$prods = \Product::getProducts(\Context::getContext()->language->id, 0, 1, 'date_upd', 'DESC', false, true);
}
$this->addControl(
'preview_id',
[
'type' => ControlsManager::SELECT2,
'label' => __('Product'),
'label_block' => true,
'select2options' => [
'placeholder' => __('Loading') . '...',
'allowClear' => false,
'product' => true,
'ajax' => [
'url' => Helper::getAjaxProductsListLink(),
],
],
'default' => !empty($prods[0]['id_product']) ? $prods[0]['id_product'] : 1,
'export' => false,
]
);
$this->addControl(
'apply_preview',
[
'type' => ControlsManager::BUTTON,
'label' => __('Apply & Preview'),
'label_block' => true,
'show_label' => false,
'text' => __('Apply & Preview'),
'separator' => 'none',
'event' => 'elementorThemeBuilder:ApplyPreview',
]
);
$this->endControlsSection();
}
}

View File

@@ -0,0 +1,627 @@
<?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\CoreXDocumentTypesXPost as Post;
use CE\CoreXDocumentTypesXContent as Content;
use CE\CoreXDocumentTypesXHeader as Header;
use CE\CoreXDocumentTypesXFooter as Footer;
use CE\CoreXDocumentTypesXProduct as Product;
use CE\CoreXDocumentTypesXProductQuickView as ProductQuickView;
use CE\CoreXDocumentTypesXProductMiniature as ProductMiniature;
use CE\CoreXDocumentTypesXPageIndex as PageIndex;
use CE\CoreXDocumentTypesXPageContact as PageContact;
use CE\CoreXDocumentTypesXPageNotFound as PageNotFound;
use CE\TemplateLibraryXSourceLocal as SourceLocal;
/**
* Elementor documents manager.
*
* Elementor documents manager handler class is responsible for registering and
* managing Elementor documents.
*
* @since 2.0.0
*/
class CoreXDocumentsManager
{
/**
* Registered types.
*
* Holds the list of all the registered types.
*
* @since 2.0.0
* @access protected
*
* @var Document[]
*/
protected $types = [];
/**
* Registered documents.
*
* Holds the list of all the registered documents.
*
* @since 2.0.0
* @access protected
*
* @var Document[]
*/
protected $documents = [];
/**
* Current document.
*
* Holds the current document.
*
* @since 2.0.0
* @access protected
*
* @var Document
*/
protected $current_doc;
/**
* Switched data.
*
* Holds the current document when changing to the requested post.
*
* @since 2.0.0
* @access protected
*
* @var array
*/
protected $switched_data = [];
protected $cpt = [];
/**
* Documents manager constructor.
*
* Initializing the Elementor documents manager.
*
* @since 2.0.0
* @access public
*/
public function __construct()
{
add_action('elementor/documents/register', [$this, 'register_default_types'], 0);
add_action('elementor/ajax/register_actions', [$this, 'register_ajax_actions']);
// add_filter('post_row_actions', [$this, 'filter_post_row_actions'], 11, 2);
// add_filter('page_row_actions', [$this, 'filter_post_row_actions'], 11, 2);
// add_filter('user_has_cap', [$this, 'remove_user_edit_cap'], 10, 3);
add_filter('elementor/editor/localize_settings', [$this, 'localize_settings']);
}
/**
* Register ajax actions.
*
* Process ajax action handles when saving data and discarding changes.
*
* Fired by `elementor/ajax/register_actions` action.
*
* @since 2.0.0
* @access public
*
* @param Ajax $ajax_manager An instance of the ajax manager.
*/
public function registerAjaxActions($ajax_manager)
{
$ajax_manager->registerAjaxAction('save_builder', [$this, 'ajax_save']);
$ajax_manager->registerAjaxAction('discard_changes', [$this, 'ajax_discard_changes']);
}
/**
* Register default types.
*
* Registers the default document types.
*
* @since 2.0.0
* @access public
*/
public function registerDefaultTypes()
{
$default_types = [
'post' => Post::getClassFullName(),
'content' => Content::getClassFullName(),
'header' => Header::getClassFullName(),
'footer' => Footer::getClassFullName(),
'product' => Product::getClassFullName(),
'product-quick-view' => ProductQuickView::getClassFullName(),
'product-miniature' => ProductMiniature::getClassFullName(),
'page-index' => PageIndex::getClassFullName(),
'page-contact' => PageContact::getClassFullName(),
'page-not-found' => PageNotFound::getClassFullName(),
];
foreach ($default_types as $type => $class) {
$this->registerDocumentType($type, $class);
}
}
/**
* Register document type.
*
* Registers a single document.
*
* @since 2.0.0
* @access public
*
* @param string $type Document type name.
* @param Document $class The name of the class that registers the document type.
* Full name with the namespace.
*
* @return DocumentsManager The updated document manager instance.
*/
public function registerDocumentType($type, $class)
{
$this->types[$type] = $class;
$cpt = $class::getProperty('cpt');
if ($cpt) {
foreach ($cpt as $post_type) {
$this->cpt[$post_type] = $type;
}
}
if ($class::getProperty('register_type')) {
SourceLocal::addTemplateType($type);
}
return $this;
}
/**
* Get document.
*
* Retrieve the document data based on a post ID.
*
* @since 2.0.0
* @access public
*
* @param int $post_id Post ID.
* @param bool $from_cache Optional. Whether to retrieve cached data. Default is true.
*
* @return false|Document Document data or false if post ID was not entered.
*/
public function get($post_id, $from_cache = true)
{
$this->registerTypes();
$post_id = absint($post_id);
if (!$post_id || !get_post($post_id)) {
return false;
}
$post_id = apply_filters('elementor/documents/get/post_id', "$post_id");
if (!$from_cache || !isset($this->documents[$post_id])) {
if ($parent = wp_is_post_autosave($post_id)) {
$post_type = get_post_type($parent);
} else {
$post_type = get_post_type($post_id);
}
$doc_type = 'post';
if (isset($this->cpt[$post_type])) {
$doc_type = $this->cpt[$post_type];
}
// $meta_type = get_post_meta($post_id, Document::TYPE_META_KEY, true);
$uid = UId::parse($post_id);
$meta_type = get_post($uid)->template_type;
if ($meta_type && isset($this->types[$meta_type])) {
$doc_type = $meta_type;
}
$doc_type_class = $this->getDocumentType($doc_type);
$this->documents[$post_id] = new $doc_type_class([
'post_id' => $post_id,
]);
}
return $this->documents[$post_id];
}
/**
* Get document or autosave.
*
* Retrieve either the document or the autosave.
*
* @since 2.0.0
* @access public
*
* @param int $id Post ID.
* @param int $user_id User ID. Default is `0`.
*
* @return false|Document The document if it exist, False otherwise.
*/
public function getDocOrAutoSave($id, $user_id = 0)
{
$document = $this->get($id);
if ($document && $document->getAutosaveId($user_id)) {
$document = $document->getAutosave($user_id);
}
return $document;
}
/**
* Get document for frontend.
*
* Retrieve the document for frontend use.
*
* @since 2.0.0
* @access public
*
* @param int $post_id Optional. Post ID. Default is `0`.
*
* @return false|Document The document if it exist, False otherwise.
*/
public function getDocForFrontend($post_id)
{
if (\CreativeElements::getPreviewUId(false)) {
$document = $this->getDocOrAutoSave($post_id, get_current_user_id());
} else {
$document = $this->get($post_id);
}
return $document;
}
/**
* Get document type.
*
* Retrieve the type of any given document.
*
* @since 2.0.0
* @access public
*
* @param string $type
*
* @param string $fallback
*
* @return Document|bool The type of the document.
*/
public function getDocumentType($type, $fallback = 'post')
{
$types = $this->getDocumentTypes();
if (isset($types[$type])) {
return $types[$type];
}
if (isset($types[$fallback])) {
return $types[$fallback];
}
return false;
}
/**
* Get document types.
*
* Retrieve the all the registered document types.
*
* @since 2.0.0
* @access public
*
* @param array $args Optional. An array of key => value arguments to match against
* the properties. Default is empty array.
* @param string $operator Optional. The logical operation to perform. 'or' means only one
* element from the array needs to match; 'and' means all elements
* must match; 'not' means no elements may match. Default 'and'.
*
* @return Document[] All the registered document types.
*/
public function getDocumentTypes($args = [], $operator = 'and')
{
$this->registerTypes();
if (!empty($args)) {
// $types_properties = $this->getTypesProperties();
// $filtered = wp_filter_object_list($types_properties, $args, $operator);
// return array_intersect_key($this->types, $filtered);
throw new \RuntimeException('TODO');
}
return $this->types;
}
/**
* Get document types with their properties.
*
* @return array A list of properties arrays indexed by the type.
*/
public function getTypesProperties()
{
$types_properties = [];
foreach ($this->getDocumentTypes() as $type => $class) {
$types_properties[$type] = $class::getProperties();
}
return $types_properties;
}
/**
* Create a document.
*
* Create a new document using any given parameters.
*
* @since 2.0.0
* @access public
*
* @param string $type Document type.
* @param array $post_data An array containing the post data.
* @param array $meta_data An array containing the post meta data.
*
* @return Document The type of the document.
*/
public function create($type, $post_data = [], $meta_data = [])
{
$class = $this->getDocumentType($type, false);
if (!$class) {
die(sprintf('Type %s does not exist.', $type));
}
// if (empty($post_data['post_title'])) {
// $post_data['post_title'] = __('Elementor');
// if ('post' !== $type) {
// $post_data['post_title'] = sprintf(
// __('Elementor %s'),
// call_user_func([$class, 'get_title'])
// );
// }
// $update_title = true;
// }
$meta_data['_elementor_edit_mode'] = 'builder';
// $meta_data[Document::TYPE_META_KEY] = $type;
$post_data['template_type'] = $type;
$post_data['meta_input'] = $meta_data;
$post_id = wp_insert_post($post_data);
// if (!empty($update_title)) {
// $post_data['ID'] = $post_id;
// $post_data['post_title'] .= ' #' . $post_id;
// // The meta doesn't need update.
// unset($post_data['meta_input']);
// wp_update_post($post_data);
// }
/** @var Document $document */
$document = new $class([
'post_id' => $post_id,
]);
// Let the $document to re-save the template type by his way + version.
$document->save([]);
return $document;
}
// public function removeUserEditCap($allcaps, $caps, $args)
// public function filterPostRowActions($actions, $post)
/**
* Save document data using ajax.
*
* Save the document on the builder using ajax, when saving the changes, and refresh the editor.
*
* @since 2.0.0
* @access public
*
* @param $request Post ID.
*
* @throws \Exception If current user don't have permissions to edit the post or the post is not using Elementor.
*
* @return array The document data after saving.
*/
public function ajaxSave($request)
{
$document = $this->get($request['editor_post_id']);
// if (!$document->isBuiltWithElementor() || !$document->isEditableByCurrentUser()) {
if (!$document->isEditableByCurrentUser()) {
throw new \Exception('Access denied.');
}
$this->switchToDocument($document);
$post = $document->getPost();
// Set the post as global post.
Plugin::$instance->db->switchToPost($post->ID);
$status = DB::STATUS_DRAFT;
if (isset($request['status']) && in_array($request['status'], [DB::STATUS_PUBLISH, DB::STATUS_PRIVATE, DB::STATUS_AUTOSAVE], true)) {
$status = $request['status'];
}
if (DB::STATUS_AUTOSAVE === $status) {
// If the post is a draft - save the `autosave` to the original draft.
// Allow a revision only if the original post is already published.
if (in_array($post->post_status, [DB::STATUS_PUBLISH, DB::STATUS_PRIVATE], true)) {
$document = $document->getAutosave(0, true);
}
}
// Set default page template because the footer-saver doesn't send default values,
// But if the template was changed from canvas to default - it needed to save.
if (Utils::isCptCustomTemplatesSupported($post) && !isset($request['settings']['template'])) {
$request['settings']['template'] = 'default';
}
$data = [
'elements' => $request['elements'],
'settings' => $request['settings'],
];
$document->save($data);
// Refresh after save.
$document = $this->get($post->ID, false);
$return_data = [
'config' => [
'document' => [
'last_edited' => $document->getLastEdited(),
'urls' => [
'wp_preview' => $document->getWpPreviewUrl(),
],
],
],
];
/**
* Returned documents ajax saved data.
*
* Filters the ajax data returned when saving the post on the builder.
*
* @since 2.0.0
*
* @param array $return_data The returned data.
* @param Document $document The document instance.
*/
$return_data = apply_filters('elementor/documents/ajax_save/return_data', $return_data, $document);
return $return_data;
}
/**
* Ajax discard changes.
*
* Load the document data from an autosave, deleting unsaved changes.
*
* @since 2.0.0
* @access public
*
* @param $request
*
* @return bool True if changes discarded, False otherwise.
*/
public function ajaxDiscardChanges($request)
{
$document = $this->get($request['editor_post_id']);
$autosave = $document->getAutosave();
if ($autosave) {
$success = $autosave->delete();
} else {
$success = true;
}
return $success;
}
/**
* Switch to document.
*
* Change the document to any new given document type.
*
* @since 2.0.0
* @access public
*
* @param Document $document The document to switch to.
*/
public function switchToDocument($document)
{
// If is already switched, or is the same post, return.
if ($this->current_doc === $document) {
$this->switched_data[] = false;
return;
}
$this->switched_data[] = [
'switched_doc' => $document,
'original_doc' => $this->current_doc, // Note, it can be null if the global isn't set
];
$this->current_doc = $document;
}
/**
* Restore document.
*
* Rollback to the original document.
*
* @since 2.0.0
* @access public
*/
public function restoreDocument()
{
$data = array_pop($this->switched_data);
// If not switched, return.
if (!$data) {
return;
}
$this->current_doc = $data['original_doc'];
}
/**
* Get current document.
*
* Retrieve the current document.
*
* @since 2.0.0
* @access public
*
* @return Document The current document.
*/
public function getCurrent()
{
return $this->current_doc;
}
public function localizeSettings($settings)
{
$translations = [];
foreach ($this->getDocumentTypes() as $type => $class) {
$translations[$type] = $class::getTitle();
}
return array_replace_recursive($settings, [
'i18n' => $translations,
]);
}
private function registerTypes()
{
if (!did_action('elementor/documents/register')) {
/**
* Register Elementor documents.
*
* @since 2.0.0
*
* @param DocumentsManager $this The document manager instance.
*/
do_action('elementor/documents/register', $this);
}
}
}

View File

@@ -0,0 +1,200 @@
<?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 base tag.
*
* An abstract class to register new Elementor tags.
*
* @since 2.0.0
* @abstract
*/
abstract class CoreXDynamicTagsXBaseTag extends ControlsStack
{
const REMOTE_RENDER = false;
/**
* @since 2.0.0
* @access public
* @static
*/
final public static function getType()
{
return 'tag';
}
/**
* @since 2.0.0
* @access public
* @abstract
*/
abstract public function getCategories();
/**
* @since 2.0.0
* @access public
* @abstract
*/
abstract public function getGroup();
/**
* @since 2.0.0
* @access public
* @abstract
*/
abstract public function getTitle();
/**
* @since 2.0.0
* @access public
* @abstract
*
* @param array $options
*/
abstract public function getContent(array $options = []);
/**
* @since 2.0.0
* @access public
* @abstract
*/
abstract public function getContentType();
/**
* @since 2.0.0
* @access public
*/
public function getPanelTemplateSettingKey()
{
return '';
}
/**
* @since 2.0.0
* @access public
*/
public function isSettingsRequired()
{
return true;
}
/**
* @since 2.0.9
* @access public
*/
public function getEditorConfig()
{
ob_start();
$this->printPanelTemplate();
$panel_template = ob_get_clean();
return [
'name' => $this->getName(),
'title' => $this->getTitle(),
'panel_template' => &$panel_template,
'categories' => $this->getCategories(),
'group' => $this->getGroup(),
'controls' => $this->getControls(),
'content_type' => $this->getContentType(),
'settings_required' => $this->isSettingsRequired(),
];
}
/**
* @since 2.0.0
* @access public
*/
public function printPanelTemplate()
{
$panel_template_setting_key = $this->getPanelTemplateSettingKey();
if (!$panel_template_setting_key) {
return;
}
?>
<#
var key = <?= esc_html($panel_template_setting_key); ?>;
if (key) {
var settingsKey = "<?= esc_html($panel_template_setting_key); ?>";
/*
* If the tag has controls,
* and key is an existing control (and not an old one),
* and the control has options (select/select2/choose),
* and the key is an existing option (and not in a group or an old one).
*/
if (controls && controls[settingsKey]) {
var controlSettings = controls[settingsKey];
if (controlSettings.options && controlSettings.options[key]) {
var label = controlSettings.options[key];
key = label.title || label;
} else if (controlSettings.groups) {
var label = controlSettings.groups[key];
if ('string' === typeof label) {
key = label;
} else {
label = _.filter(_.pluck(_.pluck(controlSettings.groups, 'options'), key));
if (label[0]) {
key = label[0];
}
}
}
}
print('(' + key + ')');
}
#>
<?php
}
/**
* @since 2.0.0
* @access public
*/
final public function getUniqueName()
{
return 'tag-' . $this->getName();
}
/**
* @since 2.0.0
* @access protected
*/
protected function registerAdvancedSection()
{
}
/**
* @since 2.0.0
* @access protected
*/
final protected function initControls()
{
Plugin::$instance->controls_manager->openStack($this);
$this->startControlsSection('settings', [
'label' => __('Settings'),
]);
$this->_registerControls();
$this->endControlsSection();
// If in fact no controls were registered, empty the stack
if (1 === count(Plugin::$instance->controls_manager->getStacks($this->getUniqueName())['controls'])) {
Plugin::$instance->controls_manager->openStack($this);
}
$this->registerAdvancedSection();
}
}

View File

@@ -0,0 +1,69 @@
<?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\CoreXDynamicTagsXBaseTag as BaseTag;
/**
* Elementor base data tag.
*
* An abstract class to register new Elementor data tags.
*
* @since 2.0.0
* @abstract
*/
abstract class CoreXDynamicTagsXDataTag extends BaseTag
{
private static $getter_method = 'getValue';
/**
* @since 2.0.0
* @access protected
* @abstract
*
* @param array $options
*/
abstract protected function getValue(array $options = []);
/**
* @since 2.5.10
* @access protected
*
* @return mixed
*/
protected function getSmartyValue(array $options = [])
{
return '{literal}' . $this->getValue($options) . '{/literal}';
}
/**
* @since 2.0.0
* @access public
*/
final public function getContentType()
{
return 'plain';
}
/**
* @since 2.0.0
* @access public
*
* @param array $options
*
* @return mixed
*/
public function getContent(array $options = [])
{
return static::REMOTE_RENDER && is_admin() && 'getValue' === self::$getter_method ? null : $this->{self::$getter_method}($options);
}
}

View File

@@ -0,0 +1,126 @@
<?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\CoreXFilesXCSSXPost as Post;
class CoreXDynamicTagsXDynamicCSS extends Post
{
protected $post_id_for_data;
/**
* Dynamic_CSS constructor.
*
* @since 2.0.13
* @access public
* @param int $post_id Post ID
* @param int $post_id_for_data
*/
public function __construct($post_id, $post_id_for_data)
{
$this->post_id_for_data = $post_id_for_data;
parent::__construct($post_id);
}
/**
* @since 2.0.13
* @access public
*/
public function getName()
{
return 'dynamic';
}
/**
* @since 2.0.13
* @access protected
*/
protected function useExternalFile()
{
return false;
}
/**
* @since 2.0.13
* @access protected
*/
protected function getFileHandleId()
{
return 'elementor-post-dynamic-' . $this->post_id_for_data;
}
/**
* @since 2.0.13
* @access protected
*/
protected function getData()
{
return Plugin::$instance->db->getPlainEditor($this->post_id_for_data);
}
/**
* @since 2.0.13
* @access public
*/
public function getMeta($property = null)
{
// Parse CSS first, to get the fonts list.
$css = $this->getContent();
$meta = [
'status' => $css ? self::CSS_STATUS_INLINE : self::CSS_STATUS_EMPTY,
'fonts' => $this->getFonts(),
'css' => $css,
];
if ($property) {
return isset($meta[$property]) ? $meta[$property] : null;
}
return $meta;
}
/**
* @since 2.0.13
* @access public
*/
public function addControlsStackStyleRules(ControlsStack $controls_stack, array $controls, array $values, array $placeholders, array $replacements, array $all_controls = null)
{
$dynamic_settings = $controls_stack->getSettings('__dynamic__');
if (!empty($dynamic_settings)) {
$controls = array_intersect_key($controls, $dynamic_settings);
$all_controls = $controls_stack->getControls();
$parsed_dynamic_settings = $controls_stack->parseDynamicSettings($values, $controls);
foreach ($controls as $control) {
if (!empty($control['style_fields'])) {
$this->addRepeaterControlStyleRules($controls_stack, $control, $values[$control['name']], $placeholders, $replacements);
}
if (empty($control['selectors'])) {
continue;
}
$this->addControlStyleRules($control, $parsed_dynamic_settings, $all_controls, $placeholders, $replacements);
}
}
if ($controls_stack instanceof ElementBase) {
foreach ($controls_stack->getChildren() as $child_element) {
$this->renderStyles($child_element);
}
}
}
}

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,464 @@
<?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\CoreXFilesXCSSXPost as Post;
use CE\CoreXFilesXCSSXPostPreview as PostPreview;
use CE\CoreXDynamicTagsXBaseTag as BaseTag;
use CE\CoreXDynamicTagsXDynamicCSS as DynamicCSS;
class CoreXDynamicTagsXManager
{
const TAG_LABEL = 'elementor-tag';
const MODE_RENDER = 'render';
const MODE_REMOVE = 'remove';
const DYNAMIC_SETTING_KEY = '__dynamic__';
private $tags_groups = [];
private $tags_info = [];
private $parsing_mode = self::MODE_RENDER;
/**
* Dynamic tags manager constructor.
*
* Initializing Elementor dynamic tags manager.
*
* @since 2.0.0
* @access public
*/
public function __construct()
{
$this->addActions();
}
/**
* Parse dynamic tags text.
*
* Receives the dynamic tag text, and returns a single value or multiple values
* from the tag callback function.
*
* @since 2.0.0
* @access public
*
* @param string $text Dynamic tag text.
* @param array $settings The dynamic tag settings.
* @param callable $parse_callback The functions that renders the dynamic tag.
*
* @return string|string[]|mixed A single string or an array of strings with
* the return values from each tag callback
* function.
*/
public function parseTagsText($text, array $settings, callable $parse_callback)
{
if (!empty($settings['returnType']) && 'object' === $settings['returnType']) {
$value = $this->parseTagText($text, $settings, $parse_callback);
} else {
$value = preg_replace_callback('/\[' . self::TAG_LABEL . '.+?(?=\])\]/', function ($tag_text_match) use ($settings, $parse_callback) {
return $this->parseTagText($tag_text_match[0], $settings, $parse_callback);
}, $text);
}
return $value;
}
/**
* Parse dynamic tag text.
*
* Receives the dynamic tag text, and returns the value from the callback
* function.
*
* @since 2.0.0
* @access public
*
* @param string $tag_text Dynamic tag text.
* @param array $settings The dynamic tag settings.
* @param callable $parse_callback The functions that renders the dynamic tag.
*
* @return string|array|mixed If the tag was not found an empty string or an
* empty array will be returned, otherwise the
* return value from the tag callback function.
*/
public function parseTagText($tag_text, array $settings, callable $parse_callback)
{
$tag_data = $this->tagTextToTagData($tag_text);
if (!$tag_data) {
if (!empty($settings['returnType']) && 'object' === $settings['returnType']) {
return [];
}
return '';
}
return call_user_func_array($parse_callback, $tag_data);
}
/**
* @since 2.0.0
* @access public
*
* @param string $tag_text
*
* @return array|null
*/
public function tagTextToTagData($tag_text)
{
preg_match('/id="(.*?(?="))"/', $tag_text, $tag_id_match);
preg_match('/name="(.*?(?="))"/', $tag_text, $tag_name_match);
preg_match('/settings="(.*?(?="]))/', $tag_text, $tag_settings_match);
if (!$tag_id_match || !$tag_name_match || !$tag_settings_match) {
return null;
}
return [
'id' => $tag_id_match[1],
'name' => $tag_name_match[1],
'settings' => json_decode(urldecode($tag_settings_match[1]), true),
];
}
/**
* Dynamic tag to text.
*
* Retrieve the shortcode that represents the dynamic tag.
*
* @since 2.0.0
* @access public
*
* @param BaseTag $tag An instance of the dynamic tag.
*
* @return string The shortcode that represents the dynamic tag.
*/
public function tagToText(BaseTag $tag)
{
return sprintf('[%1$s id="%2$s" name="%3$s" settings="%4$s"]', self::TAG_LABEL, $tag->getId(), $tag->getName(), urlencode(json_encode($tag->getSettings(), JSON_FORCE_OBJECT)));
}
/**
* @since 2.0.0
* @access public
* @param string $tag_id
* @param string $tag_name
* @param array $settings
*
* @return string
*/
public function tagDataToTagText($tag_id, $tag_name, array $settings = [])
{
$tag = $this->createTag($tag_id, $tag_name, $settings);
if (!$tag) {
return '';
}
return $this->tagToText($tag);
}
/**
* @since 2.0.0
* @access public
* @param string $tag_id
* @param string $tag_name
* @param array $settings
*
* @return Tag|null
*/
public function createTag($tag_id, $tag_name, array $settings = [])
{
$tag_info = $this->getTagInfo($tag_name);
if (!$tag_info) {
return null;
}
$tag_class = $tag_info['class'];
return new $tag_class([
'settings' => $settings,
'id' => $tag_id,
]);
}
/**
* @since 2.0.0
* @access public
*
* @param $tag_id
* @param $tag_name
* @param array $settings
*
* @return null|string
*/
public function getTagDataContent($tag_id, $tag_name, array $settings = [])
{
if (self::MODE_REMOVE === $this->parsing_mode) {
return null;
}
$tag = $this->createTag($tag_id, $tag_name, $settings);
if (!$tag) {
return null;
}
return $tag->getContent();
}
/**
* @since 2.0.0
* @access public
*
* @param $tag_name
*
* @return mixed|null
*/
public function getTagInfo($tag_name)
{
$tags = $this->getTags();
if (empty($tags[$tag_name])) {
return null;
}
return $tags[$tag_name];
}
/**
* @since 2.0.9
* @access public
*/
public function getTags()
{
if (!did_action('elementor/dynamic_tags/register_tags')) {
/**
* Register dynamic tags.
*
* Fires when Elementor registers dynamic tags.
*
* @since 2.0.9
*
* @param Manager $this Dynamic tags manager.
*/
do_action('elementor/dynamic_tags/register_tags', $this);
}
return $this->tags_info;
}
/**
* @since 2.0.0
* @access public
*
* @param string $class
*/
public function registerTag($class)
{
/** @var Tag $tag */
$tag = new $class();
$this->tags_info[$tag->getName()] = [
'class' => $class,
'instance' => $tag,
];
}
/**
* @since 2.0.9
* @access public
*
* @param string $tag_name
*/
public function unregisterTag($tag_name)
{
unset($this->tags_info[$tag_name]);
}
/**
* @since 2.0.0
* @access public
*
* @param $group_name
* @param array $group_settings
*/
public function registerGroup($group_name, array $group_settings)
{
$default_group_settings = [
'title' => '',
];
$group_settings = array_merge($default_group_settings, $group_settings);
$this->tags_groups[$group_name] = $group_settings;
}
/**
* @since 2.0.0
* @access public
*/
public function printTemplates()
{
foreach ($this->getTags() as $tag_name => $tag_info) {
$tag = $tag_info['instance'];
if (!$tag instanceof Tag) {
continue;
}
$tag->printTemplate();
}
}
/**
* @since 2.0.0
* @access public
*/
public function getTagsConfig()
{
$config = [];
foreach ($this->getTags() as $tag_name => $tag_info) {
/** @var Tag $tag */
$tag = $tag_info['instance'];
$config[$tag_name] = $tag->getEditorConfig();
}
return $config;
}
/**
* @since 2.0.0
* @access public
*/
public function getConfig()
{
return [
'tags' => $this->getTagsConfig(),
'groups' => $this->tags_groups,
];
}
/**
* @since 2.0.0
* @access public
*
* @throws \Exception If post ID is missing.
* @throws \Exception If current user don't have permissions to edit the post.
*/
public function ajaxRenderTags()
{
$data = json_decode(${'_POST'}['data'], true);
if (empty($data['post_id'])) {
throw new \Exception('Missing post id.');
}
if (!User::isCurrentUserCanEdit($data['post_id'])) {
throw new \Exception('Access denied.');
}
Plugin::$instance->db->switchToPost($data['post_id']);
/**
* Before dynamic tags rendered.
*
* Fires before Elementor renders the dynamic tags.
*
* @since 2.0.0
*/
do_action('elementor/dynamic_tags/before_render');
$tags_data = [];
foreach ($data['tags'] as $tag_key) {
$tag_key_parts = explode('-', $tag_key);
$tag_name = base64_decode($tag_key_parts[0]);
$tag_settings = json_decode(urldecode(base64_decode($tag_key_parts[1])), true);
$tag = $this->createTag(null, $tag_name, $tag_settings);
$tags_data[$tag_key] = $tag->getContent();
}
/**
* After dynamic tags rendered.
*
* Fires after Elementor renders the dynamic tags.
*
* @since 2.0.0
*/
do_action('elementor/dynamic_tags/after_render');
return $tags_data;
}
/**
* @since 2.0.0
* @access public
*
* @param $mode
*/
public function setParsingMode($mode)
{
$this->parsing_mode = $mode;
}
/**
* @since 2.0.0
* @access public
*/
public function getParsingMode()
{
return $this->parsing_mode;
}
/**
* @since 2.1.0
* @access public
* @param Post $css_file
*/
public function afterEnqueuePostCss($css_file)
{
$post_id = $css_file->getPostId();
if ($css_file instanceof PostPreview) {
$post_id_for_data = $css_file->getPreviewId();
} else {
$post_id_for_data = $post_id;
}
$css_file = new DynamicCSS($post_id, $post_id_for_data);
$css_file->enqueue();
}
// public function registerAjaxActions(Ajax $ajax)
/**
* @since 2.0.0
* @access private
*/
private function addActions()
{
// add_action('elementor/ajax/register_actions', [$this, 'register_ajax_actions']);
add_action('elementor/css-file/post/enqueue', [$this, 'after_enqueue_post_css']);
}
}

View File

@@ -0,0 +1,149 @@
<?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\CoreXDynamicTagsXBaseTag as BaseTag;
/**
* Elementor tag.
*
* An abstract class to register new Elementor tag.
*
* @since 2.0.0
* @abstract
*/
abstract class CoreXDynamicTagsXTag extends BaseTag
{
const WRAPPED_TAG = false;
private static $render_method = 'render';
/**
* @since 2.0.0
* @access public
*
* @param array $options
*
* @return string
*/
public function getContent(array $options = [])
{
if (static::REMOTE_RENDER && is_admin() && 'render' === self::$render_method) {
return;
}
$settings = $this->getSettings();
ob_start();
$this->{self::$render_method}();
$value = ob_get_clean();
if ('renderSmarty' === self::$render_method) {
if ($settings['before'] || $settings['after'] || $settings['fallback']) {
$value = "{capture assign='ce_tag'}$value{/capture}" .
'{if strlen($ce_tag)}' .
wp_kses_post($settings['before'] . '{$ce_tag nofilter}' . $settings['after']) .
'{else}' .
$settings['fallback'] .
'{/if}';
}
} elseif ($value) {
if (!empty($settings['before'])) {
$value = wp_kses_post($settings['before']) . $value;
}
if (!empty($settings['after'])) {
$value .= wp_kses_post($settings['after']);
}
if (static::WRAPPED_TAG) {
$id = $this->getId();
$value = '<span id="elementor-tag-' . esc_attr($id) . '" class="elementor-tag">' . $value . '</span>';
}
} elseif (!empty($settings['fallback'])) {
$value = $settings['fallback'];
}
return $value;
}
/**
* @since 2.5.10
* @access protected
*/
protected function renderSmarty()
{
$this->render();
}
/**
* @since 2.0.0
* @access public
*/
final public function getContentType()
{
return 'ui';
}
/**
* @since 2.0.9
* @access public
*/
public function getEditorConfig()
{
$config = parent::getEditorConfig();
$config['wrapped_tag'] = $this::WRAPPED_TAG;
return $config;
}
/**
* @since 2.0.0
* @access protected
*/
protected function registerAdvancedSection()
{
$this->startControlsSection(
'advanced',
[
'label' => __('Advanced'),
]
);
$this->addControl(
'before',
[
'label' => __('Before'),
]
);
$this->addControl(
'after',
[
'label' => __('After'),
]
);
$this->addControl(
'fallback',
[
'label' => __('Fallback'),
'separator' => 'before',
]
);
$this->endControlsSection();
}
}

View File

@@ -0,0 +1,314 @@
<?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;
abstract class CoreXFilesXBase
{
const UPLOADS_DIR = 'css/ce/';
const DEFAULT_FILES_DIR = '';
const META_KEY = '';
// private static $wp_uploads_dir = [];
private $files_dir;
private $file_name;
/**
* File path.
*
* Holds the file path.
*
* @access private
*
* @var string
*/
private $path;
/**
* Content.
*
* Holds the file content.
*
* @access private
*
* @var string
*/
private $content;
/**
* @since 2.1.0
* @access public
* @static
*/
public static function getBaseUploadsDir()
{
$wp_upload_dir = wp_upload_dir();
return $wp_upload_dir['basedir'] . '/' . self::UPLOADS_DIR;
}
/**
* @since 2.1.0
* @access public
* @static
*/
public static function getBaseUploadsUrl()
{
$wp_upload_dir = wp_upload_dir();
return $wp_upload_dir['baseurl'] . '/' . self::UPLOADS_DIR;
}
/**
* @since 2.1.0
* @access public
*/
public function __construct($file_name)
{
/**
* Elementor File Name
*
* Filters the File name
*
* @since 2.3.0
*
* @param string $file_name
* @param object $this The file instance, which inherits Elementor\Core\Files
*/
$file_name = apply_filters('elementor/files/file_name', $file_name, $this);
$this->setFileName($file_name);
$this->setFilesDir(static::DEFAULT_FILES_DIR);
$this->setPath();
}
/**
* @since 2.1.0
* @access public
*/
public function setFilesDir($files_dir)
{
$this->files_dir = $files_dir;
}
/**
* @since 2.1.0
* @access public
*/
public function setFileName($file_name)
{
$this->file_name = $file_name;
}
/**
* @since 2.1.0
* @access public
*/
public function getFileName()
{
return $this->file_name;
}
/**
* @since 2.1.0
* @access public
*/
public function getUrl()
{
$url = self::getBaseUploadsUrl() . $this->files_dir . $this->file_name;
return add_query_arg(['v' => $this->getMeta('time')], $url);
}
/**
* @since 2.1.0
* @access public
*/
public function getContent()
{
if (!$this->content) {
$this->content = $this->parseContent();
}
return $this->content;
}
/**
* @since 2.1.0
* @access public
*/
public function update()
{
$this->updateFile();
$meta = $this->getMeta();
$meta['time'] = time();
$this->updateMeta($meta);
}
/**
* @since 2.1.0
* @access public
*/
public function updateFile()
{
$this->content = $this->parseContent();
// CE Fix: global fonts aren't updated
$this->delete();
if ($this->content) {
$this->write();
} else {
// $this->delete();
}
}
/**
* @since 2.1.0
* @access public
*/
public function write()
{
return file_put_contents($this->path, $this->content);
}
/**
* @since 2.1.0
* @access public
*/
public function delete()
{
if (file_exists($this->path)) {
unlink($this->path);
}
$this->deleteMeta();
}
/**
* Get meta data.
*
* Retrieve the CSS file meta data. Returns an array of all the data, or if
* custom property is given it will return the property value, or `null` if
* the property does not exist.
*
* @since 2.1.0
* @access public
*
* @param string $property Optional. Custom meta data property. Default is
* null.
*
* @return array|null An array of all the data, or if custom property is
* given it will return the property value, or `null` if
* the property does not exist.
*/
public function getMeta($property = null)
{
$default_meta = $this->getDefaultMeta();
$meta = array_merge($default_meta, (array) $this->loadMeta());
if ($property) {
return isset($meta[$property]) ? $meta[$property] : null;
}
return $meta;
}
/**
* @since 2.1.0
* @access protected
* @abstract
*/
abstract protected function parseContent();
/**
* Load meta.
*
* Retrieve the file meta data.
*
* @since 2.1.0
* @access protected
*/
protected function loadMeta()
{
return get_option(static::META_KEY);
}
/**
* Update meta.
*
* Update the file meta data.
*
* @since 2.1.0
* @access protected
*
* @param array $meta New meta data.
*/
protected function updateMeta($meta)
{
update_option(static::META_KEY, $meta);
}
/**
* Delete meta.
*
* Delete the file meta data.
*
* @since 2.1.0
* @access protected
*/
protected function deleteMeta()
{
delete_option(static::META_KEY);
}
/**
* @since 2.1.0
* @access protected
*/
protected function getDefaultMeta()
{
return [
'time' => 0,
];
}
// private static function getWpUploadsDir()
/**
* @since 2.1.0
* @access private
*/
private function setPath()
{
$dir_path = self::getBaseUploadsDir() . $this->files_dir;
if (!is_dir($dir_path)) {
@mkdir($dir_path, 0775, true);
}
$this->path = $dir_path . $this->file_name;
}
public function getPath()
{
return $this->path;
}
}

View File

@@ -0,0 +1,718 @@
<?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\CoreXDynamicTagsXManager as Manager;
use CE\CoreXDynamicTagsXTag as Tag;
use CE\CoreXFilesXBase as BaseFile;
use CE\CoreXResponsiveXResponsive as Responsive;
/**
* Elementor CSS file.
*
* Elementor CSS file handler class is responsible for generating CSS files.
*
* @since 1.2.0
* @abstract
*/
abstract class CoreXFilesXCSSXBase extends BaseFile
{
/**
* Elementor CSS file generated status.
*
* The parsing result after generating CSS file.
*/
const CSS_STATUS_FILE = 'file';
/**
* Elementor inline CSS status.
*
* The parsing result after generating inline CSS.
*/
const CSS_STATUS_INLINE = 'inline';
/**
* Elementor CSS empty status.
*
* The parsing result when an empty CSS returned.
*/
const CSS_STATUS_EMPTY = 'empty';
/**
* Fonts.
*
* Holds the list of fonts.
*
* @access private
*
* @var array
*/
private $fonts = [];
/**
* Stylesheet object.
*
* Holds the CSS file stylesheet instance.
*
* @access protected
*
* @var Stylesheet
*/
protected $stylesheet_obj;
/**
* Printed.
*
* Holds the list of printed files.
*
* @access protected
*
* @var array
*/
private static $printed = [];
/**
* Get CSS file name.
*
* Retrieve the CSS file name.
*
* @since 1.6.0
* @access public
* @abstract
*/
abstract public function getName();
/**
* CSS file constructor.
*
* Initializing Elementor CSS file.
*
* @since 1.2.0
* @access public
*/
public function __construct($file_name)
{
parent::__construct($file_name);
$this->initStylesheet();
}
/**
* Use external file.
*
* Whether to use external CSS file of not. When there are new schemes or settings
* updates.
*
* @since 1.9.0
* @access protected
*
* @return bool True if the CSS requires an update, False otherwise.
*/
protected function useExternalFile()
{
return 'internal' !== get_option('elementor_css_print_method');
}
/**
* Update the CSS file.
*
* Delete old CSS, parse the CSS, save the new file and update the database.
*
* This method also sets the CSS status to be used later on in the render posses.
*
* @since 1.2.0
* @access public
*/
public function update()
{
$this->updateFile();
$meta = $this->getMeta();
$meta['time'] = time();
$content = $this->getContent();
if (empty($content)) {
$meta['status'] = self::CSS_STATUS_EMPTY;
$meta['css'] = '';
} else {
$use_external_file = $this->useExternalFile();
if ($use_external_file) {
$meta['status'] = self::CSS_STATUS_FILE;
$meta['css'] = '';
} else {
$meta['status'] = self::CSS_STATUS_INLINE;
$meta['css'] = $content;
}
}
$this->updateMeta($meta);
}
/**
* @since 2.1.0
* @access public
*/
public function write()
{
if ($this->useExternalFile()) {
parent::write();
}
}
/**
* Enqueue CSS.
*
* Either enqueue the CSS file in Elementor or add inline style.
*
* This method is also responsible for loading the fonts.
*
* @since 1.2.0
* @access public
*/
public function enqueue()
{
$handle_id = $this->getFileHandleId();
if (isset(self::$printed[$handle_id])) {
return;
}
self::$printed[$handle_id] = true;
$meta = $this->getMeta();
if (self::CSS_STATUS_EMPTY === $meta['status']) {
return;
}
// First time after clear cache and etc.
if ('' === $meta['status'] || $this->isUpdateRequired()) {
$this->update();
$meta = $this->getMeta();
}
if (self::CSS_STATUS_INLINE === $meta['status']) {
$dep = $this->getInlineDependency();
wp_add_inline_style($dep, $meta['css']);
} elseif (self::CSS_STATUS_FILE === $meta['status']) {
// Re-check if it's not empty after CSS update.
wp_enqueue_style($this->getFileHandleId(), $this->getUrl(), $this->getEnqueueDependencies(), null);
}
// Handle fonts.
if (!empty($meta['fonts'])) {
foreach ($meta['fonts'] as $font) {
Plugin::$instance->frontend->enqueueFont($font);
}
}
$name = $this->getName();
/**
* Enqueue CSS file.
*
* Fires when CSS file is enqueued on Elementor.
*
* The dynamic portion of the hook name, `$name`, refers to the CSS file name.
*
* @since 2.0.0
*
* @param Base $this The current CSS file.
*/
do_action("elementor/css-file/{$name}/enqueue", $this);
}
/**
* Print CSS.
*
* Output the final CSS inside the `<style>` tags and all the frontend fonts in
* use.
*
* @since 1.9.4
* @access public
*/
public function printCss()
{
echo '<style>' . $this->getContent() . '</style>'; // XSS ok.
Plugin::$instance->frontend->printFontsLinks();
}
/**
* Add control rules.
*
* Parse the CSS for all the elements inside any given control.
*
* This method recursively renders the CSS for all the selectors in the control.
*
* @since 1.2.0
* @access public
*
* @param array $control The controls.
* @param array $controls_stack The controls stack.
* @param callable $value_callback Callback function for the value.
* @param array $placeholders Placeholders.
* @param array $replacements Replacements.
*/
public function addControlRules(array $control, array $controls_stack, callable $value_callback, array $placeholders, array $replacements)
{
$value = call_user_func($value_callback, $control);
if (null === $value || empty($control['selectors'])) {
return;
}
foreach ($control['selectors'] as $selector => $css_property) {
try {
$output_css_property = preg_replace_callback(
'/\{\{(?:([^.}]+)\.)?([^}| ]*)(?: *\|\| *(?:([^.}]+)\.)?([^}| ]*) *)*}}/',
function ($matches) use ($control, $value_callback, $controls_stack, $value, $css_property) {
$external_control_missing = $matches[1] && !isset($controls_stack[$matches[1]]);
$parsed_value = '';
if (!$external_control_missing) {
$parsed_value = $this->parsePropertyPlaceholder($control, $value, $controls_stack, $value_callback, $matches[2], $matches[1]);
}
if ('' === $parsed_value) {
if (isset($matches[4])) {
$parsed_value = $matches[4];
$is_string_value = preg_match('/^([\'"])(.*)\1$/', $parsed_value, $string_matches);
if ($is_string_value) {
$parsed_value = $string_matches[2];
} elseif (!is_numeric($parsed_value)) {
if ($matches[3] && !isset($controls_stack[$matches[3]])) {
return '';
}
$parsed_value = $this->parsePropertyPlaceholder($control, $value, $controls_stack, $value_callback, $matches[4], $matches[3]);
}
}
if ('' === $parsed_value) {
if ($external_control_missing) {
return '';
}
throw new \Exception();
}
}
return $parsed_value;
},
$css_property
);
} catch (\Exception $e) {
return;
}
if (!$output_css_property) {
continue;
}
$device_pattern = '/^(?:\([^\)]+\)){1,2}/';
preg_match($device_pattern, $selector, $device_rules);
$query = [];
if ($device_rules) {
$selector = preg_replace($device_pattern, '', $selector);
preg_match_all('/\(([^\)]+)\)/', $device_rules[0], $pure_device_rules);
$pure_device_rules = $pure_device_rules[1];
foreach ($pure_device_rules as $device_rule) {
if (ElementBase::RESPONSIVE_DESKTOP === $device_rule) {
continue;
}
$device = preg_replace('/\+$/', '', $device_rule);
$endpoint = $device === $device_rule ? 'max' : 'min';
$query[$endpoint] = $device;
}
}
$parsed_selector = str_replace($placeholders, $replacements, $selector);
if (!$query && !empty($control['responsive'])) {
$query = array_intersect_key($control['responsive'], array_flip(['min', 'max']));
if (!empty($query['max']) && ElementBase::RESPONSIVE_DESKTOP === $query['max']) {
unset($query['max']);
}
}
$this->stylesheet_obj->addRules($parsed_selector, $output_css_property, $query);
}
}
/**
* @param array $control
* @param mixed $value
* @param array $controls_stack
* @param callable $value_callback
* @param string $placeholder
* @param string $parser_control_name
*
* @return string
*/
public function parsePropertyPlaceholder(array $control, $value, array $controls_stack, $value_callback, $placeholder, $parser_control_name = null)
{
if ($parser_control_name) {
$control = $controls_stack[$parser_control_name];
$value = call_user_func($value_callback, $control);
}
if (ControlsManager::FONT === $control['type']) {
$this->fonts[] = $value;
}
/** @var BaseDataControl $control_obj */
$control_obj = Plugin::$instance->controls_manager->getControl($control['type']);
return (string) $control_obj->getStyleValue($placeholder, $value, $control);
}
/**
* Get the fonts.
*
* Retrieve the list of fonts.
*
* @since 1.9.0
* @access public
*
* @return array Fonts.
*/
public function getFonts()
{
return $this->fonts;
}
/**
* Get stylesheet.
*
* Retrieve the CSS file stylesheet instance.
*
* @since 1.2.0
* @access public
*
* @return Stylesheet The stylesheet object.
*/
public function getStylesheet()
{
return $this->stylesheet_obj;
}
/**
* Add controls stack style rules.
*
* Parse the CSS for all the elements inside any given controls stack.
*
* This method recursively renders the CSS for all the child elements in the stack.
*
* @since 1.6.0
* @access public
*
* @param ControlsStack $controls_stack The controls stack.
* @param array $controls Controls array.
* @param array $values Values array.
* @param array $placeholders Placeholders.
* @param array $replacements Replacements.
* @param array $all_controls All controls.
*/
public function addControlsStackStyleRules(ControlsStack $controls_stack, array $controls, array $values, array $placeholders, array $replacements, array $all_controls = null)
{
if (!$all_controls) {
$all_controls = $controls_stack->getControls();
}
$parsed_dynamic_settings = $controls_stack->parseDynamicSettings($values, $controls);
foreach ($controls as $control) {
if (!empty($control['style_fields'])) {
$this->addRepeaterControlStyleRules($controls_stack, $control, $values[$control['name']], $placeholders, $replacements);
}
if (!empty($control['__dynamic__'][$control['name']])) {
$this->addDynamicControlStyleRules($control, $control['__dynamic__'][$control['name']]);
}
if (!empty($parsed_dynamic_settings['__dynamic__'][$control['name']])) {
unset($parsed_dynamic_settings[$control['name']]);
continue;
}
if (empty($control['selectors'])) {
continue;
}
$this->addControlStyleRules($control, $parsed_dynamic_settings, $all_controls, $placeholders, $replacements);
}
}
/**
* Get file handle ID.
*
* Retrieve the file handle ID.
*
* @since 1.2.0
* @access protected
* @abstract
*
* @return string CSS file handle ID.
*/
abstract protected function getFileHandleId();
/**
* Render CSS.
*
* Parse the CSS.
*
* @since 1.2.0
* @access protected
* @abstract
*/
abstract protected function renderCss();
protected function getDefaultMeta()
{
return array_merge(parent::getDefaultMeta(), [
'fonts' => array_unique($this->fonts),
'status' => '',
]);
}
/**
* Get enqueue dependencies.
*
* Retrieve the name of the stylesheet used by `wp_enqueue_style()`.
*
* @since 1.2.0
* @access protected
*
* @return array Name of the stylesheet.
*/
protected function getEnqueueDependencies()
{
return [];
}
/**
* Get inline dependency.
*
* Retrieve the name of the stylesheet used by `wp_add_inline_style()`.
*
* @since 1.2.0
* @access protected
*
* @return string Name of the stylesheet.
*/
protected function getInlineDependency()
{
return '';
}
/**
* Is update required.
*
* Whether the CSS requires an update. When there are new schemes or settings
* updates.
*
* @since 1.2.0
* @access protected
*
* @return bool True if the CSS requires an update, False otherwise.
*/
protected function isUpdateRequired()
{
return false;
}
/**
* Parse CSS.
*
* Parsing the CSS file.
*
* @since 1.2.0
* @access protected
*/
protected function parseContent()
{
$this->renderCss();
$name = $this->getName();
/**
* Parse CSS file.
*
* Fires when CSS file is parsed on Elementor.
*
* The dynamic portion of the hook name, `$name`, refers to the CSS file name.
*
* @since 2.0.0
*
* @param Base $this The current CSS file.
*/
do_action("elementor/css-file/{$name}/parse", $this);
return $this->stylesheet_obj->__toString();
}
/**
* Add control style rules.
*
* Register new style rules for the control.
*
* @since 1.6.0
* @access private
*
* @param array $control The control.
* @param array $values Values array.
* @param array $controls The controls stack.
* @param array $placeholders Placeholders.
* @param array $replacements Replacements.
*/
protected function addControlStyleRules(array $control, array $values, array $controls, array $placeholders, array $replacements)
{
$this->addControlRules(
$control,
$controls,
function ($control) use ($values) {
return $this->getStyleControlValue($control, $values);
},
$placeholders,
$replacements
);
}
/**
* Get style control value.
*
* Retrieve the value of the style control for any give control and values.
*
* It will retrieve the control name and return the style value.
*
* @since 1.6.0
* @access private
*
* @param array $control The control.
* @param array $values Values array.
*
* @return mixed Style control value.
*/
private function getStyleControlValue(array $control, array $values)
{
$value = $values[$control['name']];
// fix for background image
if (!empty($value['url']) && (strrpos($control['name'], '_image') !== false || 'background_video_fallback' === $control['name'])) {
$value['url'] = Helper::getMediaLink($value['url']);
}
if (isset($control['selectors_dictionary'][$value])) {
$value = $control['selectors_dictionary'][$value];
}
if (!is_numeric($value) && !is_float($value) && empty($value)) {
return null;
}
return $value;
}
/**
* Init stylesheet.
*
* Initialize CSS file stylesheet by creating a new `Stylesheet` object and register new
* breakpoints for the stylesheet.
*
* @since 1.2.0
* @access private
*/
private function initStylesheet()
{
$this->stylesheet_obj = new Stylesheet();
$breakpoints = Responsive::getBreakpoints();
$this->stylesheet_obj
->addDevice('mobile', 0)
->addDevice('tablet', $breakpoints['md'])
->addDevice('desktop', $breakpoints['lg']);
}
/**
* Add repeater control style rules.
*
* Register new style rules for the repeater control.
*
* @since 2.0.0
* @access private
*
* @param ControlsStack $controls_stack The control stack.
* @param array $repeater_control The repeater control.
* @param array $repeater_values Repeater values array.
* @param array $placeholders Placeholders.
* @param array $replacements Replacements.
*/
protected function addRepeaterControlStyleRules(ControlsStack $controls_stack, array $repeater_control, array $repeater_values, array $placeholders, array $replacements)
{
$placeholders = array_merge($placeholders, ['{{CURRENT_ITEM}}']);
foreach ($repeater_control['style_fields'] as $index => $item) {
$this->addControlsStackStyleRules(
$controls_stack,
$item,
$repeater_values[$index],
$placeholders,
array_merge($replacements, ['.elementor-repeater-item-' . $repeater_values[$index]['_id']]),
$repeater_control['fields']
);
}
}
/**
* Add dynamic control style rules.
*
* Register new style rules for the dynamic control.
*
* @since 2.0.0
* @access private
*
* @param array $control The control.
* @param string $value The value.
*/
protected function addDynamicControlStyleRules(array $control, $value)
{
Plugin::$instance->dynamic_tags->parseTagsText($value, $control, function ($id, $name, $settings) {
$tag = Plugin::$instance->dynamic_tags->createTag($id, $name, $settings);
if (!$tag instanceof Tag) {
return;
}
$this->addControlsStackStyleRules($tag, $tag->getStyleControls(), $tag->getActiveSettings(), ['{{WRAPPER}}'], ['#elementor-tag-' . $id]);
});
}
}

View File

@@ -0,0 +1,165 @@
<?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\CoreXFilesXCSSXBase as Base;
/**
* Elementor global CSS file.
*
* Elementor CSS file handler class is responsible for generating the global CSS
* file.
*
* @since 1.2.0
*/
class CoreXFilesXCSSXGlobalCSS extends Base
{
/**
* Elementor global CSS file handler ID.
*/
const FILE_HANDLER_ID = 'elementor-global';
const META_KEY = '_elementor_global_css';
/**
* Get CSS file name.
*
* Retrieve the CSS file name.
*
* @since 1.6.0
* @access public
*
* @return string CSS file name.
*/
public function getName()
{
return 'global';
}
/**
* Get file handle ID.
*
* Retrieve the handle ID for the global post CSS file.
*
* @since 1.2.0
* @access protected
*
* @return string CSS file handle ID.
*/
protected function getFileHandleId()
{
return self::FILE_HANDLER_ID;
}
/**
* Render CSS.
*
* Parse the CSS for all the widgets and all the scheme controls.
*
* @since 1.2.0
* @access protected
*/
protected function renderCss()
{
do_action("ce/css-file/{$this->getName()}/before_render", $this);
$this->renderSchemesCss();
}
/**
* Get inline dependency.
*
* Retrieve the name of the stylesheet used by `wp_add_inline_style()`.
*
* @since 1.2.0
* @access protected
*
* @return string Name of the stylesheet.
*/
protected function getInlineDependency()
{
return 'elementor-frontend';
}
/**
* Is update required.
*
* Whether the CSS requires an update. When there are new schemes or settings
* updates.
*
* @since 1.2.0
* @access protected
*
* @return bool True if the CSS requires an update, False otherwise.
*/
protected function isUpdateRequired()
{
$file_last_updated = $this->getMeta('time');
$schemes_last_update = get_option(SchemeBase::LAST_UPDATED_META);
if ($file_last_updated < $schemes_last_update) {
return true;
}
// $elementor_settings_last_updated = get_option(Settings::UPDATE_TIME_FIELD);
// if ($file_last_updated < $elementor_settings_last_updated) {
// return true;
// }
return false;
}
/**
* Render schemes CSS.
*
* Parse the CSS for all the widgets and all the scheme controls.
*
* @since 1.2.0
* @access private
*/
private function renderSchemesCss()
{
$elementor = Plugin::$instance;
foreach ($elementor->widgets_manager->getWidgetTypes() as $widget) {
$scheme_controls = $widget->getSchemeControls();
foreach ($scheme_controls as $control) {
$this->addControlRules(
$control,
$widget->getControls(),
function ($control) use ($elementor) {
$scheme_value = $elementor->schemes_manager->getSchemeValue($control['scheme']['type'], $control['scheme']['value']);
if (empty($scheme_value)) {
return null;
}
if (!empty($control['scheme']['key'])) {
$scheme_value = $scheme_value[$control['scheme']['key']];
}
if (empty($scheme_value)) {
return null;
}
return $scheme_value;
},
['{{WRAPPER}}'],
['.elementor-widget-' . $widget->getName()]
);
}
}
}
}

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,124 @@
<?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\CoreXFilesXCSSXPost as Post;
/**
* Elementor post preview CSS file.
*
* Elementor CSS file handler class is responsible for generating the post
* preview CSS file.
*
* @since 1.9.0
*/
class CoreXFilesXCSSXPostPreview extends Post
{
/**
* Preview ID.
*
* Holds the ID of the current post being previewed.
*
* @var int
*/
private $preview_id;
/**
* Post preview CSS file constructor.
*
* Initializing the CSS file of the post preview. Set the post ID and the
* parent ID and initiate the stylesheet.
*
* @since 1.9.0
* @access public
*
* @param int $post_id Post ID.
*/
public function __construct($post_id)
{
$this->preview_id = $post_id;
$parent_id = wp_get_post_parent_id($post_id);
parent::__construct($parent_id);
}
/**
* @since 2.1.0
* @access public
*/
public function getPreviewId()
{
return $this->preview_id;
}
/**
* Get data.
*
* Retrieve raw post data from the database.
*
* @since 1.9.0
* @access protected
*
* @return array Post data.
*/
protected function getData()
{
return Plugin::$instance->db->getPlainEditor($this->preview_id);
}
/**
* Get file handle ID.
*
* Retrieve the handle ID for the previewed post CSS file.
*
* @since 1.9.0
* @access protected
*
* @return string CSS file handle ID.
*/
protected function getFileHandleId()
{
return 'elementor-preview-' . $this->preview_id;
}
/**
* Get meta data.
*
* Retrieve the previewed post CSS file meta data.
*
* @since 1.9.0
* @access public
*
* @param string $property Optional. Custom meta data property. Default is
* null.
*
* @return array Previewed post CSS file meta data.
*/
public function getMeta($property = null)
{
// Parse CSS first, to get the fonts list.
$css = $this->getContent();
$meta = [
'status' => self::CSS_STATUS_INLINE,
'fonts' => $this->getFonts(),
'css' => $css,
];
if ($property) {
return isset($meta[$property]) ? $meta[$property] : null;
}
return $meta;
}
}

View File

@@ -0,0 +1,347 @@
<?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\CoreXFilesXCSSXBase as Base;
/**
* Elementor post CSS file.
*
* Elementor CSS file handler class is responsible for generating the single
* post CSS file.
*
* @since 1.2.0
*/
class CoreXFilesXCSSXPost extends Base
{
/**
* Elementor post CSS file prefix.
*/
const FILE_PREFIX = '';
const META_KEY = '_elementor_css';
/**
* Post ID.
*
* Holds the current post ID.
*
* @var int
*/
private $post_id;
/**
* Post CSS file constructor.
*
* Initializing the CSS file of the post. Set the post ID and initiate the stylesheet.
*
* @since 1.2.0
* @access public
*
* @param int $post_id Post ID.
*/
public function __construct($post_id)
{
$this->post_id = $post_id;
parent::__construct(self::FILE_PREFIX . $post_id . '.css');
}
/**
* Get CSS file name.
*
* Retrieve the CSS file name.
*
* @since 1.6.0
* @access public
*
* @return string CSS file name.
*/
public function getName()
{
return 'post';
}
/**
* Get post ID.
*
* Retrieve the ID of current post.
*
* @since 1.2.0
* @access public
*
* @return int Post ID.
*/
public function getPostId()
{
return $this->post_id;
}
/**
* Get unique element selector.
*
* Retrieve the unique selector for any given element.
*
* @since 1.2.0
* @access public
*
* @param ElementBase $element The element.
*
* @return string Unique element selector.
*/
public function getElementUniqueSelector(ElementBase $element)
{
return '.elementor-' . $this->post_id . ' .elementor-element' . $element->getUniqueSelector();
}
public function getTransformHoverSelector(ElementBase $element)
{
switch ($element->getSettings('_transform_trigger_hover')) {
case 'miniature':
$selector = "[data-elementor-type$=miniature] > :hover {$element->getUniqueSelector()} > .elementor-widget-container";
break;
case 'section':
$selector = ".elementor-section:hover > .elementor-container > * > * > .elementor-column-wrap > * > {$element->getUniqueSelector()} > .elementor-widget-container";
break;
case 'column':
$selector = ".elementor-column-wrap:hover > * > {$element->getUniqueSelector()} > .elementor-widget-container";
break;
default:
$selector = "{$element->getUniqueSelector()} > .elementor-widget-container:hover";
break;
}
return $selector;
}
/**
* Load meta data.
*
* Retrieve the post CSS file meta data.
*
* @since 1.2.0
* @access protected
*
* @return array Post CSS file meta data.
*/
protected function loadMeta()
{
return get_post_meta($this->post_id, static::META_KEY, true);
}
/**
* Update meta data.
*
* Update the global CSS file meta data.
*
* @since 1.2.0
* @access protected
*
* @param array $meta New meta data.
*/
protected function updateMeta($meta)
{
update_post_meta($this->post_id, static::META_KEY, $meta);
}
/**
* Delete meta.
*
* Delete the file meta data.
*
* @since 2.1.0
* @access protected
*/
protected function deleteMeta()
{
delete_post_meta($this->post_id, static::META_KEY);
}
/**
* Get post data.
*
* Retrieve raw post data from the database.
*
* @since 1.9.0
* @access protected
*
* @return array Post data.
*/
protected function getData()
{
return Plugin::$instance->db->getPlainEditor($this->post_id);
}
/**
* Render CSS.
*
* Parse the CSS for all the elements.
*
* @since 1.2.0
* @access protected
*/
protected function renderCss()
{
$data = $this->getData();
if (!empty($data)) {
foreach ($data as $element_data) {
$element = Plugin::$instance->elements_manager->createElementInstance($element_data);
if (!$element) {
continue;
}
$this->renderStyles($element);
}
}
}
/**
* Enqueue CSS.
*
* Enqueue the post CSS file in Elementor.
*
* This method ensures that the post was actually built with elementor before
* enqueueing the post CSS file.
*
* @since 1.2.2
* @access public
*/
public function enqueue()
{
if (!Plugin::$instance->db->isBuiltWithElementor($this->post_id)) {
return;
}
parent::enqueue();
}
/**
* Add controls-stack style rules.
*
* Parse the CSS for all the elements inside any given controls stack.
*
* This method recursively renders the CSS for all the child elements in the stack.
*
* @since 1.6.0
* @access public
*
* @param ControlsStack $controls_stack The controls stack.
* @param array $controls Controls array.
* @param array $values Values array.
* @param array $placeholders Placeholders.
* @param array $replacements Replacements.
* @param array $all_controls All controls.
*/
public function addControlsStackStyleRules(ControlsStack $controls_stack, array $controls, array $values, array $placeholders, array $replacements, array $all_controls = null)
{
parent::addControlsStackStyleRules($controls_stack, $controls, $values, $placeholders, $replacements, $all_controls);
if ($controls_stack instanceof ElementBase) {
foreach ($controls_stack->getChildren() as $child_element) {
$this->renderStyles($child_element);
}
}
}
/**
* Get enqueue dependencies.
*
* Retrieve the name of the stylesheet used by `wp_enqueue_style()`.
*
* @since 1.2.0
* @access protected
*
* @return array Name of the stylesheet.
*/
protected function getEnqueueDependencies()
{
return ['elementor-frontend'];
}
/**
* Get inline dependency.
*
* Retrieve the name of the stylesheet used by `wp_add_inline_style()`.
*
* @since 1.2.0
* @access protected
*
* @return string Name of the stylesheet.
*/
protected function getInlineDependency()
{
return 'elementor-frontend';
}
/**
* Get file handle ID.
*
* Retrieve the handle ID for the post CSS file.
*
* @since 1.2.0
* @access protected
*
* @return string CSS file handle ID.
*/
protected function getFileHandleId()
{
return 'elementor-post-' . $this->post_id;
}
/**
* Render styles.
*
* Parse the CSS for any given element.
*
* @since 1.2.0
* @access protected
*
* @param ElementBase $element The element.
*/
protected function renderStyles(ElementBase $element)
{
/**
* Before element parse CSS.
*
* Fires before the CSS of the element is parsed.
*
* @since 1.2.0
*
* @param Post $this The post CSS file.
* @param ElementBase $element The element.
*/
do_action('elementor/element/before_parse_css', $this, $element);
$element_settings = $element->getSettings();
$this->addControlsStackStyleRules(
$element,
$element->getStyleControls(null, $element->getParsedDynamicSettings()),
$element_settings,
['{{ID}}', '{{WRAPPER}}', '{{HOVER}}'],
[$element->getId(), $this->getElementUniqueSelector($element), $this->getTransformHoverSelector($element)]
);
/**
* After element parse CSS.
*
* Fires after the CSS of the element is parsed.
*
* @since 1.2.0
*
* @param Post $this The post CSS file.
* @param ElementBase $element The element.
*/
do_action('elementor/element/parse_css', $this, $element);
}
}

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,129 @@
<?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\CoreXFilesXBase as Base;
use CE\CoreXFilesXCSSXGlobalCSS as GlobalCSS;
use CE\CoreXFilesXCSSXPost as PostCSS;
use CE\CoreXResponsiveXFilesXFrontend as Frontend;
/**
* Elementor files manager.
*
* Elementor files manager handler class is responsible for creating files.
*
* @since 1.2.0
*/
class CoreXFilesXManager
{
/**
* Files manager constructor.
*
* Initializing the Elementor files manager.
*
* @since 1.2.0
* @access public
*/
public function __construct()
{
$this->registerActions();
}
/**
* On post delete.
*
* Delete post CSS immediately after a post is deleted from the database.
*
* Fired by `deleted_post` action.
*
* @since 1.2.0
* @access public
*
* @param string $post_id Post ID.
*/
public function onDeletePost($post_id)
{
if (!Utils::isPostSupport($post_id)) {
return;
}
$css_file = new PostCSS($post_id);
$css_file->delete();
}
// public function onExportPostMeta($skip, $meta_key)
/**
* Clear cache.
*
* Delete all meta containing files data. And delete the actual
* files from the upload directory.
*
* @since 1.2.0
* @access public
*/
public function clearCache()
{
if (\Shop::getContext() == \Shop::CONTEXT_ALL) {
\Configuration::deleteByName(GlobalCSS::META_KEY);
\Configuration::deleteByName(Frontend::META_KEY);
} else {
\Configuration::deleteFromContext(GlobalCSS::META_KEY);
\Configuration::deleteFromContext(Frontend::META_KEY);
}
$db = \Db::getInstance();
$table = _DB_PREFIX_ . 'ce_meta';
foreach (\Shop::getContextListShopID() as $id_shop) {
$id_shop = (int) $id_shop;
$id = sprintf('%02d', $id_shop);
$meta_key = $db->escape(PostCSS::META_KEY);
$db->execute("DELETE FROM $table WHERE id LIKE '%$id' AND name = '$meta_key'");
// Delete files.
$path = Base::getBaseUploadsDir() . Base::DEFAULT_FILES_DIR;
foreach (glob("{$path}*$id.css", GLOB_NOSORT) as $file_path) {
\Tools::deleteFile($file_path);
}
foreach (glob("{$path}$id_shop-*.css", GLOB_NOSORT) as $file_path) {
\Tools::deleteFile($file_path);
}
}
/**
* Elementor clear files.
*
* Fires after Elementor clears files
*
* @since 2.1.0
*/
do_action('elementor/core/files/clear_cache');
}
/**
* Register actions.
*
* Register filters and actions for the files manager.
*
* @since 1.2.0
* @access private
*/
private function registerActions()
{
add_action('deleted_post', [$this, 'on_delete_post']);
// add_filter('wxr_export_skip_postmeta', [$this, 'on_export_post_meta'], 10, 2);
}
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
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,129 @@
<?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\CoreXBaseXModule as Module;
/**
* Elementor modules manager.
*
* Elementor modules manager handler class is responsible for registering and
* managing Elementor modules.
*
* @since 1.6.0
*/
class CoreXModulesManager
{
/**
* Registered modules.
*
* Holds the list of all the registered modules.
*
* @since 1.6.0
* @access public
*
* @var array
*/
private $modules = [];
/**
* Modules manager constructor.
*
* Initializing the Elementor modules manager.
*
* @since 1.6.0
* @access public
*/
public function __construct()
{
$modules_namespace_prefix = $this->getModulesNamespacePrefix();
foreach ($this->getModulesNames() as $module_name) {
$class_name = str_replace('-', ' ', $module_name);
$class_name = str_replace(' ', '', ucwords($class_name));
$class_name = $modules_namespace_prefix . '\ModulesX' . $class_name . 'XModule';
/** @var Module $class_name */
if ($class_name::isActive()) {
$this->modules[$module_name] = $class_name::instance();
}
}
}
/**
* Get modules names.
*
* Retrieve the modules names.
*
* @since 2.0.0
* @access public
*
* @return string[] Modules names.
*/
public function getModulesNames()
{
return [
'history',
'library',
'dynamic-tags',
'page-templates',
'catalog',
'creative',
'fonts-manager',
'custom-css',
'motion-effects',
'visibility',
];
}
/**
* Get modules.
*
* Retrieve all the registered modules or a specific module.
*
* @since 2.0.0
* @access public
*
* @param string $module_name Module name.
*
* @return null|Module|Module[] All the registered modules or a specific module.
*/
public function getModules($module_name)
{
if ($module_name) {
if (isset($this->modules[$module_name])) {
return $this->modules[$module_name];
}
return null;
}
return $this->modules;
}
/**
* Get modules namespace prefix.
*
* Retrieve the modules namespace prefix.
*
* @since 2.0.0
* @access protected
*
* @return string Modules namespace prefix.
*/
protected function getModulesNamespacePrefix()
{
return 'CE';
}
}

View File

@@ -0,0 +1,157 @@
<?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\CoreXFilesXBase as Base;
use CE\CoreXResponsiveXResponsive as Responsive;
class CoreXResponsiveXFilesXFrontend extends Base
{
const META_KEY = 'elementor-custom-breakpoints-files';
private $template_file;
/**
* @since 2.1.0
* @access public
*/
public function __construct($file_name, $template_file = null)
{
$this->template_file = $template_file;
parent::__construct($file_name);
}
/**
* @since 2.1.0
* @access public
*/
public function parseContent()
{
$breakpoints = Responsive::getBreakpoints();
$breakpoints_keys = array_keys($breakpoints);
$file_content = call_user_func('file_get_contents', $this->template_file);
$file_content = preg_replace_callback('/-width:\s*(767|768|1024|1025)px\s*\)/', function ($placeholder_data) use ($breakpoints_keys, $breakpoints) {
$width = (int) $placeholder_data[1];
$size = $width < 768 ? 'sm' : ($width < 1025 ? 'md' : 'lg');
$breakpoint_index = array_search($size, $breakpoints_keys);
$is_max_point = 767 === $width || 1024 === $width;
if ($is_max_point) {
$breakpoint_index++;
}
$value = $breakpoints[$breakpoints_keys[$breakpoint_index]];
if ($is_max_point) {
$value--;
}
return "-width:{$value}px)";
}, $file_content);
return $file_content;
}
/**
* Load meta.
*
* Retrieve the file meta data.
*
* @since 2.1.0
* @access protected
*/
protected function loadMeta()
{
$option = $this->loadMetaOption();
$file_meta_key = $this->getFileMetaKey();
if (empty($option[$file_meta_key])) {
return [];
}
return $option[$file_meta_key];
}
/**
* Update meta.
*
* Update the file meta data.
*
* @since 2.1.0
* @access protected
*
* @param array $meta New meta data.
*/
protected function updateMeta($meta)
{
$option = $this->loadMetaOption();
$option[$this->getFileMetaKey()] = $meta;
update_option(static::META_KEY, $option);
}
/**
* Delete meta.
*
* Delete the file meta data.
*
* @since 2.1.0
* @access protected
*/
protected function deleteMeta()
{
$option = $this->loadMetaOption();
$file_meta_key = $this->getFileMetaKey();
if (isset($option[$file_meta_key])) {
unset($option[$file_meta_key]);
}
if ($option) {
update_option(static::META_KEY, $option);
} else {
delete_option(static::META_KEY);
}
}
/**
* @since 2.1.0
* @access private
*/
private function getFileMetaKey()
{
return pathinfo($this->getFileName(), PATHINFO_FILENAME);
}
/**
* @since 2.1.0
* @access private
*/
private function loadMetaOption()
{
$option = get_option(static::META_KEY);
if (!$option) {
$option = [];
}
return $option;
}
}

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,192 @@
<?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\CoreXResponsiveXFilesXFrontend as FrontendFile;
/**
* Elementor responsive.
*
* Elementor responsive handler class is responsible for setting up Elementor
* responsive breakpoints.
*
* @since 1.0.0
*/
class CoreXResponsiveXResponsive
{
/**
* The Elementor breakpoint prefix.
*/
const BREAKPOINT_OPTION_PREFIX = 'elementor_viewport_';
/**
* Default breakpoints.
*
* Holds the default responsive breakpoints.
*
* @since 1.0.0
* @access private
* @static
*
* @var array Default breakpoints.
*/
private static $default_breakpoints = [
'xs' => 0,
'sm' => 480,
'md' => 768,
'lg' => 1025,
'xl' => 1440,
'xxl' => 1600,
];
/**
* Editable breakpoint keys.
*
* Holds the editable breakpoint keys.
*
* @since 1.0.0
* @access private
* @static
*
* @var array Editable breakpoint keys.
*/
private static $editable_breakpoints_keys = [
'md',
'lg',
];
/**
* Get default breakpoints.
*
* Retrieve the default responsive breakpoints.
*
* @since 1.0.0
* @access public
* @static
*
* @return array Default breakpoints.
*/
public static function getDefaultBreakpoints()
{
return self::$default_breakpoints;
}
/**
* Get editable breakpoints.
*
* Retrieve the editable breakpoints.
*
* @since 1.0.0
* @access public
* @static
*
* @return array Editable breakpoints.
*/
public static function getEditableBreakpoints()
{
return array_intersect_key(self::getBreakpoints(), array_flip(self::$editable_breakpoints_keys));
}
/**
* Get breakpoints.
*
* Retrieve the responsive breakpoints.
*
* @since 1.0.0
* @access public
* @static
*
* @return array Responsive breakpoints.
*/
public static function getBreakpoints()
{
$self = __CLASS__;
return array_reduce(
array_keys(self::$default_breakpoints),
function ($new_array, $breakpoint_key) use ($self) {
if (!in_array($breakpoint_key, $self::${'editable_breakpoints_keys'})) {
$new_array[$breakpoint_key] = $self::${'default_breakpoints'}[$breakpoint_key];
} else {
$saved_option = get_option($self::BREAKPOINT_OPTION_PREFIX . $breakpoint_key);
$new_array[$breakpoint_key] = $saved_option ? (int) $saved_option : $self::${'default_breakpoints'}[$breakpoint_key];
}
return $new_array;
},
[]
);
}
/**
* @since 2.1.0
* @access public
* @static
*/
public static function hasCustomBreakpoints()
{
return !!array_diff(self::$default_breakpoints, self::getBreakpoints());
}
/**
* @since 2.1.0
* @access public
* @static
*/
public static function getStylesheetTemplatesPath()
{
return _CE_PATH_ . 'views/css/';
}
/**
* @since 2.1.0
* @access public
* @static
*/
public static function compileStylesheetTemplates()
{
foreach (self::getStylesheetTemplates() as $file_name => $template_path) {
$file = new FrontendFile($file_name, $template_path);
$file->update();
}
}
/**
* @since 2.1.0
* @access private
* @static
*/
private static function getStylesheetTemplates()
{
// $templates_paths = glob(self::getStylesheetTemplatesPath() . '*.css');
$stylesheet_path = self::getStylesheetTemplatesPath();
$templates_paths = [
"{$stylesheet_path}frontend.css",
"{$stylesheet_path}frontend.min.css",
"{$stylesheet_path}frontend-rtl.css",
"{$stylesheet_path}frontend-rtl.min.css",
];
$templates = [];
$id_shop = (int) \Context::getContext()->shop->id;
foreach ($templates_paths as $template_path) {
$file_name = "$id_shop-" . basename($template_path);
$templates[$file_name] = $template_path;
}
return apply_filters('elementor/core/responsive/get_stylesheet_templates', $templates);
}
}

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,417 @@
<?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\CoreXFilesXCSSXBase as Base;
/**
* Elementor settings base manager.
*
* Elementor settings base manager handler class is responsible for registering
* and managing Elementor settings base managers.
*
* @since 1.6.0
* @abstract
*/
abstract class CoreXSettingsXBaseXManager
{
/**
* Models cache.
*
* Holds all the models.
*
* @since 1.6.0
* @access private
*
* @var Model[]
*/
private $models_cache = [];
/**
* Settings base manager constructor.
*
* Initializing Elementor settings base manager.
*
* @since 1.6.0
* @access public
*/
public function __construct()
{
add_action('elementor/editor/init', [$this, 'on_elementor_editor_init']);
add_action('elementor/ajax/register_actions', [$this, 'register_ajax_actions']);
$name = $this->getCssFileName();
add_action("elementor/css-file/{$name}/parse", [$this, 'add_settings_css_rules']);
}
/**
* Register ajax actions.
*
* Add new actions to handle data after an ajax requests returned.
*
* Fired by `elementor/ajax/register_actions` action.
*
* @since 2.0.0
* @access public
*
* @param Ajax $ajax_manager
*/
public function registerAjaxActions($ajax_manager)
{
$name = $this->getName();
$ajax_manager->registerAjaxAction("save_{$name}_settings", [$this, 'ajax_save_settings']);
}
/**
* Get model for config.
*
* Retrieve the model for settings configuration.
*
* @since 1.6.0
* @access public
* @abstract
*
* @return Model The model object.
*/
abstract public function getModelForConfig();
/**
* Get manager name.
*
* Retrieve settings manager name.
*
* @since 1.6.0
* @access public
* @abstract
*/
abstract public function getName();
/**
* Get model.
*
* Retrieve the model for any given model ID.
*
* @since 1.6.0
* @access public
*
* @param int $id Optional. Model ID. Default is `0`.
*
* @return Model The model.
*/
final public function getModel($id = 0)
{
$uid = "$id";
if (!isset($this->models_cache[$uid])) {
$this->createModel($uid);
}
return $this->models_cache[$uid];
}
/**
* Ajax request to save settings.
*
* Save settings using an ajax request.
*
* @since 1.6.0
* @access public
*
* @param array $request Ajax request.
*
* @return array Ajax response data.
*/
final public function ajaxSaveSettings($request)
{
$data = $request['data'];
$id = 0;
if (!empty($request['id'])) {
$id = $request['id'];
}
$this->ajaxBeforeSaveSettings($data, $id);
$this->saveSettings($data, $id);
$settings_name = $this->getName();
$success_response_data = [];
/**
* Settings success response data.
*
* Filters the success response data when saving settings using ajax.
*
* The dynamic portion of the hook name, `$settings_name`, refers to the settings name.
*
* @since 2.0.0
*
* @param array $success_response_data Success response data.
* @param int $id Settings ID.
* @param array $data Settings data.
*/
$success_response_data = apply_filters("elementor/settings/{$settings_name}/success_response_data", $success_response_data, $id, $data);
return $success_response_data;
}
/**
* Save settings.
*
* Save settings to the database and update the CSS file.
*
* @since 1.6.0
* @access public
*
* @param array $settings Settings.
* @param int $id Optional. Post ID. Default is `0`.
*/
final public function saveSettings(array $settings, $id = 0)
{
$special_settings = $this->getSpecialSettingsNames();
$settings_to_save = $settings;
foreach ($special_settings as $special_setting) {
if (isset($settings_to_save[$special_setting])) {
unset($settings_to_save[$special_setting]);
}
}
$this->saveSettingsToDb($settings_to_save, $id);
// Clear cache after save.
if (isset($this->models_cache[$id])) {
unset($this->models_cache[$id]);
}
$css_file = $this->getCssFileForUpdate($id);
if ($css_file) {
$css_file->update();
}
}
/**
* Add settings CSS rules.
*
* Add new CSS rules to the settings manager.
*
* Fired by `elementor/css-file/{$name}/parse` action.
*
* @since 1.6.0
* @access public
*
* @param Base $css_file The requested CSS file.
*/
public function addSettingsCssRules(Base $css_file)
{
$model = $this->getModelForCssFile($css_file);
$css_file->addControlsStackStyleRules(
$model,
$model->getStyleControls(),
$model->getSettings(),
['{{WRAPPER}}'],
[$model->getCssWrapperSelector()]
);
}
/**
* On Elementor init.
*
* Add editor template for the settings
*
* Fired by `elementor/init` action.
*
* @since 2.3.0
* @access public
*/
public function onElementorEditorInit()
{
Plugin::$instance->common->addTemplate($this->getEditorTemplate(), 'text');
}
/**
* Get saved settings.
*
* Retrieve the saved settings from the database.
*
* @since 1.6.0
* @access protected
* @abstract
*
* @param int $id Post ID.
*/
abstract protected function getSavedSettings($id);
/**
* Get CSS file name.
*
* Retrieve CSS file name for the settings base manager.
*
* @since 1.6.0
* @access protected
* @abstract
*/
abstract protected function getCssFileName();
/**
* Save settings to DB.
*
* Save settings to the database.
*
* @since 1.6.0
* @access protected
* @abstract
*
* @param array $settings Settings.
* @param int $id Post ID.
*/
abstract protected function saveSettingsToDb(array $settings, $id);
/**
* Get model for CSS file.
*
* Retrieve the model for the CSS file.
*
* @since 1.6.0
* @access protected
* @abstract
*
* @param Base $css_file The requested CSS file.
*/
abstract protected function getModelForCssFile(Base $css_file);
/**
* Get CSS file for update.
*
* Retrieve the CSS file before updating it.
*
* @since 1.6.0
* @access protected
* @abstract
*
* @param int $id Post ID.
*/
abstract protected function getCssFileForUpdate($id);
/**
* Get special settings names.
*
* Retrieve the names of the special settings that are not saved as regular
* settings. Those settings have a separate saving process.
*
* @since 1.6.0
* @access protected
*
* @return array Special settings names.
*/
protected function getSpecialSettingsNames()
{
return [];
}
/**
* Ajax before saving settings.
*
* Validate the data before saving it and updating the data in the database.
*
* @since 1.6.0
* @access public
*
* @param array $data Post data.
* @param int $id Post ID.
*/
public function ajaxBeforeSaveSettings(array $data, $id)
{
}
/**
* Print the setting template content in the editor.
*
* Used to generate the control HTML in the editor using Underscore JS
* template. The variables for the class are available using `data` JS
* object.
*
* @since 1.6.0
* @access protected
*
* @param string $name Settings panel name.
*/
protected function printEditorTemplateContent($name)
{
?>
<div class="elementor-panel-navigation">
<# _.each( elementor.config.settings.<?= esc_html($name) ?>.tabs, function( tabTitle, tabSlug ) { #>
<div class="elementor-panel-navigation-tab elementor-tab-control-{{ tabSlug }}" data-tab="{{ tabSlug }}">
<a href="#">{{{ tabTitle }}}</a>
</div>
<# } ); #>
</div>
<div id="elementor-panel-<?= esc_attr($name) ?>-settings-controls"></div>
<?php
}
/**
* Create model.
*
* Create a new model object for any given model ID and store the object in
* models cache property for later use.
*
* @since 1.6.0
* @access private
*
* @param int $id Model ID.
*/
private function createModel($id)
{
$class_parts = explode('X', get_called_class());
array_splice($class_parts, count($class_parts) - 1, 1, 'Model');
$class_name = implode('X', $class_parts);
$this->models_cache[$id] = new $class_name([
'id' => $id,
'settings' => $this->getSavedSettings($id),
]);
}
/**
* Get editor template.
*
* Retrieve the final HTML for the editor.
*
* @since 1.6.0
* @access private
*
* @return string Settings editor template.
*/
private function getEditorTemplate()
{
$name = $this->getName();
ob_start();
?>
<script type="text/template" id="tmpl-elementor-panel-<?= esc_attr($name) ?>-settings">
<?php $this->printEditorTemplateContent($name) ?>
</script>
<?php
return ob_get_clean();
}
}

View File

@@ -0,0 +1,46 @@
<?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 settings base model.
*
* Elementor settings base model handler class is responsible for registering
* and managing Elementor settings base models.
*
* @since 1.6.0
* @abstract
*/
abstract class CoreXSettingsXBaseXModel extends ControlsStack
{
/**
* Get CSS wrapper selector.
*
* Retrieve the wrapper selector for the current panel.
*
* @since 1.6.0
* @access public
* @abstract
*/
abstract public function getCssWrapperSelector();
/**
* Get panel page settings.
*
* Retrieve the page setting for the current panel.
*
* @since 1.6.0
* @access public
* @abstract
*/
abstract public function getPanelPageSettings();
}

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,223 @@
<?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\CoreXFilesXCSSXBase as Base;
use CE\CoreXFilesXCSSXGlobalCSS as GlobalCSS;
use CE\CoreXSettingsXBaseXManager as BaseManager;
use CE\CoreXSettingsXBaseXModel as BaseModel;
use CE\CoreXSettingsXGeneralXModel as Model;
/**
* Elementor general settings manager.
*
* Elementor general settings manager handler class is responsible for registering
* and managing Elementor general settings managers.
*
* @since 1.6.0
*/
class CoreXSettingsXGeneralXManager extends BaseManager
{
/**
* Lightbox panel tab.
*/
const PANEL_TAB_LIGHTBOX = 'lightbox';
/**
* Meta key for the general settings.
*/
const META_KEY = '_elementor_general_settings';
/**
* General settings manager constructor.
*
* Initializing Elementor general settings manager.
*
* @since 1.6.0
* @access public
*/
public function __construct()
{
parent::__construct();
$this->addPanelTabs();
}
/**
* Get manager name.
*
* Retrieve general settings manager name.
*
* @since 1.6.0
* @access public
*
* @return string Manager name.
*/
public function getName()
{
return 'general';
}
/**
* Get model for config.
*
* Retrieve the model for settings configuration.
*
* @since 1.6.0
* @access public
*
* @return BaseModel The model object.
*/
public function getModelForConfig()
{
return $this->getModel();
}
/**
* Get saved settings.
*
* Retrieve the saved settings from the site options.
*
* @since 1.6.0
* @access protected
*
* @param int $id Post ID.
*
* @return array Saved settings.
*/
protected function getSavedSettings($id)
{
$model_controls = Model::getControlsList();
$settings = [];
foreach ($model_controls as $tab_name => $sections) {
foreach ($sections as $section_name => $section_data) {
foreach ($section_data['controls'] as $control_name => $control_data) {
$saved_setting = get_option($control_name, null);
if (null !== $saved_setting) {
$settings[$control_name] = get_option($control_name);
}
}
}
}
return $settings;
}
/**
* Get CSS file name.
*
* Retrieve CSS file name for the general settings manager.
*
* @since 1.6.0
* @access protected
* @return string
*
* @return string CSS file name.
*/
protected function getCssFileName()
{
return 'global';
}
/**
* Save settings to DB.
*
* Save general settings to the database, as site options.
*
* @since 1.6.0
* @access protected
*
* @param array $settings Settings.
* @param int $id Post ID.
*/
protected function saveSettingsToDb(array $settings, $id)
{
$model_controls = Model::getControlsList();
$one_list_settings = [];
foreach ($model_controls as $tab_name => $sections) {
foreach ($sections as $section_name => $section_data) {
foreach ($section_data['controls'] as $control_name => $control_data) {
if (isset($settings[$control_name])) {
$one_list_control_name = str_replace('elementor_', '', $control_name);
$one_list_settings[$one_list_control_name] = $settings[$control_name];
update_option($control_name, $settings[$control_name]);
} else {
delete_option($control_name);
}
}
}
}
// Save all settings in one list for a future usage
if (!empty($one_list_settings)) {
update_option(self::META_KEY, $one_list_settings);
} else {
delete_option(self::META_KEY);
}
}
/**
* Get model for CSS file.
*
* Retrieve the model for the CSS file.
*
* @since 1.6.0
* @access protected
*
* @param Base $css_file The requested CSS file.
*
* @return BaseModel The model object.
*/
protected function getModelForCssFile(Base $css_file)
{
return $this->getModel();
}
/**
* Get CSS file for update.
*
* Retrieve the CSS file before updating the it.
*
* @since 1.6.0
* @access protected
*
* @param int $id Post ID.
*
* @return GlobalCSS The global CSS file object.
*/
protected function getCssFileForUpdate($id)
{
$id_shop = (int) \Context::getContext()->shop->id;
return new GlobalCSS("$id_shop-global.css");
}
/**
* Add panel tabs.
*
* Register new panel tab for the lightbox settings.
*
* @since 1.6.0
* @access private
*/
private function addPanelTabs()
{
ControlsManager::addTab(self::PANEL_TAB_LIGHTBOX, __('Lightbox'));
}
}

View File

@@ -0,0 +1,337 @@
<?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\CoreXSettingsXBaseXModel as BaseModel;
use CE\CoreXSettingsXGeneralXManager as Manager;
/**
* Elementor global settings model.
*
* Elementor global settings model handler class is responsible for registering
* and managing Elementor global settings models.
*
* @since 1.6.0
*/
class CoreXSettingsXGeneralXModel extends BaseModel
{
/**
* Get model name.
*
* Retrieve global settings model name.
*
* @since 1.6.0
* @access public
*
* @return string Model name.
*/
public function getName()
{
return 'global-settings';
}
/**
* Get CSS wrapper selector.
*
* Retrieve the wrapper selector for the global settings model.
*
* @since 1.6.0
* @access public
*
* @return string CSS wrapper selector.
*/
public function getCssWrapperSelector()
{
return '';
}
/**
* Get panel page settings.
*
* Retrieve the panel setting for the global settings model.
*
* @since 1.6.0
* @access public
*
* @return array {
* Panel settings.
*
* @type string $title The panel title.
* @type array $menu The panel menu.
* }
*/
public function getPanelPageSettings()
{
return [
'title' => __('Global Settings'),
'menu' => [
'icon' => 'fa fa-cogs',
'beforeItem' => 'elementor-settings',
],
];
}
/**
* Get controls list.
*
* Retrieve the global settings model controls list.
*
* @since 1.6.0
* @access public
* @static
*
* @return array Controls list.
*/
public static function getControlsList()
{
return [
ControlsManager::TAB_STYLE => [
'style' => [
'label' => __('Style'),
'controls' => [
'elementor_default_generic_fonts' => [
'label' => __('Default Generic Fonts'),
'type' => ControlsManager::TEXT,
'default' => 'Sans-serif',
'description' => __('The list of fonts used if the chosen font is not available.'),
'label_block' => true,
],
'elementor_container_width' => [
'label' => __('Content Width') . ' (px)',
'type' => ControlsManager::NUMBER,
'min' => 300,
'description' => __('Sets the default width of the content area (Default: 1140)'),
'selectors' => [
'.elementor-section.elementor-section-boxed > .elementor-container' => 'max-width: {{VALUE}}px',
],
],
'elementor_space_between_widgets' => [
'label' => __('Widgets Space') . ' (px)',
'type' => ControlsManager::NUMBER,
'min' => 0,
'placeholder' => '20',
'description' => __('Sets the default space between widgets (Default: 20)'),
'selectors' => [
'.elementor-widget:not(:last-child)' => 'margin-bottom: {{VALUE}}px',
],
],
'elementor_stretched_section_container' => [
'label' => __('Stretched Section Fit To'),
'type' => ControlsManager::TEXT,
'placeholder' => 'body',
'description' => __('Enter parent element selector to which stretched sections will fit to (e.g. #primary / .wrapper / main etc). Leave blank to fit to page width.'),
'label_block' => true,
'frontend_available' => true,
],
'elementor_page_title_selector' => [
'label' => __('Page Title Selector'),
'type' => ControlsManager::TEXTAREA,
'rows' => 1,
'placeholder' => 'header.page-header',
'description' => sprintf(
__("You can hide the title at document settings. This works for themes that have ”%s” selector. If your theme's selector is different, please enter it above."),
'header.page-header'
),
'label_block' => true,
],
'elementor_page_wrapper_selector' => [
'label' => __('Content Wrapper Selector'),
'type' => ControlsManager::TEXTAREA,
'rows' => 3,
'placeholder' => '#content, #wrapper, #wrapper .container',
'description' => sprintf(
__("You can clear margin, padding, max-width from content wrapper at document settings. This works for themes that have ”%s” selector. If your theme's selector is different, please enter it above."),
'#content, #wrapper, #wrapper .container'
),
'label_block' => true,
],
],
],
],
Manager::PANEL_TAB_LIGHTBOX => [
'lightbox' => [
'label' => __('Lightbox'),
'controls' => [
'elementor_global_image_lightbox' => [
'label' => __('Image Lightbox'),
'type' => ControlsManager::SWITCHER,
'return_value' => '1',
'description' => __('Open all image links in a lightbox popup window. The lightbox will automatically work on any link that leads to an image file.'),
'frontend_available' => true,
],
'elementor_enable_lightbox_in_editor' => [
'label' => __('Enable In Editor'),
'type' => ControlsManager::SWITCHER,
'default' => 'yes',
'frontend_available' => true,
],
'elementor_lightbox_enable_counter' => [
'label' => __('Counter'),
'type' => ControlsManager::SWITCHER,
'default' => 'yes',
'frontend_available' => true,
],
'elementor_lightbox_enable_zoom' => [
'label' => __('Zoom'),
'type' => ControlsManager::SWITCHER,
'default' => 'yes',
'frontend_available' => true,
],
'elementor_lightbox_title_src' => [
'label' => __('Title'),
'type' => ControlsManager::SELECT,
'options' => [
'' => __('None'),
'title' => __('Title'),
'caption' => __('Caption'),
'alt' => __('Alt'),
// 'description' => __('Description'),
],
'default' => 'title',
'frontend_available' => true,
],
'elementor_lightbox_description_src' => [
'label' => __('Description'),
'type' => ControlsManager::SELECT,
'options' => [
'' => __('None'),
'title' => __('Title'),
'caption' => __('Caption'),
'alt' => __('Alt'),
// 'description' => __('Description'),
],
'default' => 'caption',
'frontend_available' => true,
],
'elementor_lightbox_color' => [
'label' => __('Background Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'.elementor-lightbox' => 'background-color: {{VALUE}}',
],
],
'elementor_lightbox_ui_color' => [
'label' => __('UI Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'.elementor-lightbox' => '--lightbox-ui-color: {{VALUE}}',
],
],
'elementor_lightbox_ui_color_hover' => [
'label' => __('UI Hover Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'.elementor-lightbox' => '--lightbox-ui-color-hover: {{VALUE}}',
],
],
'elementor_lightbox_text_color' => [
'label' => __('Text Color'),
'type' => ControlsManager::COLOR,
'selectors' => [
'.elementor-lightbox' => '--lightbox-text-color: {{VALUE}}',
],
],
'lightbox_box_shadow_type' => [
'label' => _x('Box Shadow', 'Box Shadow Control'),
'type' => ControlsManager::POPOVER_TOGGLE,
'return_value' => 'yes',
'render_type' => 'ui',
],
'lightbox_box_shadow' => [
'label' => _x('Box Shadow', 'Box Shadow Control'),
'type' => ControlsManager::BOX_SHADOW,
'default' => [
'horizontal' => 0,
'vertical' => 0,
'blur' => 10,
'spread' => 0,
'color' => 'rgba(0,0,0,0.5)',
],
'selectors' => [
'.elementor-lightbox .elementor-lightbox-image' => 'box-shadow: {{HORIZONTAL}}px {{VERTICAL}}px {{BLUR}}px {{SPREAD}}px {{COLOR}} {{lightbox_box_shadow_position.VALUE}};',
],
'condition' => [
'lightbox_box_shadow_type!' => '',
],
'popover' => [
'start' => true,
],
],
'lightbox_box_shadow_position' => [
'label' => 'Position',
'type' => ControlsManager::SELECT,
'options' => [
' ' => 'Outline',
'inset' => 'Inset',
],
'default' => ' ',
'render_type' => 'ui',
'condition' => [
'lightbox_box_shadow_type!' => '',
],
'popover' => [
'end' => true,
],
],
'lightbox_icons_size' => [
'label' => __('Toolbar Icons Size'),
'type' => ControlsManager::SLIDER,
'selectors' => [
'.elementor-lightbox' => '--lightbox-header-icons-size: {{SIZE}}{{UNIT}}',
],
'separator' => 'before',
],
'lightbox_slider_icons_size' => [
'label' => __('Navigation Icons Size'),
'type' => ControlsManager::SLIDER,
'selectors' => [
'.elementor-lightbox' => '--lightbox-navigation-icons-size: {{SIZE}}{{UNIT}}',
],
],
],
],
],
];
}
/**
* Register model controls.
*
* Used to add new controls to the global settings model.
*
* @since 1.6.0
* @access protected
*/
protected function _registerControls()
{
$controls_list = self::getControlsList();
foreach ($controls_list as $tab_name => $sections) {
foreach ($sections as $section_name => $section_data) {
$this->startControlsSection(
$section_name,
[
'label' => $section_data['label'],
'tab' => $tab_name,
]
);
foreach ($section_data['controls'] as $control_name => $control_data) {
$this->addControl($control_name, $control_data);
}
$this->endControlsSection();
}
}
}
}

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,196 @@
<?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\CoreXSettingsXBaseXManager as BaseManager;
/**
* Elementor settings manager.
*
* Elementor settings manager handler class is responsible for registering and
* managing Elementor settings managers.
*
* @since 1.6.0
*/
class CoreXSettingsXManager
{
/**
* Settings managers.
*
* Holds all the registered settings managers.
*
* @since 1.6.0
* @access private
*
* @var BaseManager[]
*/
private static $settings_managers = [];
/**
* Builtin settings managers names.
*
* Holds the names for builtin Elementor settings managers.
*
* @since 1.6.0
* @access private
*
* @var array
*/
private static $builtin_settings_managers_names = ['page', 'general'];
/**
* Add settings manager.
*
* Register a single settings manager to the registered settings managers.
*
* @since 1.6.0
* @access public
* @static
*
* @param BaseManager $manager Settings manager.
*/
public static function addSettingsManager(BaseManager $manager)
{
self::$settings_managers[$manager->getName()] = $manager;
}
/**
* Get settings managers.
*
* Retrieve registered settings manager(s).
*
* If no parameter passed, it will retrieve all the settings managers. For
* any given parameter it will retrieve a single settings manager if one
* exist, or `null` otherwise.
*
* @since 1.6.0
* @access public
* @static
*
* @param string $manager_name Optional. Settings manager name. Default is
* null.
*
* @return BaseManager|BaseManager[] Single settings manager, if it exists,
* null if it doesn't exists, or the all
* the settings managers if no parameter
* defined.
*/
public static function getSettingsManagers($manager_name = null)
{
if ($manager_name) {
if (isset(self::$settings_managers[$manager_name])) {
return self::$settings_managers[$manager_name];
}
return null;
}
return self::$settings_managers;
}
/**
* Register default settings managers.
*
* Register builtin Elementor settings managers.
*
* @since 1.6.0
* @access private
* @static
*/
private static function registerDefaultSettingsManagers()
{
foreach (self::$builtin_settings_managers_names as $manager_name) {
$manager_class = call_user_func('substr', __CLASS__, 0, strrpos(__CLASS__, 'X') + 1) . call_user_func('ucfirst', $manager_name) . 'XManager';
self::addSettingsManager(new $manager_class());
}
}
/**
* Get settings managers config.
*
* Retrieve the settings managers configuration.
*
* @since 1.6.0
* @access public
* @static
*
* @return array The settings managers configuration.
*/
public static function getSettingsManagersConfig()
{
$config = [];
// $user_can = Plugin::instance()->role_manager->userCan('design');
foreach (self::$settings_managers as $name => $manager) {
$settings_model = $manager->getModelForConfig();
$tabs = $settings_model->getTabsControls();
// if (!$user_can) {
// unset($tabs['style']);
// }
$config[$name] = [
'name' => $manager->getName(),
'panelPage' => $settings_model->getPanelPageSettings(),
'cssWrapperSelector' => $settings_model->getCssWrapperSelector(),
'controls' => $settings_model->getControls(),
'tabs' => $tabs,
'settings' => $settings_model->getSettings(),
];
}
return $config;
}
/**
* Get settings frontend config.
*
* Retrieve the settings managers frontend configuration.
*
* @since 1.6.0
* @access public
* @static
*
* @return array The settings managers frontend configuration.
*/
public static function getSettingsFrontendConfig()
{
$config = [];
foreach (self::$settings_managers as $name => $manager) {
$settings_model = $manager->getModelForConfig();
if ($settings_model) {
$config[$name] = $settings_model->getFrontendSettings();
}
}
return $config;
}
/**
* Run settings managers.
*
* Register builtin Elementor settings managers.
*
* @since 1.6.0
* @access public
* @static
*/
public static function run()
{
self::registerDefaultSettingsManagers();
}
}

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,310 @@
<?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\CoreXFilesXCSSXBase as Base;
use CE\CoreXFilesXCSSXPost as Post;
use CE\CoreXFilesXCSSXPostPreview as PostPreview;
use CE\CoreXSettingsXBaseXManager as BaseManager;
use CE\CoreXSettingsXBaseXModel as BaseModel;
use CE\CoreXSettingsXManager as SettingsManager;
use CE\CoreXUtilsXExceptions as Exceptions;
/**
* Elementor page settings manager.
*
* Elementor page settings manager handler class is responsible for registering
* and managing Elementor page settings managers.
*
* @since 1.6.0
*/
class CoreXSettingsXPageXManager extends BaseManager
{
/**
* Meta key for the page settings.
*/
const META_KEY = '_elementor_page_settings';
/**
* Get manager name.
*
* Retrieve page settings manager name.
*
* @since 1.6.0
* @access public
*
* @return string Manager name.
*/
public function getName()
{
return 'page';
}
/**
* Get model for config.
*
* Retrieve the model for settings configuration.
*
* @since 1.6.0
* @access public
*
* @return BaseModel The model object.
*/
public function getModelForConfig()
{
if (!is_singular() && !Plugin::$instance->editor->isEditMode()) {
return null;
}
if (Plugin::$instance->editor->isEditMode()) {
$post_id = Plugin::$instance->editor->getPostId();
$document = Plugin::$instance->documents->getDocOrAutoSave($post_id);
} else {
$post_id = get_the_ID();
$document = Plugin::$instance->documents->getDocForFrontend($post_id);
}
if (!$document) {
return null;
}
$model = $this->getModel($document->getPost()->ID);
if ($document->isAutosave()) {
$model->setSettings('post_status', $document->getMainPost()->post_status);
}
return $model;
}
/**
* Ajax before saving settings.
*
* Validate the data before saving it and updating the data in the database.
*
* @since 1.6.0
* @access public
*
* @param array $data Post data.
* @param int $id Post ID.
*
* @throws \Exception If invalid post returned using the `$id`.
* @throws \Exception If current user don't have permissions to edit the post.
*/
public function ajaxBeforeSaveSettings(array $data, $id)
{
$post = get_post($id);
if (empty($post)) {
throw new \Exception('Invalid post.', Exceptions::NOT_FOUND);
}
if (!current_user_can('edit', $id)) {
throw new \Exception('Access denied.', Exceptions::FORBIDDEN);
}
// Avoid save empty post title.
if (!empty($data['post_title'])) {
$post->post_title = $data['post_title'];
}
// if (isset($data['post_excerpt']) && post_type_supports($post->post_type, 'excerpt')) {
// $post->post_excerpt = $data['post_excerpt'];
// }
if (isset($data['post_status'])) {
// $this->savePostStatus($id, $data['post_status']);
// unset($post->post_status);
$post->post_status = $data['post_status'];
}
wp_update_post($post);
// Check updated status
// if (DB::STATUS_PUBLISH === get_post_status($id))
$autosave = wp_get_post_autosave($post->ID);
if ($autosave) {
wp_delete_post_revision($autosave->ID);
}
if (isset($data['post_featured_image'])) {
if (empty($data['post_featured_image']['url'])) {
delete_post_meta($post->ID, '_og_image');
} else {
update_post_meta($post->ID, '_og_image', $data['post_featured_image']['url']);
}
}
if (Utils::isCptCustomTemplatesSupported($post)) {
$template = get_post_meta($post->ID, '_wp_page_template', true);
if (isset($data['template'])) {
$template = $data['template'];
}
if (empty($template)) {
$template = 'default';
}
update_post_meta($post->ID, '_wp_page_template', $template);
}
}
/**
* Save settings to DB.
*
* Save page settings to the database, as post meta data.
*
* @since 1.6.0
* @access protected
*
* @param array $settings Settings.
* @param int $id Post ID.
*/
protected function saveSettingsToDb(array $settings, $id)
{
if (!empty($settings)) {
update_post_meta($id, self::META_KEY, $settings);
} else {
delete_post_meta($id, self::META_KEY);
}
}
/**
* Get CSS file for update.
*
* Retrieve the CSS file before updating it.
*
* This method overrides the parent method to disallow updating CSS files for pages.
*
* @since 1.6.0
* @access protected
*
* @param int $id Post ID.
*
* @return false Disallow The updating CSS files for pages.
*/
protected function getCssFileForUpdate($id)
{
return false;
}
/**
* Get saved settings.
*
* Retrieve the saved settings from the post meta.
*
* @since 1.6.0
* @access protected
*
* @param int $id Post ID.
*
* @return array Saved settings.
*/
protected function getSavedSettings($id)
{
$settings = get_post_meta($id, self::META_KEY, true);
if (!$settings) {
$settings = [];
}
if (Utils::isCptCustomTemplatesSupported(get_post($id))) {
$saved_template = get_post_meta($id, '_wp_page_template', true);
if ($saved_template) {
$settings['template'] = $saved_template;
}
}
return $settings;
}
/**
* Get CSS file name.
*
* Retrieve CSS file name for the page settings manager.
*
* @since 1.6.0
* @access protected
*
* @return string CSS file name.
*/
protected function getCssFileName()
{
return 'post';
}
/**
* Get model for CSS file.
*
* Retrieve the model for the CSS file.
*
* @since 1.6.0
* @access protected
*
* @param Base $css_file The requested CSS file.
*
* @return BaseModel The model object.
*/
protected function getModelForCssFile(Base $css_file)
{
if (!$css_file instanceof Post) {
return null;
}
$post_id = $css_file->getPostId();
if ($css_file instanceof PostPreview) {
$autosave = Utils::getPostAutosave($post_id);
if ($autosave) {
$post_id = $autosave->ID;
}
}
return $this->getModel($post_id);
}
/**
* Get special settings names.
*
* Retrieve the names of the special settings that are not saved as regular
* settings. Those settings have a separate saving process.
*
* @since 1.6.0
* @access protected
*
* @return array Special settings names.
*/
protected function getSpecialSettingsNames()
{
return [
'id',
'post_title',
'post_status',
'template',
'post_excerpt',
'post_featured_image',
// Do not save:
'action',
'_nonce',
'section_page_settings',
'section_page_style',
'section_custom_css',
'template_default_description',
'template_canvas_description',
];
}
// public function savePostStatus($post_id, $status)
}

View File

@@ -0,0 +1,193 @@
<?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\CoreXSettingsXBaseXModel as BaseModel;
/**
* Elementor page settings model.
*
* Elementor page settings model handler class is responsible for registering
* and managing Elementor page settings models.
*
* @since 1.6.0
*/
class CoreXSettingsXPageXModel extends BaseModel
{
/**
* Wrapper post object.
*
* Holds an instance of `WPPost` containing the post object.
*
* @since 1.6.0
* @access public
*
* @var WPPost
*/
private $post;
/**
* @var WPPost
*/
private $post_parent;
/**
* Model constructor.
*
* Initializing Elementor page settings model.
*
* @since 1.6.0
* @access public
*
* @param array $data Optional. Model data. Default is an empty array.
*/
public function __construct(array $data = [])
{
$this->post = get_post($data['id']);
if (!$this->post) {
$this->post = new WPPost((object) []);
}
if (wp_is_post_revision($this->post->ID)) {
$this->post_parent = get_post($this->post->post_parent);
} else {
$this->post_parent = $this->post;
}
parent::__construct($data);
}
/**
* Get model name.
*
* Retrieve page settings model name.
*
* @since 1.6.0
* @access public
*
* @return string Model name.
*/
public function getName()
{
return 'page-settings';
}
/**
* Get model unique name.
*
* Retrieve page settings model unique name.
*
* @since 1.6.0
* @access public
*
* @return string Model unique name.
*/
public function getUniqueName()
{
return $this->getName() . '-' . $this->post->ID;
}
/**
* Get CSS wrapper selector.
*
* Retrieve the wrapper selector for the page settings model.
*
* @since 1.6.0
* @access public
*
* @return string CSS wrapper selector.
*/
public function getCssWrapperSelector()
{
$document = Plugin::$instance->documents->get($this->post_parent->ID);
return $document->getCssWrapperSelector();
}
/**
* Get panel page settings.
*
* Retrieve the panel setting for the page settings model.
*
* @since 1.6.0
* @access public
*
* @return array {
* Panel settings.
*
* @type string $title The panel title.
* }
*/
public function getPanelPageSettings()
{
$document = Plugin::$instance->documents->get($this->post->ID);
return [
/* translators: %s: Document title */
'title' => sprintf(__('%s Settings'), $document::getTitle()),
];
}
/**
* On export post meta.
*
* When exporting data, check if the post is not using page template and
* exclude it from the exported Elementor data.
*
* @since 1.6.0
* @access public
*
* @param array $element_data Element data.
*
* @return array Element data to be exported.
*/
public function onExport($element_data)
{
if (!empty($element_data['settings']['template'])) {
/**
* @var \Elementor\Modules\PageTemplates\Module $page_templates_module
*/
$page_templates_module = Plugin::$instance->modules_manager->getModules('page-templates');
$is_elementor_template = !!$page_templates_module->getTemplatePath($element_data['settings']['template']);
if (!$is_elementor_template) {
unset($element_data['settings']['template']);
}
}
return $element_data;
}
/**
* Register model controls.
*
* Used to add new controls to the page settings model.
*
* @since 1.6.0
* @access protected
*/
protected function _registerControls()
{
// Check if it's a real model, or abstract (for example - on import )
if ($this->post->ID) {
$document = Plugin::$instance->documents->getDocOrAutoSave($this->post->ID);
if ($document) {
$controls = $document->getControls();
foreach ($controls as $control_id => $args) {
$this->addControl($control_id, $args);
}
}
}
}
}

View File

@@ -0,0 +1,47 @@
<?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 exceptions.
*
* Elementor exceptions handler class is responsible for handling exceptions.
*
* @since 2.0.0
*/
class CoreXUtilsXExceptions
{
/**
* HTTP status code for bad request error.
*/
const BAD_REQUEST = 400;
/**
* HTTP status code for unauthorized access error.
*/
const UNAUTHORIZED = 401;
/**
* HTTP status code for forbidden access error.
*/
const FORBIDDEN = 403;
/**
* HTTP status code for resource that could not be found.
*/
const NOT_FOUND = 404;
/**
* HTTP status code for internal server error.
*/
const INTERNAL_SERVER_ERROR = 500;
}

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,855 @@
<?php
/**
* Creative Elements - live Theme & Page Builder
*
* @author WebshopWorks
* @copyright 2019-2022 WebshopWorks.com
* @license One domain support license
*/
defined('_PS_VERSION_') or die;
define('_CE_VERSION_', '2.5.11');
define('_CE_PATH_', _PS_MODULE_DIR_ . 'creativeelements/');
define('_CE_URL_', defined('_PS_BO_ALL_THEMES_DIR_') ? _MODULE_DIR_ . 'creativeelements/' : 'modules/creativeelements/');
define('_CE_ASSETS_URL_', _CE_URL_ . 'views/');
define('_CE_TEMPLATES_', _CE_PATH_ . 'views/templates/');
/** @deprecated since 2.5.0 - PrestaShop 1.6.x isn't supported */
define('_CE_PS16_', false);
require_once _CE_PATH_ . 'classes/CETheme.php';
require_once _CE_PATH_ . 'classes/CEContent.php';
require_once _CE_PATH_ . 'classes/CETemplate.php';
require_once _CE_PATH_ . 'classes/CEFont.php';
require_once _CE_PATH_ . 'classes/CESmarty.php';
require_once _CE_PATH_ . 'includes/plugin.php';
class CreativeElements extends Module
{
const VIEWED_PRODUCTS_LIMIT = 100;
protected static $controller;
protected static $tplOverride;
protected static $overrides = [
'Category',
'CmsCategory',
'Manufacturer',
'Supplier',
];
public $controllers = [
'ajax',
'preview',
];
public function __construct($name = null, Context $context = null)
{
$this->name = 'creativeelements';
$this->tab = 'content_management';
$this->version = '2.5.11';
$this->author = 'WebshopWorks';
$this->module_key = '7a5ebcc21c1764675f1db5d0f0eacfe5';
$this->ps_versions_compliancy = ['min' => '1.7.0', 'max' => '1.7'];
$this->bootstrap = true;
$this->displayName = $this->l('Creative Elements - live Theme & Page Builder');
$this->description = $this->l('The most advanced frontend drag & drop page builder. Create high-end, pixel perfect websites at record speeds. Any theme, any page, any design.');
parent::__construct($this->name, null);
$this->checkThemeChange();
Shop::addTableAssociation(CETheme::$definition['table'], ['type' => 'shop']);
Shop::addTableAssociation(CETheme::$definition['table'] . '_lang', ['type' => 'fk_shop']);
Shop::addTableAssociation(CEContent::$definition['table'], ['type' => 'shop']);
Shop::addTableAssociation(CEContent::$definition['table'] . '_lang', ['type' => 'fk_shop']);
}
public function install()
{
require_once _CE_PATH_ . 'classes/CEDatabase.php';
if (Shop::isFeatureActive()) {
Shop::setContext(Shop::CONTEXT_ALL);
}
CEDatabase::initConfigs();
if (!CEDatabase::createTables()) {
$this->_errors[] = Db::getInstance()->getMsgError();
return false;
}
if ($res = parent::install() && CEDatabase::updateTabs()) {
foreach (CEDatabase::getHooks() as $hook) {
$res = $res && $this->registerHook($hook, null, 1);
}
}
return $res;
}
public function uninstall()
{
foreach (Tab::getCollectionFromModule($this->name) as $tab) {
$tab->delete();
}
return parent::uninstall();
}
public function enable($force_all = false)
{
return parent::enable($force_all) && Db::getInstance()->update(
'tab',
['active' => 1],
"module = 'creativeelements' AND class_name != 'AdminCEEditor'"
);
}
public function disable($force_all = false)
{
return Db::getInstance()->update(
'tab',
['active' => 0],
"module = 'creativeelements'"
) && parent::disable($force_all);
}
public function addOverride($classname)
{
try {
return parent::addOverride($classname);
} catch (Exception $ex) {
return false;
}
}
public function getContent()
{
Tools::redirectAdmin($this->context->link->getAdminLink('AdminCEThemes'));
}
public function hookDisplayBackOfficeHeader($params = [])
{
Configuration::get("PS_ALLOW_HTML_\x49FRAME") or Configuration::updateValue("PS_ALLOW_HTML_\x49FRAME", 1);
// Handle migrate
if ((Configuration::getGlobalValue('ce_migrate') || Tools::getIsset('CEMigrate')) &&
Db::getInstance()->executeS("SHOW TABLES LIKE '%_ce_meta'")
) {
require_once _CE_PATH_ . 'classes/CEMigrate.php';
CEMigrate::registerJavascripts();
}
$footer_product = '';
preg_match('~/([^/]+)/(\d+)/edit\b~', $_SERVER['REQUEST_URI'], $req);
$controller = Tools::strtolower(Tools::getValue('controller'));
switch ($controller) {
case 'admincetemplates':
$id_type = CE\UId::TEMPLATE;
$id = (int) Tools::getValue('id_ce_template');
break;
case 'admincethemes':
$id_type = CE\UId::THEME;
$id = (int) Tools::getValue('id_ce_theme');
break;
case 'admincecontent':
$id_type = CE\UId::CONTENT;
$id = (int) Tools::getValue('id_ce_content');
break;
case 'admincmscontent':
if ($req && $req[1] == 'category' || Tools::getIsset('addcms_category') || Tools::getIsset('updatecms_category')) {
$id_type = CE\UId::CMS_CATEGORY;
$id = (int) Tools::getValue('id_cms_category', $req ? $req[2] : 0);
break;
}
$id_type = CE\UId::CMS;
$id = (int) Tools::getValue('id_cms', $req ? $req[2] : 0);
break;
case 'adminproducts':
$id_type = CE\UId::PRODUCT;
$id = (int) Tools::getValue('id_product', basename(explode('?', $_SERVER['REQUEST_URI'])[0]));
$footer_product = new CE\UId(CEContent::getFooterProductId($id), CE\UId::CONTENT, 0, $this->context->shop->id);
break;
case 'admincategories':
$id_type = CE\UId::CATEGORY;
$id = (int) Tools::getValue('id_category', $req ? $req[2] : 0);
break;
case 'adminmanufacturers':
$id_type = CE\UId::MANUFACTURER;
$id = (int) Tools::getValue('id_manufacturer', $req ? $req[2] : 0);
break;
case 'adminsuppliers':
$id_type = CE\UId::SUPPLIER;
$id = (int) Tools::getValue('id_supplier', $req ? $req[2] : 0);
break;
case 'adminxippost':
$id_type = CE\UId::XIPBLOG_POST;
$id = (int) Tools::getValue('id_xipposts');
break;
case 'adminstblog':
$id_type = CE\UId::STBLOG_POST;
$id = (int) Tools::getValue('id_st_blog');
break;
case 'adminblogposts':
if ('advanceblog' === $this->context->controller->module->name) {
$id_type = CE\UId::ADVANCEBLOG_POST;
$id = (int) Tools::getValue('id_post');
}
break;
case 'adminpsblogblogs':
$id_type = CE\UId::PSBLOG_POST;
$id = (int) Tools::getValue('id_psblog_blog');
break;
case 'admintvcmspost':
$id_type = CE\UId::TVCMSBLOG_POST;
$id = (int) Tools::getValue('id_tvcmsposts');
break;
case 'adminmodules':
$configure = Tools::strtolower(Tools::getValue('configure'));
if ('ybc_blog' == $configure && Tools::getValue('control') == 'post') {
$id_type = CE\UId::YBC_BLOG_POST;
$id = (int) Tools::getValue('id_post');
break;
}
if ('prestablog' == $configure && Tools::getIsset('editNews')) {
$id_type = CE\UId::PRESTABLOG_POST;
$id = (int) Tools::getValue('idN');
break;
}
if ('hiblog' == $configure) {
$id_type = CE\UId::HIBLOG_POST;
$id = 0;
$hideEditor = [];
break;
}
break;
case 'adminmaintenance':
$id_type = CE\UId::CONTENT;
$id = CEContent::getMaintenanceId();
$uids = CE\UId::getBuiltList($id, $id_type, $this->context->shop->id);
$hideEditor = empty($uids) ? $uids : array_keys($uids[$this->context->shop->id]);
break;
}
if (isset($id)) {
self::$controller = $this->context->controller;
self::$controller->addJQuery();
self::$controller->js_files[] = $this->_path . 'views/js/admin.js?v=' . _CE_VERSION_;
self::$controller->css_files[$this->_path . 'views/css/admin.css?v=' . _CE_VERSION_] = 'all';
$uid = new CE\UId($id, $id_type, 0, Shop::getContext() === Shop::CONTEXT_SHOP ? $this->context->shop->id : 0);
isset($hideEditor) or $hideEditor = $uid->getBuiltLangIdList();
$display_suppliers = Configuration::get('PS_DISPLAY_SUPPLIERS');
$display_manufacturers = version_compare(_PS_VERSION_, '1.7.7', '<')
? $display_suppliers
: Configuration::get('PS_DISPLAY_MANUFACTURERS');
Media::addJsDef([
'ceAdmin' => [
'uid' => "$uid",
'hideEditor' => $hideEditor,
'footerProduct' => "$footer_product",
'i18n' => [
'edit' => str_replace("'", "", $this->l('Edit with Creative Elements')),
'save' => str_replace("'", "", $this->l('Please save the form before editing with Creative Elements')),
'error' => str_replace("'", "", $this->getErrorMsg()),
],
'editorUrl' => Tools::safeOutput($this->context->link->getAdminLink('AdminCEEditor') . '&uid='),
'languages' => Language::getLanguages(true, $uid->id_shop),
'editSuppliers' => (int) $display_suppliers,
'editManufacturers' => (int) $display_manufacturers,
],
]);
$this->context->smarty->assign('edit_width_ce', $this->context->link->getAdminLink('AdminCEEditor'));
}
return $this->context->smarty->fetch(_CE_TEMPLATES_ . 'hook/backoffice_header.tpl');
}
protected function getErrorMsg()
{
if (!Configuration::get('PS_SHOP_ENABLE', null, null, $this->context->shop->id)) {
$ips = explode(',', Configuration::get('PS_MAINTENANCE_IP', null, null, $this->context->shop->id));
if (!in_array(Tools::getRemoteAddr(), $ips)) {
return $this->l('The shop is in maintenance mode, please whitelist your IP');
}
}
$id_tab = Tab::getIdFromClassName('AdminCEEditor');
$access = Profile::getProfileAccess($this->context->employee->id_profile, $id_tab);
if ('1' !== $access['view']) {
return CE\Helper::transError('You do not have permission to view this.');
}
$class = isset(self::$controller->className) ? self::$controller->className : '';
if (in_array($class, self::$overrides)) {
$loadObject = new ReflectionMethod(self::$controller, 'loadObject');
$loadObject->setAccessible(true);
if (empty($loadObject->invoke(self::$controller, true)->active) && !defined("$class::CE_OVERRIDE")) {
return $this->l('You can not edit items which are not displayed, because an override file is missing. Please contact us on https://addons.prestashop.com');
}
}
return '';
}
public function hookActionFrontControllerAfterInit($params = [])
{
if (version_compare(_PS_VERSION_, '1.7.7', '<')) {
// Compatibility fix for PS 1.7.3 - 1.7.6
$this->hookActionFrontControllerInitAfter($params);
}
}
public function hookActionFrontControllerInitAfter($params = [])
{
$tpl_dir = $this->context->smarty->getTemplateDir();
array_unshift($tpl_dir, _CE_TEMPLATES_ . 'front/theme/');
$this->context->smarty->setTemplateDir($tpl_dir);
if ($id_miniature = (int) Configuration::get('CE_PRODUCT_MINIATURE')) {
$this->context->smarty->assign(
'CE_PRODUCT_MINIATURE_UID',
new CE\UId($id_miniature, CE\UId::THEME, $this->context->language->id, $this->context->shop->id)
);
CE\Plugin::instance()->frontend->hasElementorInPage(true);
}
}
public function hookHeader()
{
// Compatibility fix for PS 1.7.7.x upgrade
return $this->hookDisplayHeader();
}
public function hookDisplayHeader()
{
self::$controller = $this->context->controller;
$plugin = CE\Plugin::instance();
CE\did_action('template_redirect') or CE\do_action('template_redirect');
if ($id_quick_view = Configuration::get('CE_PRODUCT_QUICK_VIEW')) {
$plugin->frontend->hasElementorInPage(true);
}
if (self::$controller instanceof ProductController) {
$this->addViewedProduct(self::$controller->getProduct()->id);
if ($id_quick_view && Tools::getValue('action') === 'quickview') {
CE\UId::$_ID = new CE\UId($id_quick_view, CE\UId::THEME, $this->context->language->id, $this->context->shop->id);
self::skipOverrideLayoutTemplate();
$this->context->smarty->assign('CE_PRODUCT_QUICK_VIEW_ID', $id_quick_view);
}
}
$uid_preview = self::getPreviewUId(false);
if ($uid_preview && CE\UId::CONTENT === $uid_preview->id_type) {
Tools::getIsset('maintenance') && $this->displayMaintenancePage();
}
// PS fix: OverrideLayoutTemplate hook doesn't exec on forbidden page
http_response_code() !== 403 or $this->hookOverrideLayoutTemplate();
}
protected function addViewedProduct($id_product)
{
$products = isset($this->context->cookie->ceViewedProducts)
? explode(',', $this->context->cookie->ceViewedProducts)
: []
;
if (in_array($id_product, $products)) {
$products = array_diff($products, [$id_product]);
}
array_unshift($products, (int) $id_product);
while (count($products) > self::VIEWED_PRODUCTS_LIMIT) {
array_pop($products);
}
$this->context->cookie->ceViewedProducts = implode(',', $products);
if (Tools::getValue('action') === 'quickview') {
$this->context->cookie->write();
}
}
public static function skipOverrideLayoutTemplate()
{
self::$tplOverride = '';
}
public function hookOverrideLayoutTemplate($params = [])
{
if (null !== self::$tplOverride || !self::$controller) {
return self::$tplOverride;
}
self::$tplOverride = '';
if (self::isMaintenance()) {
return self::$tplOverride;
}
// Page Content
$controller = self::$controller;
$tpl_vars = &$this->context->smarty->tpl_vars;
$front = Tools::strtolower(preg_replace('/(ModuleFront)?Controller(Override)?$/i', '', get_class($controller)));
// PrestaBlog fix for non-default blog URL
stripos($front, 'prestablog') === 0 && property_exists($controller, 'news') && $front = 'prestablogblog';
switch ($front) {
case 'creativeelementspreview':
$model = self::getPreviewUId(false)->getModel();
$key = $model::${'definition'}['table'];
if (isset($tpl_vars[$key]->value['id'])) {
$id = $tpl_vars[$key]->value['id'];
$desc = ['description' => &$tpl_vars[$key]->value['content']];
}
break;
case 'cms':
$model = class_exists('CMS') ? 'CMS' : 'CMSCategory';
$key = $model::${'definition'}['table'];
if (isset($tpl_vars[$key]->value['id'])) {
$id = $tpl_vars[$key]->value['id'];
$desc = ['description' => &$tpl_vars[$key]->value['content']];
CE\add_action('wp_head', 'print_og_image');
} elseif (isset($tpl_vars['cms_category']->value['id'])) {
$model = 'CMSCategory';
$id = $tpl_vars['cms_category']->value['id'];
$desc = &$tpl_vars['cms_category']->value;
}
break;
case 'product':
case 'category':
case 'manufacturer':
case 'supplier':
$model = $front;
if (isset($tpl_vars[$model]->value['id'])) {
$id = $tpl_vars[$model]->value['id'];
$desc = &$tpl_vars[$model]->value;
}
break;
case 'ybc_blogblog':
$model = 'Ybc_blog_post_class';
if (isset($tpl_vars['blog_post']->value['id_post'])) {
$id = $tpl_vars['blog_post']->value['id_post'];
$desc = &$tpl_vars['blog_post']->value;
if (Tools::getIsset('adtoken') && self::hasAdminToken('AdminModules')) {
// override post status for preview
$tpl_vars['blog_post']->value['enabled'] = 1;
}
}
break;
case 'xipblogsingle':
$model = 'XipPostsClass';
if (isset($tpl_vars['xipblogpost']->value['id_xipposts'])) {
$id = $tpl_vars['xipblogpost']->value['id_xipposts'];
$desc = ['description' => &$tpl_vars['xipblogpost']->value['post_content']];
}
break;
case 'stblogarticle':
$model = 'StBlogClass';
if (isset($tpl_vars['blog']->value['id'])) {
$id = $tpl_vars['blog']->value['id'];
$desc = ['description' => &$tpl_vars['blog']->value['content']];
break;
}
$blogProp = new ReflectionProperty($controller, 'blog');
$blogProp->setAccessible(true);
$blog = $blogProp->getValue($controller);
if (isset($blog->id)) {
$id = $blog->id;
$desc = ['description' => &$blog->content];
}
break;
case 'advanceblogdetail':
$model = 'BlogPosts';
if (isset($tpl_vars['postData']->value['id_post'])) {
$id = $tpl_vars['postData']->value['id_post'];
$desc = ['description' => &$tpl_vars['postData']->value['post_content']];
}
break;
case 'prestablogblog':
$model = 'NewsClass';
$newsProp = new ReflectionProperty($controller, 'news');
$newsProp->setAccessible(true);
$news = $newsProp->getValue($controller);
if (isset($news->id)) {
$id = $news->id;
if (isset($tpl_vars['tpl_unique'])) {
$desc = ['description' => &$tpl_vars['tpl_unique']->value];
} else {
$desc = ['description' => &$news->content];
}
}
break;
case 'hiblogpostdetails':
$model = 'HiBlogPost';
if (isset($tpl_vars['post']->value['id_post'])) {
$id = $tpl_vars['post']->value['id_post'];
$desc = &$tpl_vars['post']->value;
if (Tools::getIsset('adtoken') && self::hasAdminToken('AdminModules')) {
// override post status for preview
$tpl_vars['post']->value['enabled'] = 1;
}
}
break;
case 'tvcmsblogsingle':
$model = 'TvcmsPostsClass';
if (isset($tpl_vars['tvcmsblogpost']->value['id_tvcmsposts'])) {
$id = $tpl_vars['tvcmsblogpost']->value['id_tvcmsposts'];
$desc = ['description' => &$tpl_vars['tvcmsblogpost']->value['post_content']];
}
break;
}
if (isset($id)) {
$uid_preview = self::getPreviewUId();
if ($uid_preview && $uid_preview->id === (int) $id && $uid_preview->id_type === CE\UId::getTypeId($model)) {
CE\UId::$_ID = $uid_preview;
} elseif (!CE\UId::$_ID || in_array(CE\UId::$_ID->id_type, [CE\UId::CONTENT, CE\UId::THEME, CE\UId::TEMPLATE])) {
CE\UId::$_ID = new CE\UId($id, CE\UId::getTypeId($model), $this->context->language->id, $this->context->shop->id);
}
if (CE\UId::$_ID) {
$this->filterBodyClasses();
$desc['description'] = CE\apply_filters('the_content', $desc['description']);
}
}
// Theme Builder
$themes = [
'header' => Configuration::get('CE_HEADER'),
'footer' => Configuration::get('CE_FOOTER'),
];
$pages = [
'index' => 'page-index',
'contact' => 'page-contact',
'product' => 'product',
'pagenotfound' => 'page-not-found',
];
foreach ($pages as $page_type => $theme_type) {
if ($front === $page_type) {
$themes[$theme_type] = Configuration::get(self::getThemeVarName($theme_type));
break;
}
}
$uid = CE\UId::$_ID;
$uid_preview = self::getPreviewUId(false);
if ($uid_preview && (CE\UId::THEME === $uid_preview->id_type || CE\UId::TEMPLATE === $uid_preview->id_type)) {
$preview = self::renderTheme($uid_preview);
$document = CE\Plugin::$instance->documents->getDocForFrontend($uid_preview);
$type_preview = $document->getTemplateType();
$this->context->smarty->assign(self::getThemeVarName($type_preview), $preview);
if ('product-quick-view' === $type_preview) {
unset($desc);
$desc = ['description' => &$preview];
CE\Plugin::$instance->modules_manager->getModules('catalog')->handleProductQuickView();
$this->context->smarty->assign('CE_PRODUCT_QUICK_VIEW_ID', $uid_preview->id);
} elseif ('product-miniature' === $type_preview) {
unset($desc);
$desc = ['description' => &$preview];
CE\Plugin::$instance->modules_manager->getModules('catalog')->handleProductMiniature();
$this->context->smarty->assign('CE_PRODUCT_MINIATURE_ID', $uid_preview->id);
} elseif ('product' === $type_preview) {
$this->context->smarty->assign('CE_PRODUCT_ID', $uid_preview->id);
} elseif (stripos($type_preview, 'page-') === 0) {
$desc = ['description' => &$preview];
CE\add_action('wp_head', 'print_og_image');
}
array_search($type_preview, $pages) && $this->filterBodyClasses($uid_preview->id);
unset($themes[$type_preview]);
}
if (isset($pages[$front]) && !empty($themes[$pages[$front]])) {
$theme_type = $pages[$front];
$uid_theme = new CE\UId($themes[$theme_type], CE\UId::THEME, $this->context->language->id, $this->context->shop->id);
if ('product' === $page_type) {
$this->context->smarty->assign([
'CE_PRODUCT_ID' => $uid_theme->id,
'CE_PRODUCT' => self::renderTheme($uid_theme),
]);
} else {
$desc = ['description' => self::renderTheme($uid_theme)];
$this->context->smarty->assign(self::getThemeVarName($theme_type), $desc['description']);
CE\add_action('wp_head', 'print_og_image');
}
$this->filterBodyClasses($uid_theme->id);
unset($themes[$theme_type]);
}
self::$tplOverride = CE\apply_filters('template_include', self::$tplOverride);
if (strrpos(self::$tplOverride, 'layout-canvas') !== false) {
empty($desc) or $this->context->smarty->assign('ce_desc', $desc);
} else {
foreach ($themes as $theme_type => $id_ce_theme) {
empty($id_ce_theme) or $this->context->smarty->assign(
self::getThemeVarName($theme_type),
self::renderTheme(
new CE\UId($id_ce_theme, CE\UId::THEME, $this->context->language->id, $this->context->shop->id)
)
);
}
}
CE\UId::$_ID = $uid;
return self::$tplOverride;
}
protected function filterBodyClasses($id_ce_theme = 0)
{
$body_classes = &$this->context->smarty->tpl_vars['page']->value['body_classes'];
if ($id_ce_theme) {
$body_classes['ce-theme'] = 1;
$body_classes["ce-theme-$id_ce_theme"] = 1;
} else {
$body_classes['elementor-page'] = 1;
$body_classes['elementor-page-' . CE\get_the_ID()->toDefault()] = 1;
}
}
protected function displayMaintenancePage()
{
Configuration::set('PS_SHOP_ENABLE', false);
Configuration::set('PS_MAINTENANCE_IP', '');
$displayMaintenancePage = new ReflectionMethod($this->context->controller, 'displayMaintenancePage');
$displayMaintenancePage->setAccessible(true);
$displayMaintenancePage->invoke($this->context->controller);
}
public function hookDisplayMaintenance($params = [])
{
if (self::getPreviewUId(false)) {
http_response_code(200);
header_remove('Retry-After');
} else {
$this->hookDisplayHeader();
}
CE\add_filter('the_content', function () {
$uid = CE\get_the_ID();
${'this'}->context->smarty->assign('ce_content', new CEContent($uid->id, $uid->id_lang, $uid->id_shop));
CE\remove_all_filters('the_content');
}, 0);
if (!$maintenance = $this->renderContent('displayMaintenance', $params)) {
return;
}
self::$controller->registerJavascript('jquery', 'js/jquery/jquery-1.11.0.min.js');
$this->context->smarty->assign([
'iso_code' => $this->context->language->iso_code,
'favicon' => Configuration::get('PS_FAVICON'),
'favicon_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'),
]);
return $maintenance;
}
public function hookDisplayFooterProduct($params = [])
{
return $this->renderContent('displayFooterProduct', $params);
}
public function __call($method, $args)
{
if (stripos($method, 'hookActionObject') === 0 && stripos($method, 'DeleteAfter') !== false) {
call_user_func_array([$this, 'hookActionObjectDeleteAfter'], $args);
} elseif (stripos($method, 'hook') === 0) {
// render hook only after Header init or if it's Home
if (null !== self::$tplOverride || !strcasecmp($method, 'hookDisplayHome')) {
return $this->renderContent(Tools::substr($method, 4), $args);
}
} else {
throw new Exception('Can not find method: ' . $method);
}
}
public function renderContent($hook_name = null)
{
if (!$hook_name) {
return;
}
$out = '';
$rows = CEContent::getIdsByHook(
$hook_name,
$id_lang = $this->context->language->id,
$id_shop = $this->context->shop->id,
Tools::getValue('id_product', 0),
self::getPreviewUId()
);
if ($rows) {
$uid = CE\UId::$_ID;
foreach ($rows as $row) {
CE\UId::$_ID = new CE\UId($row['id'], CE\UId::CONTENT, $id_lang, $id_shop);
$out .= CE\apply_filters('the_content', '');
}
CE\UId::$_ID = $uid;
}
return $out;
}
public static function renderTheme($uid)
{
CE\UId::$_ID = $uid;
return CE\apply_filters('the_content', '');
}
public function registerHook($hook_name, $shop_list = null, $position = null)
{
$res = parent::registerHook($hook_name, $shop_list);
if ($res && is_numeric($position)) {
$this->updatePosition(Hook::getIdByName($hook_name), 0, $position);
}
return $res;
}
public function hookCETemplate($params = [])
{
if (empty($params['id']) || !Validate::isLoadedObject($tpl = new CETemplate($params['id'])) || !$tpl->active) {
return;
}
$uid = CE\UId::$_ID;
CE\UId::$_ID = new CE\UId($params['id'], CE\UId::TEMPLATE);
$out = CE\apply_filters('the_content', '');
CE\UId::$_ID = $uid;
return $out;
}
public function hookActionObjectDeleteAfter($params = [])
{
$model = get_class($params['object']);
$id_type = CE\UId::getTypeId($model);
$id_start = sprintf('%d%02d', $params['object']->id, $id_type);
// Delete meta data
Db::getInstance()->delete('ce_meta', "id LIKE '{$id_start}____'");
// Delete CSS files
array_map('unlink', glob(_CE_PATH_ . "views/css/ce/$id_start????.css", GLOB_NOSORT));
}
public function hookActionObjectProductDeleteAfter($params = [])
{
$this->hookActionObjectDeleteAfter($params);
// Delete displayFooterProduct content
if ($id = CEContent::getFooterProductId($params['object']->id)) {
$content = new CEContent($id);
Validate::isLoadedObject($content) && $content->delete();
}
}
public function hookActionProductAdd($params = [])
{
if (isset($params['request']) && $params['request']->attributes->get('action') === 'duplicate') {
$id_product_duplicate = (int) $params['request']->attributes->get('id');
} elseif (Tools::getIsset('duplicateproduct')) {
$id_product_duplicate = (int) Tools::getValue('id_product');
}
if (isset($id_product_duplicate, $params['id_product']) &&
$built_list = CE\UId::getBuiltList($id_product_duplicate, CE\UId::PRODUCT)
) {
$db = CE\Plugin::instance()->db;
$uid = new CE\UId($params['id_product'], CE\UId::PRODUCT, 0);
foreach ($built_list as $id_shop => &$langs) {
foreach ($langs as $id_lang => $uid_from) {
$uid->id_lang = $id_lang;
$uid->id_shop = $id_shop;
$db->copyElementorMeta($uid_from, $uid);
}
}
}
}
protected function checkThemeChange()
{
if (!$theme = Configuration::get('CE_THEME')) {
Configuration::updateValue('CE_THEME', _THEME_NAME_);
} elseif (_THEME_NAME_ !== $theme) {
require_once _CE_PATH_ . 'classes/CEDatabase.php';
// register missing hooks after changing theme
foreach (CEDatabase::getHooks() as $hook) {
$this->registerHook($hook, null, 1);
}
Configuration::updateValue('CE_THEME', _THEME_NAME_);
}
}
public static function getPreviewUId($embed = true)
{
static $res = null;
if (null === $res && $res = Tools::getIsset('preview_id') &&
$uid = CE\UId::parse(Tools::getValue('preview_id'))
) {
$admin = $uid->getAdminController();
$key = 'AdminBlogPosts' === $admin ? 'blogtoken' : 'adtoken';
$res = self::hasAdminToken($admin, $key) ? $uid : false;
}
return !$embed || Tools::getIsset('ver') ? $res : false;
}
public static function hasAdminToken($tab, $key = 'adtoken')
{
$adtoken = Tools::getAdminToken($tab . (int) Tab::getIdFromClassName($tab) . (int) Tools::getValue('id_employee'));
return Tools::getValue($key) == $adtoken;
}
public static function getThemeVarName($theme_type)
{
if ('product' === $theme_type && Tools::getValue('quickview')) {
return 'CE_PRODUCT_QUICK_VIEW';
} elseif ('product' === $theme_type && Tools::getValue('miniature')) {
return 'CE_PRODUCT_MINIATURE';
}
return 'CE_' . Tools::strtoupper(str_replace('-', '_', $theme_type));
}
public static function isMaintenance()
{
return !Configuration::get('PS_SHOP_ENABLE') &&
!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP')));
}
}

View File

@@ -0,0 +1,302 @@
<?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 API.
*
* Elementor API handler class is responsible for communicating with Elementor
* remote servers retrieving templates data and to send uninstall feedback.
*
* @since 1.0.0
*/
class Api
{
/**
* Elementor library option key.
*/
const LIBRARY_OPTION_KEY = 'elementor_remote_info_library';
/**
* Elementor feed option key.
*/
const FEED_OPTION_KEY = 'elementor_remote_info_feed_data';
/**
* API info URL.
*
* Holds the URL of the info API.
*
* @access public
* @static
*
* @var string API info URL.
*/
public static $api_info_url = 'http://pagebuilder.webshopworks.com/?api=2&info';
// private static $api_feedback_url = 'http://pagebuilder.webshopworks.com/?api=2&feedback';
/**
* API get template content URL.
*
* Holds the URL of the template content API.
*
* @access private
* @static
*
* @var string API get template content URL.
*/
private static $api_get_template_content_url = 'http://pagebuilder.webshopworks.com/?api=2&template=%d';
/**
* Get info data.
*
* This function notifies the user of upgrade notices, new templates and contributors.
*
* @since 2.0.0
* @access private
* @static
*
* @param bool $force_update Optional. Whether to force the data retrieval or
* not. Default is false.
*
* @return array|false Info data, or false.
*/
private static function getInfoData($force_update = false)
{
$cache_key = 'elementor_remote_info_api_data_' . _CE_VERSION_;
$info_data = get_transient($cache_key);
if ($force_update || false === $info_data) {
$timeout = ($force_update) ? 25 : 8;
$response = wp_remote_get(self::$api_info_url, [
'timeout' => $timeout,
'body' => [
// Which API version is used.
'api_version' => _CE_VERSION_,
// Which language to return.
'site_lang' => get_locale(),
],
]);
if (empty($response)) {
set_transient($cache_key, [], 2 * HOUR_IN_SECONDS);
return false;
}
$info_data = json_decode($response, true);
if (empty($info_data) || !is_array($info_data)) {
set_transient($cache_key, [], 2 * HOUR_IN_SECONDS);
return false;
}
if (isset($info_data['library'], $info_data['templates'])) {
$info_data['library']['templates'] = &$info_data['templates'];
update_post_meta(0, self::LIBRARY_OPTION_KEY, $info_data['library']);
unset($info_data['library'], $info_data['templates']);
}
if (isset($info_data['feed'])) {
update_post_meta(0, self::FEED_OPTION_KEY, $info_data['feed']);
unset($info_data['feed']);
}
set_transient($cache_key, $info_data, 12 * HOUR_IN_SECONDS);
}
return $info_data;
}
/**
* Get upgrade notice.
*
* Retrieve the upgrade notice if one exists, or false otherwise.
*
* @since 1.0.0
* @access public
* @static
*
* @return array|false Upgrade notice, or false none exist.
*/
public static function getUpgradeNotice()
{
$data = self::getInfoData();
if (empty($data['upgrade_notice'])) {
return false;
}
return $data['upgrade_notice'];
}
/**
* Get templates data.
*
* Retrieve the templates data from a remote server.
*
* @since 2.0.0
* @access public
* @static
*
* @param bool $force_update Optional. Whether to force the data update or
* not. Default is false.
*
* @return array The templates data.
*/
public static function getLibraryData($force_update = false)
{
self::getInfoData($force_update);
$library_data = get_post_meta(0, self::LIBRARY_OPTION_KEY, true);
if (empty($library_data)) {
return [];
}
return $library_data;
}
/**
* Get feed data.
*
* Retrieve the feed info data from remote elementor server.
*
* @since 1.9.0
* @access public
* @static
*
* @param bool $force_update Optional. Whether to force the data update or
* not. Default is false.
*
* @return array Feed data.
*/
public static function getFeedData($force_update = false)
{
self::getInfoData($force_update);
$feed = get_post_meta(0, self::FEED_OPTION_KEY, true);
if (empty($feed)) {
return [];
}
return $feed;
}
/**
* Get template content.
*
* Retrieve the templates content received from a remote server.
*
* @since 1.0.0
* @access public
* @static
*
* @param int $template_id The template ID.
*
* @return array The template content.
*/
public static function getTemplateContent($template_id)
{
$url = sprintf(self::$api_get_template_content_url, $template_id);
$body_args = [
// Which API version is used.
'api_version' => _CE_VERSION_,
// Which language to return.
'site_lang' => get_locale(),
];
/**
* API: Template body args.
*
* Filters the body arguments send with the GET request when fetching the content.
*
* @since 1.0.0
*
* @param array $body_args Body arguments.
*/
$body_args = apply_filters('elementor/api/get_templates/body_args', $body_args);
$response = wp_remote_get($url, [
'timeout' => 40,
'body' => $body_args,
]);
if (empty($response)) {
return $response;
}
$template_content = json_decode($response, true);
/**
* API: Template content.
*
* Filters the remote template content.
*
* @since 2.5.0
*
* @param array $template_content Template content.
*/
$template_content = apply_filters('elementor/api/get_templates/content', $template_content);
if (isset($template_content['error'])) {
return new WPError('response_error', $template_content['error']);
}
if (empty($template_content['data']) && empty($template_content['content'])) {
return new WPError('template_data_error', 'An invalid data was returned.');
}
return $template_content;
}
// public static function sendFeedback($feedback_key, $feedback_text)
/**
* Ajax reset API data.
*
* Reset Elementor library API data using an ajax call.
*
* @since 1.0.0
* @access public
* @static
*/
public static function ajaxResetApiData()
{
check_ajax_referer('elementor_reset_library', '_nonce');
self::getInfoData(true);
wp_send_json_success();
}
/**
* Init.
*
* Initialize Elementor API.
*
* @since 1.0.0
* @access public
* @static
*/
public static function init()
{
add_action('wp_ajax_elementor_reset_library', [__CLASS__, 'ajax_reset_api_data']);
}
}

View File

@@ -0,0 +1,279 @@
<?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 autoloader.
*
* Elementor autoloader handler class is responsible for loading the different
* classes needed to run the plugin.
*
* @since 1.6.0
*/
class Autoloader
{
/**
* Classes map.
*
* Maps Elementor classes to file names.
*
* @since 1.6.0
* @access private
* @static
*
* @var array Classes used by elementor.
*/
private static $classes_map;
/**
* Classes aliases.
*
* Maps Elementor classes to aliases.
*
* @since 1.6.0
* @access private
* @static
*
* @var array Classes aliases.
*/
private static $classes_aliases;
/**
* Run autoloader.
*
* Register a function as `__autoload()` implementation.
*
* @since 1.6.0
* @access public
* @static
*/
public static function run()
{
spl_autoload_register([__CLASS__, 'autoload']);
}
/**
* Get classes aliases.
*
* Retrieve the classes aliases names.
*
* @since 1.6.0
* @access public
* @static
*
* @return array Classes aliases.
*/
public static function getClassesAliases()
{
if (!self::$classes_aliases) {
self::initClassesAliases();
}
return self::$classes_aliases;
}
public static function getClassesMap()
{
if (!self::$classes_map) {
self::initClassesMap();
}
return self::$classes_map;
}
private static function initClassesMap()
{
self::$classes_map = [
'Api' => 'includes/api.php',
'BaseControl' => 'includes/controls/base.php',
'BaseDataControl' => 'includes/controls/base-data.php',
'BaseUIControl' => 'includes/controls/base-ui.php',
'Conditions' => 'includes/conditions.php',
'ControlsManager' => 'includes/managers/controls.php',
'ControlsStack' => 'includes/base/controls-stack.php',
'DB' => 'includes/db.php',
'Editor' => 'includes/editor.php',
'ElementsManager' => 'includes/managers/elements.php',
'Embed' => 'includes/embed.php',
'Fonts' => 'includes/fonts.php',
'Frontend' => 'includes/frontend.php',
'GroupControlBase' => 'includes/controls/groups/base.php',
'GroupControlInterface' => 'includes/interfaces/group-control.php',
'Heartbeat' => 'includes/heartbeat.php',
// 'ImagesManager' => 'includes/managers/image.php',
// 'PostsCSSManager' => 'includes/managers/css-files.php',
'Preview' => 'includes/preview.php',
'SchemeBase' => 'includes/schemes/base.php',
'SchemeColor' => 'includes/schemes/color.php',
'SchemeColorPicker' => 'includes/schemes/color-picker.php',
'SchemeTypography' => 'includes/schemes/typography.php',
'SchemeInterface' => 'includes/interfaces/scheme.php',
'SchemesManager' => 'includes/managers/schemes.php',
'Shapes' => 'includes/shapes.php',
'SkinsManager' => 'includes/managers/skins.php',
'Stylesheet' => 'includes/stylesheet.php',
'TemplateLibraryXClassesXImportImages' => 'includes/template-library/classes/class-import-images.php',
'TemplateLibraryXManager' => 'includes/template-library/manager.php',
'TemplateLibraryXSourceBase' => 'includes/template-library/sources/base.php',
'TemplateLibraryXSourceLocal' => 'includes/template-library/sources/local.php',
'TemplateLibraryXSourceRemote' => 'includes/template-library/sources/remote.php',
'User' => 'includes/user.php',
'Utils' => 'includes/utils.php',
'WidgetsManager' => 'includes/managers/widgets.php',
];
$controls_names = ControlsManager::getControlsNames();
$controls_names = array_merge($controls_names, [
'base_multiple',
'base_units',
]);
foreach ($controls_names as $control_name) {
$class_name = 'Control' . self::normalizeClassName($control_name, '_');
self::$classes_map[$class_name] = 'includes/controls/' . str_replace('_', '-', $control_name) . '.php';
}
$controls_groups_names = ControlsManager::getGroupsNames();
foreach ($controls_groups_names as $group_name) {
$class_name = 'GroupControl' . self::normalizeClassName(str_replace('-', '_', $group_name), '_');
self::$classes_map[$class_name] = 'includes/controls/groups/' . $group_name . '.php';
}
}
/**
* Normalize Class Name
*
* Used to convert control names to class name,
* a ucwords polyfill for php versions not supporting delimiter parameter
* reference : https://github.com/elementor/elementor/issues/7310#issuecomment-469593385
*
* @param $string
* @param string $delimiter
*
* @todo Remove once we bump minimum php version to 5.6
* @return mixed
*/
private static function normalizeClassName($string, $delimiter = ' ')
{
return str_replace(' ', '', ucwords(str_replace($delimiter, ' ', $string)));
}
private static function initClassesAliases()
{
self::$classes_aliases = [
'CSSFile' => [
'replacement' => 'CoreXFilesXCSSXBase',
'version' => '2.1.0',
],
'GlobalCSSFile' => [
'replacement' => 'CoreXFilesXCSSXGlobalCSS',
'version' => '2.1.0',
],
'PostCSSFile' => [
'replacement' => 'CoreXFilesXCSSXPost',
'version' => '2.1.0',
],
'PostsCSSManager' => [
'replacement' => 'CoreXFilesXManager',
'version' => '2.1.0',
],
'PostPreviewCSS' => [
'replacement' => 'CoreXFilesXCSSXPostPreview',
'version' => '2.1.0',
],
'Responsive' => [
'replacement' => 'CoreXResponsiveXResponsive',
'version' => '2.1.0',
],
'Ajax' => [
'replacement' => 'CoreXCommonXModulesXAjaxXModule',
'version' => '2.3.0',
],
];
}
/**
* Load class.
*
* For a given class name, require the class file.
*
* @since 1.6.0
* @access private
* @static
*
* @param string $relative_class_name Class name.
*/
private static function loadClass($relative_class_name)
{
$classes_map = self::getClassesMap();
if (isset($classes_map[$relative_class_name])) {
$filename = _CE_PATH_ . '/' . $classes_map[$relative_class_name];
} else {
$filename = call_user_func(
'strtolower',
preg_replace(
['/X/', '/([a-z])([A-Z])/'],
['/', '$1-$2'],
$relative_class_name
)
);
$filename = _CE_PATH_ . $filename . '.php';
}
if (is_readable($filename)) {
require $filename;
}
}
/**
* Autoload.
*
* For a given class, check if it exist and load it.
*
* @since 1.6.0
* @access private
* @static
*
* @param string $class Class name.
*/
private static function autoload($class)
{
if (0 !== strpos($class, __NAMESPACE__ . '\\')) {
return;
}
$relative_class_name = preg_replace('/^' . __NAMESPACE__ . '\\\/', '', $class);
$classes_aliases = self::getClassesAliases();
$has_class_alias = isset($classes_aliases[$relative_class_name]);
// Backward Compatibility: Save old class name for set an alias after the new class is loaded
if ($has_class_alias) {
$alias_data = $classes_aliases[$relative_class_name];
$relative_class_name = $alias_data['replacement'];
}
$final_class_name = __NAMESPACE__ . '\\' . $relative_class_name;
if (!class_exists($final_class_name)) {
self::loadClass($relative_class_name);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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,370 @@
<?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 skin base.
*
* An abstract class to register new skins for Elementor widgets. Skins allows
* you to add new templates, set custom controls and more.
*
* To register new skins for your widget use the `add_skin()` method inside the
* widget's `_register_skins()` method.
*
* @since 1.0.0
* @abstract
*/
abstract class SkinBase
{
/**
* Parent widget.
*
* Holds the parent widget of the skin. Default value is null, no parent widget.
*
* @access protected
*
* @var WidgetBase|null
*/
protected $parent = null;
/**
* Skin base constructor.
*
* Initializing the skin base class by setting parent widget and registering
* controls actions.
*
* @since 1.0.0
* @access public
* @param WidgetBase $parent
*/
public function __construct(WidgetBase $parent)
{
$this->parent = $parent;
$this->_registerControlsActions();
}
/**
* Get skin ID.
*
* Retrieve the skin ID.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function getId();
/**
* Get skin title.
*
* Retrieve the skin title.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function getTitle();
/**
* Render skin.
*
* Generates the final HTML on the frontend.
*
* @since 1.0.0
* @access public
* @abstract
*/
abstract public function render();
/**
* Register skin controls actions.
*
* Run on init and used to register new skins to be injected to the widget.
* This method is used to register new actions that specify the location of
* the skin in the widget.
*
* Example usage:
* `add_action( 'elementor/element/{widget_id}/{section_id}/before_section_end', [ $this, 'register_controls' ] );`
*
* @since 1.0.0
* @access protected
*/
protected function _registerControlsActions()
{
}
/**
* Get skin control ID.
*
* Retrieve the skin control ID. Note that skin controls have special prefix
* to distinguish them from regular controls, and from controls in other
* skins.
*
* @since 1.0.0
* @access protected
*
* @param string $control_base_id Control base ID.
*
* @return string Control ID.
*/
protected function getControlId($control_base_id)
{
$skin_id = str_replace('-', '_', $this->getId());
return $skin_id . '_' . $control_base_id;
}
/**
* Get skin settings.
*
* Retrieve all the skin settings or, when requested, a specific setting.
*
* @since 1.0.0
* @TODO: rename to get_setting() and create backward compatibility.
*
* @access public
*
* @param string $control_base_id Control base ID.
*
* @return WidgetBase Widget instance.
*/
public function getInstanceValue($control_base_id)
{
$control_id = $this->getControlId($control_base_id);
return $this->parent->getSettings($control_id);
}
/**
* Start skin controls section.
*
* Used to add a new section of controls to the skin.
*
* @since 1.3.0
* @access public
*
* @param string $id Section ID.
* @param array $args Section arguments.
*/
public function startControlsSection($id, $args)
{
$args['condition']['_skin'] = $this->getId();
$this->parent->startControlsSection($this->getControlId($id), $args);
}
/**
* End skin controls section.
*
* Used to close an existing open skin controls section.
*
* @since 1.3.0
* @access public
*/
public function endControlsSection()
{
$this->parent->endControlsSection();
}
/**
* Add new skin control.
*
* Register a single control to the allow the user to set/update skin data.
*
* @since 1.0.0
* @access public
*
* @param string $id Control ID.
* @param array $args Control arguments.
*
* @return bool True if skin added, False otherwise.
*/
public function addControl($id, $args)
{
$args['condition']['_skin'] = $this->getId();
return $this->parent->addControl($this->getControlId($id), $args);
}
/**
* Update skin control.
*
* Change the value of an existing skin control.
*
* @since 1.3.0
* @since 1.8.1 New `$options` parameter added.
*
* @access public
*
* @param string $id Control ID.
* @param array $args Control arguments. Only the new fields you want to update.
* @param array $options Optional. Some additional options.
*/
public function updateControl($id, $args, array $options = [])
{
$args['condition']['_skin'] = $this->getId();
$this->parent->updateControl($this->getControlId($id), $args, $options);
}
/**
* Remove skin control.
*
* Unregister an existing skin control.
*
* @since 1.3.0
* @access public
*
* @param string $id Control ID.
*/
public function removeControl($id)
{
$this->parent->removeControl($this->getControlId($id));
}
/**
* Add new responsive skin control.
*
* Register a set of controls to allow editing based on user screen size.
*
* @since 1.0.5
* @access public
*
* @param string $id Responsive control ID.
* @param array $args Responsive control arguments.
*/
public function addResponsiveControl($id, $args)
{
$args['condition']['_skin'] = $this->getId();
$this->parent->addResponsiveControl($this->getControlId($id), $args);
}
/**
* Update responsive skin control.
*
* Change the value of an existing responsive skin control.
*
* @since 1.3.5
* @access public
*
* @param string $id Responsive control ID.
* @param array $args Responsive control arguments.
*/
public function updateResponsiveControl($id, $args)
{
$this->parent->updateResponsiveControl($this->getControlId($id), $args);
}
/**
* Remove responsive skin control.
*
* Unregister an existing skin responsive control.
*
* @since 1.3.5
* @access public
*
* @param string $id Responsive control ID.
*/
public function removeResponsiveControl($id)
{
$this->parent->removeResponsiveControl($this->getControlId($id));
}
/**
* Start skin controls tab.
*
* Used to add a new tab inside a group of tabs.
*
* @since 1.5.0
* @access public
*
* @param string $id Control ID.
* @param array $args Control arguments.
*/
public function startControlsTab($id, $args)
{
$args['condition']['_skin'] = $this->getId();
$this->parent->startControlsTab($this->getControlId($id), $args);
}
/**
* End skin controls tab.
*
* Used to close an existing open controls tab.
*
* @since 1.5.0
* @access public
*/
public function endControlsTab()
{
$this->parent->endControlsTab();
}
/**
* Start skin controls tabs.
*
* Used to add a new set of tabs inside a section.
*
* @since 1.5.0
* @access public
*
* @param string $id Control ID.
*/
public function startControlsTabs($id)
{
// $args['condition']['_skin'] = $this->getId();
$this->parent->startControlsTabs($this->getControlId($id));
}
/**
* End skin controls tabs.
*
* Used to close an existing open controls tabs.
*
* @since 1.5.0
* @access public
*/
public function endControlsTabs()
{
$this->parent->endControlsTabs();
}
/**
* Add new group control.
*
* Register a set of related controls grouped together as a single unified
* control.
*
* @since 1.0.0
* @access public
*
* @param string $group_name Group control name.
* @param array $args Group control arguments. Default is an empty array.
*/
final public function addGroupControl($group_name, $args = [])
{
$args['name'] = $this->getControlId($args['name']);
$args['condition']['_skin'] = $this->getId();
$this->parent->addGroupControl($group_name, $args);
}
/**
* Set parent widget.
*
* Used to define the parent widget of the skin.
*
* @since 1.0.0
* @access public
*
* @param WidgetBase $parent Parent widget.
*/
public function setParent($parent)
{
$this->parent = $parent;
}
}

View File

@@ -0,0 +1,870 @@
<?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 widget base.
*
* An abstract class to register new Elementor widgets. It extended the
* `ElementBase` class to inherit its properties.
*
* This abstract class must be extended in order to register new widgets.
*
* @since 1.0.0
* @abstract
*/
abstract class WidgetBase extends ElementBase
{
const REMOTE_RENDER = false;
private static $render_method = 'render';
/**
* Whether the widget has content.
*
* Used in cases where the widget has no content. When widgets uses only
* skins to display dynamic content generated on the server.
* Default is true, the widget has content template.
*
* @access protected
*
* @var bool
*/
protected $_has_template_content = true;
/**
* Element edit tools.
*
* Holds all the edit tools of the element. For example: delete, duplicate etc.
*
* @access protected
* @static
*
* @var array
*/
protected static $_edit_tools;
/**
* Get element type.
*
* Retrieve the element type, in this case `widget`.
*
* @since 1.0.0
* @access public
* @static
*
* @return string The type.
*/
public static function getType()
{
return 'widget';
}
/**
* Get widget icon.
*
* Retrieve the widget icon.
*
* @since 1.0.0
* @access public
*
* @return string Widget icon.
*/
public function getIcon()
{
return 'eicon-apps';
}
/**
* Get widget keywords.
*
* Retrieve the widget keywords.
*
* @since 1.0.10
* @access public
*
* @return array Widget keywords.
*/
public function getKeywords()
{
return [];
}
/**
* Get widget categories.
*
* Retrieve the widget categories.
*
* @since 1.0.10
* @access public
*
* @return array Widget categories.
*/
public function getCategories()
{
return ['general'];
}
/**
* Widget base constructor.
*
* Initializing the widget base class.
*
* @since 1.0.0
* @access public
*
* @throws \Exception If arguments are missing when initializing a full widget
* instance.
*
* @param array $data Widget data. Default is an empty array.
* @param array|null $args Optional. Widget default arguments. Default is null.
*/
public function __construct($data = [], $args = null)
{
parent::__construct($data, $args);
$is_type_instance = $this->isTypeInstance();
if (!$is_type_instance && null === $args) {
throw new \Exception('`$args` argument is required when initializing a full widget instance.');
}
if ($is_type_instance) {
$this->_registerSkins();
$widget_name = $this->getName();
/**
* Widget skin init.
*
* Fires when Elementor widget is being initialized.
*
* The dynamic portion of the hook name, `$widget_name`, refers to the widget name.
*
* @since 1.0.0
*
* @param WidgetBase $this The current widget.
*/
do_action("elementor/widget/{$widget_name}/skins_init", $this);
}
}
/**
* Get stack.
*
* Retrieve the widget stack of controls.
*
* @since 1.9.2
* @access public
*
* @param bool $with_common_controls Optional. Whether to include the common controls. Default is true.
*
* @return array Widget stack of controls.
*/
public function getStack($with_common_controls = true)
{
$stack = parent::getStack();
if ($with_common_controls && 'common' !== $this->getUniqueName()) {
/** @var WidgetCommon $common_widget */
$common_widget = Plugin::$instance->widgets_manager->getWidgetTypes('common');
$stack['controls'] = array_merge($stack['controls'], $common_widget->getControls());
$stack['tabs'] = array_merge($stack['tabs'], $common_widget->getTabsControls());
}
return $stack;
}
/**
* Get widget controls pointer index.
*
* Retrieve widget pointer index where the next control should be added.
*
* While using injection point, it will return the injection point index. Otherwise index of the last control of the
* current widget itself without the common controls, plus one.
*
* @since 1.9.2
* @access public
*
* @return int Widget controls pointer index.
*/
public function getPointerIndex()
{
$injection_point = $this->getInjectionPoint();
if (null !== $injection_point) {
return $injection_point['index'];
}
return count($this->getStack(false)['controls']);
}
/**
* Show in panel.
*
* Whether to show the widget in the panel or not. By default returns true.
*
* @since 1.0.0
* @access public
*
* @return bool Whether to show the widget in the panel or not.
*/
public function showInPanel()
{
return true;
}
/**
* Start widget controls section.
*
* Used to add a new section of controls to the widget. Regular controls and
* skin controls.
*
* Note that when you add new controls to widgets they must be wrapped by
* `start_controls_section()` and `end_controls_section()`.
*
* @since 1.0.0
* @access public
*
* @param string $section_id Section ID.
* @param array $args Section arguments Optional.
*/
public function startControlsSection($section_id, array $args = [])
{
parent::startControlsSection($section_id, $args);
static $is_first_section = true;
if ($is_first_section) {
$this->registerSkinControl();
$is_first_section = false;
}
}
/**
* Register the Skin Control if the widget has skins.
*
* An internal method that is used to add a skin control to the widget.
* Added at the top of the controls section.
*
* @since 2.0.0
* @access private
*/
private function registerSkinControl()
{
$skins = $this->getSkins();
if (!empty($skins)) {
$skin_options = [];
if ($this->_has_template_content) {
$skin_options[''] = __('Default');
}
foreach ($skins as $skin_id => $skin) {
$skin_options[$skin_id] = $skin->getTitle();
}
// Get the first item for default value
$default_value = array_keys($skin_options);
$default_value = array_shift($default_value);
if (1 >= count($skin_options)) {
$this->addControl(
'_skin',
[
'label' => __('Skin'),
'type' => ControlsManager::HIDDEN,
'default' => $default_value,
]
);
} else {
$this->addControl(
'_skin',
[
'label' => __('Skin'),
'type' => ControlsManager::SELECT,
'default' => $default_value,
'options' => $skin_options,
]
);
}
}
}
/**
* Get default edit tools.
*
* Retrieve the element default edit tools. Used to set initial tools.
* By default the element has no edit tools.
*
* @since 1.0.0
* @access protected
* @static
*
* @return array Default edit tools.
*/
protected static function getDefaultEditTools()
{
$widget_label = __('Widget');
$edit_tools = [
'edit' => [
'title' => __('Edit'),
'icon' => 'edit',
],
];
if (self::isEditButtonsEnabled()) {
$edit_tools += [
'duplicate' => [
/* translators: %s: Widget label */
'title' => sprintf(__('Duplicate %s'), $widget_label),
'icon' => 'clone',
],
'remove' => [
/* translators: %s: Widget label */
'title' => sprintf(__('Remove %s'), $widget_label),
'icon' => 'close',
],
];
}
return $edit_tools;
}
/**
* Register widget skins.
*
* This method is activated while initializing the widget base class. It is
* used to assign skins to widgets with `addSkin()` method.
*
* Usage:
*
* protected function _registerSkins() {
* $this->addSkin( new SkinClassic( $this ) );
* }
*
* @since 1.7.12
* @access protected
*/
protected function _registerSkins()
{
}
/**
* Get initial config.
*
* Retrieve the current widget initial configuration.
*
* Adds more configuration on top of the controls list, the tabs assigned to
* the control, element name, type, icon and more. This method also adds
* widget type, keywords and categories.
*
* @since 1.0.10
* @access protected
*
* @return array The initial widget config.
*/
protected function _getInitialConfig()
{
$config = [
'widget_type' => $this->getName(),
'keywords' => $this->getKeywords(),
'categories' => $this->getCategories(),
'html_wrapper_class' => $this->getHtmlWrapperClass(),
'show_in_panel' => $this->showInPanel(),
];
$stack = Plugin::$instance->controls_manager->getElementStack($this);
if ($stack) {
$config['controls'] = $this->getStack(false)['controls'];
$config['tabs_controls'] = $this->getTabsControls();
}
return array_merge(parent::_getInitialConfig(), $config);
}
/**
* @since 2.3.1
* @access protected
*/
protected function shouldPrintEmpty()
{
return false;
}
/**
* Print widget content template.
*
* Used to generate the widget content template on the editor, using a
* Backbone JavaScript template.
*
* @since 2.0.0
* @access protected
*
* @param string $template_content Template content.
*/
protected function printTemplateContent($template_content)
{
$this->renderEditTools();
?>
<div class="elementor-widget-container"><?= $template_content ?></div>
<?php
}
/**
* Parse text editor.
*
* Parses the content from rich text editor with shortcodes.
*
* @since 1.0.0
* @access protected
*
* @param string $content Text editor content.
*
* @return string Parsed content.
*/
protected function parseTextEditor($content)
{
/** This filter is documented in wp-includes/widgets/class-wp-widget-text.php */
$content = apply_filters('widget_text', $content, $this->getSettings());
if ('renderSmarty' === self::$render_method) {
return $content;
}
// if ($GLOBALS['wp_embed'] instanceof \WP_Embed) {
// $content = $GLOBALS['wp_embed']->autoembed($content);
// }
return 'render' === self::$render_method ? do_shortcode($content) : $content;
}
/**
* Get HTML wrapper class.
*
* Retrieve the widget container class. Can be used to override the
* container class for specific widgets.
*
* @since 2.0.9
* @access protected
*/
protected function getHtmlWrapperClass()
{
return 'elementor-widget-' . $this->getName();
}
/**
* Add widget render attributes.
*
* Used to add attributes to the current widget wrapper HTML tag.
*
* @since 1.0.0
* @access protected
*/
protected function _addRenderAttributes()
{
parent::_addRenderAttributes();
$this->addRenderAttribute('_wrapper', 'class', [
'elementor-widget',
$this->getHtmlWrapperClass(),
]);
$this->addRenderAttribute('_wrapper', 'data-widget_type', $this->getName() . '.' . ($this->getSettings('_skin') ?: 'default'));
}
/**
* Render widget output on the frontend.
*
* Used to generate the final HTML displayed on the frontend.
*
* Note that if skin is selected, it will be rendered by the skin itself,
* not the widget.
*
* @since 1.0.0
* @access public
*/
public function renderContent()
{
if (static::REMOTE_RENDER && is_admin() && 'render' === self::$render_method) {
return print '<div class="ce-remote-render"></div>';
}
/**
* Before widget render content.
*
* Fires before Elementor widget is being rendered.
*
* @since 1.0.0
*
* @param WidgetBase $this The current widget.
*/
do_action('elementor/widget/before_render_content', $this);
ob_start();
$skin = $this->getCurrentSkin();
if ($skin) {
$skin->setParent($this);
$skin->{self::$render_method}();
} else {
$this->{self::$render_method}();
}
$widget_content = ob_get_clean();
if (empty($widget_content)) {
return;
}
if (Plugin::$instance->editor->isEditMode()) {
$this->renderEditTools();
}
echo '<div class="elementor-widget-container">';
/**
* Render widget content.
*
* Filters the widget content before it's rendered.
*
* @since 1.0.0
*
* @param string $widget_content The content of the widget.
* @param WidgetBase $this The widget.
*/
echo apply_filters('elementor/widget/render_content', $widget_content, $this); // XSS ok.
echo '</div>';
}
/**
* Render widget smarty template.
*
* @since 2.5.10
* @access protected
*/
protected function renderSmarty()
{
$this->render();
}
/**
* Render widget plain content.
*
* Elementor saves the page content in a unique way, but it's not the way
* PretaShop saves data. This method is used to save generated HTML to the
* database as plain content the PretaShop way.
*
* When rendering plain content, it allows other PretaShop modules to
* interact with the content - to search, check SEO and other purposes. It
* also allows the site to keep working even if Elementor is deactivated.
*
* Note that if the widget uses shortcodes to display the data, the best
* practice is to return the shortcode itself.
*
* Also note that if the widget don't display any content it should return
* an empty string.
*
* @since 1.0.0
* @access public
*/
public function renderPlainContent()
{
$this->renderContent();
}
/**
* Before widget rendering.
*
* Used to add stuff before the widget `_wrapper` element.
*
* @since 1.0.0
* @access public
*/
public function beforeRender()
{
?>
<div <?= $this->getRenderAttributeString('_wrapper') ?>>
<?php
}
/**
* After widget rendering.
*
* Used to add stuff after the widget `_wrapper` element.
*
* @since 1.0.0
* @access public
*/
public function afterRender()
{
?>
</div>
<?php
}
/**
* Get the element raw data.
*
* Retrieve the raw element data, including the id, type, settings, child
* elements and whether it is an inner element.
*
* The data with the HTML used always to display the data, but the Elementor
* editor uses the raw data without the HTML in order not to render the data
* again.
*
* @since 1.0.0
* @access public
*
* @param bool $with_html_content Optional. Whether to return the data with
* HTML content or without. Used for caching.
* Default is false, without HTML.
*
* @return array Element raw data.
*/
public function getRawData($with_html_content = false)
{
$data = parent::getRawData($with_html_content);
unset($data['isInner']);
$data['widgetType'] = $this->getData('widgetType');
if ($with_html_content) {
ob_start();
$this->renderContent();
$data['htmlCache'] = ob_get_clean();
}
return $data;
}
/**
* Print widget content.
*
* Output the widget final HTML on the frontend.
*
* @since 1.0.0
* @access protected
*/
protected function _printContent()
{
$this->renderContent();
}
/**
* Get default data.
*
* Retrieve the default widget data. Used to reset the data on initialization.
*
* @since 1.0.0
* @access protected
*
* @return array Default data.
*/
protected function getDefaultData()
{
$data = parent::getDefaultData();
$data['widgetType'] = '';
return $data;
}
/**
* Get default child type.
*
* Retrieve the widget child type based on element data.
*
* @since 1.0.0
* @access protected
*
* @param array $element_data Widget ID.
*
* @return array|false Child type or false if it's not a valid widget.
*/
protected function _getDefaultChildType(array $element_data)
{
return Plugin::$instance->elements_manager->getElementTypes('section');
}
/**
* Get repeater setting key.
*
* Retrieve the unique setting key for the current repeater item. Used to connect the current element in the
* repeater to it's settings model and it's control in the panel.
*
* @since 1.8.0
* @access protected
*
* @param string $setting_key The current setting key inside the repeater item (e.g. `tab_title`).
* @param string $repeater_key The repeater key containing the array of all the items in the repeater (e.g. `tabs`).
* @param int $repeater_item_index The current item index in the repeater array (e.g. `3`).
*
* @return string The repeater setting key (e.g. `tabs.3.tab_title`).
*/
protected function getRepeaterSettingKey($setting_key, $repeater_key, $repeater_item_index)
{
return implode('.', [$repeater_key, $repeater_item_index, $setting_key]);
}
/**
* Add inline editing attributes.
*
* Define specific area in the element to be editable inline. The element can have several areas, with this method
* you can set the area inside the element that can be edited inline. You can also define the type of toolbar the
* user will see, whether it will be a basic toolbar or an advanced one.
*
* Note: When you use wysiwyg control use the advanced toolbar, with textarea control use the basic toolbar. Text
* control should not have toolbar.
*
* PHP usage (inside `WidgetBase::render()` method):
*
* $this->addInlineEditingAttributes( 'text', 'advanced' );
* echo '<div ' . $this->getRenderAttributeString( 'text' ) . '>' . $this->getSettings( 'text' ) . '</div>';
*
* @since 1.8.0
* @access protected
*
* @param string $key Element key.
* @param string $toolbar Optional. Toolbar type. Accepted values are `advanced`, `basic` or `none`. Default is
* `basic`.
*/
protected function addInlineEditingAttributes($key, $toolbar = 'basic')
{
if (!Plugin::$instance->editor->isEditMode()) {
return;
}
$this->addRenderAttribute($key, [
'class' => 'elementor-inline-editing',
'data-elementor-setting-key' => $key,
]);
if ('basic' !== $toolbar) {
$this->addRenderAttribute($key, [
'data-elementor-inline-editing-toolbar' => $toolbar,
]);
}
}
/**
* Add new skin.
*
* Register new widget skin to allow the user to set custom designs. Must be
* called inside the `_register_skins()` method.
*
* @since 1.0.0
* @access public
*
* @param SkinBase $skin Skin instance.
*/
public function addSkin(SkinBase $skin)
{
Plugin::$instance->skins_manager->addSkin($this, $skin);
}
/**
* Get single skin.
*
* Retrieve a single skin based on skin ID, from all the skin assigned to
* the widget. If the skin does not exist or not assigned to the widget,
* return false.
*
* @since 1.0.0
* @access public
*
* @param string $skin_id Skin ID.
*
* @return string|false Single skin, or false.
*/
public function getSkin($skin_id)
{
$skins = $this->getSkins();
if (isset($skins[$skin_id])) {
return $skins[$skin_id];
}
return false;
}
/**
* Get current skin ID.
*
* Retrieve the ID of the current skin.
*
* @since 1.0.0
* @access public
*
* @return string Current skin.
*/
public function getCurrentSkinId()
{
return $this->getSettings('_skin');
}
/**
* Get current skin.
*
* Retrieve the current skin, or if non exist return false.
*
* @since 1.0.0
* @access public
*
* @return SkinBase|false Current skin or false.
*/
public function getCurrentSkin()
{
return $this->getSkin($this->getCurrentSkinId());
}
/**
* Remove widget skin.
*
* Unregister an existing skin and remove it from the widget.
*
* @since 1.0.0
* @access public
*
* @param string $skin_id Skin ID.
*
* @return WPError|true Whether the skin was removed successfully from the widget.
*/
public function removeSkin($skin_id)
{
return Plugin::$instance->skins_manager->removeSkin($this, $skin_id);
}
/**
* Get widget skins.
*
* Retrieve all the skin assigned to the widget.
*
* @since 1.0.0
* @access public
*
* @return SkinBase[]
*/
public function getSkins()
{
return Plugin::$instance->skins_manager->getSkins($this);
}
}

Some files were not shown because too many files have changed in this diff Show More