function generateArchive($themeName, $userThemeName = '', $includeThemler = true) { register_shutdown_function('fatalErrorShutdownHandler'); $themeDir = FilesHelper::normalizePath(getThemeDir($themeName)); if (!file_exists($themeDir)) { die('Error : No Theme Folder'); } $userThemeName = $userThemeName ? $userThemeName : $themeName; $uniqid = uniqid(); $base_upload_dir = get_base_upload_dir() . '/' . $uniqid; $user_template_dir = $base_upload_dir . '/' . $userThemeName; FilesHelper::copyRecursive($themeDir, $user_template_dir); if (!$includeThemler) { $dirs = array('export', 'project'); clearDirs($user_template_dir, $dirs); } $previewThemeDir = FilesHelper::normalizePath(getThemeDir($themeName . _PREVIEW_SUFFIX_)); $archiveName = 'theme_' . uniqid(time()) . '.zip'; $archiveFile = $base_upload_dir . '/' . $archiveName; $archive = new PclZip($archiveFile); add_version_folders($archive, $base_upload_dir, $user_template_dir, $previewThemeDir, $userThemeName, $includeThemler); add_files_to_archive_root($archive, $base_upload_dir, $user_template_dir, $previewThemeDir, $userThemeName); // Temporary fix to support Prestashop Cloud Install deleteFromArchive($archive, 'modules/designer/override/controllers/admin/AdminLoginController.php'); if (is_readable($archiveFile)) { $archiveContent = array('ext' => 'zip', 'content' => base64_encode(FilesHelper::readFile($archiveFile))); FilesHelper::removeDir($base_upload_dir, true); return $archiveContent; } die('Archive file: ' . $archiveFile . ' is not readable'); }
function getThemeArchive($themeName, $userThemeName, $includeThemler) { $themeDir = FilesHelper::normalizePath(getThemeDir($themeName)); if (!file_exists($themeDir)) { die('Error : No Theme Folder'); } $userThemeName = $userThemeName ? $userThemeName : $themeName; $base_upload_dir = get_base_upload_dir(); $user_template_dir = $base_upload_dir . '/' . $userThemeName; FilesHelper::copyRecursive($themeDir, $user_template_dir); if (!$includeThemler) { $dirs = array('export', 'project'); clearDirs($user_template_dir, $dirs); } $previewThemeDir = FilesHelper::normalizePath(getThemeDir($themeName . _PREVIEW_SUFFIX_)); $archive_name = 'theme_' . uniqid(time()) . '.zip'; $archive_file = $base_upload_dir . '/' . $archive_name; $archive = new PclZip($archive_file); add_version_folders($archive, $base_upload_dir, $user_template_dir, $previewThemeDir, $userThemeName, $includeThemler); add_files_to_archive_root($archive, $base_upload_dir, $user_template_dir, $previewThemeDir, $userThemeName); // Temporary fix to support Prestashop Cloud Install deleteFromArchive($archive, 'modules/designer/override/controllers/admin/AdminLoginController.php'); FilesHelper::removeDir($user_template_dir, true); return $archive_file; }
public function renderForms($themeName) { $themeDir = FilesHelper::normalizePath(getThemeDir($themeName)); $form = array(); $this->_renderTemplatesForm($form, $themeDir, $themeName); $this->_renderSlidersForms($form, $themeDir, $themeName); return $form; }
public function getThemeTemplates($themeName) { $path = FilesHelper::normalizePath(getThemeDir($themeName . _PREVIEW_SUFFIX_)) . '/templates/templates.php'; if (file_exists($path)) { // TODO: Maybe we have to store all html and parse them after each update or export operation for backward require_once $path; } else { $templates = getTemplates(); // backward with old themes which do not have templates.php file but plugin is already updated } $context = Context::getContext(); $link = $context->link; $controllers = getTemplateControllers(); $previewParam = 'theme_name=' . $themeName; $result = array(); foreach ($templates as $type => $template) { $controller = $controllers[$type]; $method = 'get' . $controller . 'Link'; if (method_exists($link, $method)) { $lower = strtolower($controller); $item = Designer::getFirstItem($lower); if ($item > 0) { $baseUrl = $link->{$method}($item); $pos = strpos($baseUrl, '?'); if ($pos !== FALSE) { // HACK: preview parameter must be first in URL in Debug mode $mainPart = substr($baseUrl, 0, $pos); $params = substr($baseUrl, $pos + 1); $templateUrl = $mainPart . '?' . $previewParam . '&' . $params; } else { $templateUrl = $baseUrl . '?' . $previewParam; } } else { $templateUrl = $link->getPageLink('index') . '?' . $previewParam . '&missingContent=' . $lower; } } else { $templateUrl = $link->getPageLink($controller); if (strpos($templateUrl, $previewParam) === FALSE) { // can be set in some case from Dispatcher.php $templateUrl .= (strpos($templateUrl, '?') !== FALSE ? '&' : '?') . $previewParam; } } if (is_array($template)) { // updated theme with templates.php file foreach ($template as $t) { $result[$t['name']] = $templateUrl . '&template=' . $type . '_' . $t['id']; // format as {templateName_id.tpl} } } else { // backward with old themes which do not have templates.php file but plugin is already updated $result[$type] = $templateUrl; } } return $result; }
function getCSSURL() { global $BASE_URL; return "{$BASE_URL}/" . getThemeDir() . "/style.css"; }
protected function _getApplicableTemplateDir($template) { require_once dirname(__FILE__) . '../../../../modules/designerpreview/defines.inc.php'; return $this->_isTemplateOverloaded($template) ? getThemeDir() : _PS_MODULE_DIR_ . $this->name . '/'; }
public static function exec($hook_name, $hook_args = array(), $id_module = null, $array_return = false, $check_exceptions = true) { require_once dirname(__FILE__) . '../../../modules/designerpreview/defines.inc.php'; static $disable_non_native_modules = null; if ($disable_non_native_modules === null) { $disable_non_native_modules = (bool) Configuration::get('PS_DISABLE_NON_NATIVE_MODULE'); } // Check arguments validity if ($id_module && !is_numeric($id_module) || !Validate::isHookName($hook_name)) { throw new PrestaShopException('Invalid id_module or hook_name'); } // If no modules associated to hook_name or recompatible hook name, we stop the function if (!($module_list = Hook::getHookModuleExecList($hook_name))) { return ''; } // Check if hook exists if (!($id_hook = Hook::getIdByName($hook_name))) { return false; } // Store list of executed hooks on this page Hook::$executed_hooks[$id_hook] = $hook_name; $live_edit = false; $context = Context::getContext(); if (!isset($hook_args['cookie']) || !$hook_args['cookie']) { $hook_args['cookie'] = $context->cookie; } if (!isset($hook_args['cart']) || !$hook_args['cart']) { $hook_args['cart'] = $context->cart; } $retro_hook_name = Hook::getRetroHookName($hook_name); // Look on modules list $altern = 0; $output = ''; if ($disable_non_native_modules && !isset(Hook::$native_module)) { Hook::$native_module = Module::getNativeModuleList(); } $callableHooks = array('displayLeftColumn', 'displayRightColumn', 'displayFooter', 'displayTop', 'displayHome', 'displayNavigationBar'); $isDesignerHook = isset($hook_args) && isset($hook_args['designer_hook']); // Billion Themler layoutPosition only $source_hook_name = $hook_name; if (isset($hook_args) && isset($hook_args['blockId'])) { // both Prestashop hooks and Designer layoutPosition $blockId = $hook_args['blockId']; $context->smarty->assign('blockId', $blockId); file_put_contents(getThemeDir() . '/includes/' . $hook_name . '.tpl', "{assign var=blockId value={$blockId} scope='parent'}"); // for blocklayered-ajax } $count = getModulesCount($hook_name, $module_list); foreach ($module_list as $index => $array) { // Check errors if ($id_module && $id_module != $array['id_module']) { continue; } if ((bool) $disable_non_native_modules && Hook::$native_module && count(Hook::$native_module) && !in_array($array['module'], self::$native_module)) { continue; } if (!($moduleInstance = Module::getInstanceByName($array['module']))) { continue; } // Check permissions if ($check_exceptions) { $exceptions = $moduleInstance->getExceptions($array['id_hook']); $controller = Dispatcher::getInstance()->getController(); if (in_array($controller, $exceptions)) { continue; } //retro compat of controller names $matching_name = array('authentication' => 'auth', 'compare' => 'products-comparison'); if (isset($matching_name[$controller]) && in_array($matching_name[$controller], $exceptions)) { continue; } if (Validate::isLoadedObject($context->employee) && !$moduleInstance->getPermission('view', $context->employee)) { continue; } } $hook_callable = false; $hook_retro_callable = false; // Check whether Billion Themler hook is if ($isDesignerHook) { foreach ($callableHooks as $name) { $hook_name = $name; $retro_hook_name = Hook::getRetroHookName($hook_name); $hook_callable = is_callable(array($moduleInstance, 'hook' . $hook_name)); $hook_retro_callable = is_callable(array($moduleInstance, 'hook' . $retro_hook_name)); // modules in layoutPosition Billion Themler hook can be called from $callableHooks (displayLeftColumn etc.) // so we save callable hook name as $hook_name variable and write its output to layoutPosition hook if ($hook_callable || $hook_retro_callable) { break; } // goes to Module::preCall line } } else { // Check which / if method is callable as usual $hook_callable = is_callable(array($moduleInstance, 'hook' . $hook_name)); $hook_retro_callable = is_callable(array($moduleInstance, 'hook' . $retro_hook_name)); } if (($hook_callable || $hook_retro_callable) && Module::preCall($moduleInstance->name)) { $hook_args['altern'] = ++$altern; // Call hook method if ($hook_callable) { $display = $moduleInstance->{'hook' . $hook_name}($hook_args); } else { if ($hook_retro_callable) { $display = $moduleInstance->{'hook' . $retro_hook_name}($hook_args); } } // Billion Themler edit - $array['live_edit'] defines if module can be moved // displayTop and displayFooter hooks can be moved too in Billion Themler but it has live_edit = 0 in DB.hook table if (!$array_return && Tools::getValue('theme_name') && ($array['live_edit'] || $hook_name == 'displayTop' || $hook_name == 'displayFooter' || $hook_name == 'displayNavigationBar')) { $display = wrapThemlerEdit($display, $moduleInstance, $array['id_hook']); } $display = addBootstrapColumn($display, $moduleInstance, $hook_name, $count, $index); // Live edit if (!$array_return && $array['live_edit'] && Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getValue('liveToken') == Tools::getAdminToken('AdminModulesPositions' . (int) Tab::getIdFromClassName('AdminModulesPositions') . (int) Tools::getValue('id_employee'))) { // We should used in Live Edit mode native PrestaShop hooks only not Billion Themler ones // That's why we remember $source_hook_name and check it if ($isDesignerHook && !in_array($source_hook_name, $callableHooks)) { $output .= $display; } else { $live_edit = true; $output .= self::wrapLiveEdit($display, $moduleInstance, $array['id_hook']); } } else { if ($array_return) { $output[$moduleInstance->name] = $display; } else { $output .= $display; } } } } if ($array_return) { return $output; } else { return ($live_edit ? '<script type="text/javascript">hooks_list.push(\'' . $hook_name . '\'); </script> <div id="' . $hook_name . '" class="dndHook" style="min-height:50px">' : '') . $output . ($live_edit ? '</div>' : ''); // Return html string } }
public function setTemplate($default_template) { require_once dirname(__FILE__) . '../../../../modules/designerpreview/defines.inc.php'; $preview_template = str_replace(_PS_THEME_DIR_, getThemeDir(), $default_template); parent::setTemplate($preview_template); }
/** * Combine Compress and Cache (ccc) JS calls * * @param array js_files * @return array processed js_files */ public static function cccJS($js_files) { require_once dirname(__FILE__) . '../../../modules/designerpreview/defines.inc.php'; //inits $compressed_js_files_not_found = array(); $js_files_infos = array(); $js_files_date = 0; $compressed_js_filename = ''; $js_external_files = array(); $protocol_link = Tools::getCurrentUrlProtocolPrefix(); // get js files infos foreach ($js_files as $filename) { $expr = explode(':', $filename); if ($expr[0] == 'http') { $js_external_files[] = $filename; } else { $infos = array(); $infos['uri'] = $filename; $url_data = parse_url($filename); $infos['path'] = _PS_ROOT_DIR_ . Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); $js_files_infos[] = $infos; $js_files_date = max(file_exists($infos['path']) ? filemtime($infos['path']) : 0, $js_files_date); $compressed_js_filename .= $filename; } } // get compressed js file infos $compressed_js_filename = md5($compressed_js_filename); $compressed_js_path = getThemeDir() . 'cache/' . $compressed_js_filename . '.js'; $compressed_js_file_date = file_exists($compressed_js_path) ? filemtime($compressed_js_path) : 0; // aggregate and compress js files content, write new caches files if ($js_files_date > $compressed_js_file_date) { $content = ''; foreach ($js_files_infos as $file_infos) { if (file_exists($file_infos['path'])) { $content .= file_get_contents($file_infos['path']) . ';'; } else { $compressed_js_files_not_found[] = $file_infos['path']; } } $content = Media::packJS($content); if (!empty($compressed_js_files_not_found)) { $content = '/* WARNING ! file(s) not found : "' . implode(',', $compressed_js_files_not_found) . '" */' . "\n" . $content; } file_put_contents($compressed_js_path, $content); chmod($compressed_js_path, 0777); } // rebuild the original js_files array $url = str_replace(_PS_ROOT_DIR_ . '/', __PS_BASE_URI__, $compressed_js_path); return array_merge(array($protocol_link . Tools::getMediaServer($url) . $url), $js_external_files); }
function getTemplateVars() { $vars = array(); $controllers = getTemplateControllers(); foreach (Theme::getAvailable(false) as $themeName) { $themeDir = getThemeDir($themeName); $path = $themeDir . '/templates/templates.php'; if (file_exists($path)) { require_once $path; } foreach ($controllers as $type => $controller) { $name = getTemplateName($themeName, $type); $value = Configuration::get($name, false); if (!$value && isset($templates)) { // template settings has not been saved to database yet or it's preview theme foreach ($templates[$type] as $t) { if (isset($t['name']) && $t['name'] == $type) { $value = $type . '_' . $t['id']; } } } if ($value) { $c = strtolower($controller); $vars[$themeName][$c] = $value; } } } return $vars; }
function uploadFile($themeName, $filename, $tmp_path) { $themeDir = FilesHelper::normalizePath(getThemeDir($themeName)); $previewThemeDir = FilesHelper::normalizePath(getThemeDir($themeName . _PREVIEW_SUFFIX_)); $base_dir = $previewThemeDir . '/img'; $base_path = $base_dir . '/' . $filename; FilesHelper::deleteFile($base_path); FilesHelper::createDir($base_dir); FilesHelper::renameFile($tmp_path, $base_path); $changed_files = getPreviewChangedFiles($themeDir); $changed_files[] = $base_path; setPreviewChangedFiles($themeDir, $previewThemeDir, $changed_files); return array('status' => 'done', 'url' => Designer::getBaseUrlWithLastSlash() . 'themes/' . $themeName . '_preview/img/' . $filename); }
public static function cccJS($js_files) { require_once dirname(__FILE__) . '../../../modules/designerpreview/defines.inc.php'; $theme_dir = getThemeDir(); //inits $compressed_js_files_not_found = array(); $js_files_infos = array(); $js_files_date = 0; $compressed_js_filename = ''; $js_external_files = array(); $protocol_link = Tools::getCurrentUrlProtocolPrefix(); $cache_path = $theme_dir . 'cache/'; // get js files infos foreach ($js_files as $filename) { if (Validate::isAbsoluteUrl($filename)) { $js_external_files[] = $filename; } else { $infos = array(); $infos['uri'] = $filename; $url_data = parse_url($filename); $infos['path'] = _PS_ROOT_DIR_ . Tools::str_replace_once(__PS_BASE_URI__, '/', $url_data['path']); $js_files_infos[] = $infos; $js_files_date = max(file_exists($infos['path']) ? @filemtime($infos['path']) : 0, $js_files_date); $compressed_js_filename .= $filename; } } // get compressed js file infos $compressed_js_filename = md5($compressed_js_filename); $version = (int) Configuration::get('PS_CCCJS_VERSION'); $compressed_js_path = $cache_path . 'v_' . $version . '_' . $compressed_js_filename . '.js'; $compressed_js_file_date = file_exists($compressed_js_path) ? @filemtime($compressed_js_path) : 0; // aggregate and compress js files content, write new caches files if ($js_files_date > $compressed_js_file_date) { if ($compressed_js_file_date) { Configuration::updateValue('PS_CCCJS_VERSION', ++$version); } $compressed_js_path = $cache_path . 'v_' . $version . '_' . $compressed_js_filename . '.js'; $content = ''; foreach ($js_files_infos as $file_infos) { if (file_exists($file_infos['path'])) { $tmp_content = file_get_contents($file_infos['path']); if (preg_match('@\\.(min|pack)\\.[^/]+$@', $file_infos['path'], $matches)) { $content .= preg_replace('/\\/\\/@\\ssourceMappingURL\\=[_a-zA-Z0-9-.]+\\.' . $matches[1] . '\\.map\\s+/', '', $tmp_content); } else { $content .= Media::packJS($tmp_content); } } else { $compressed_js_files_not_found[] = $file_infos['path']; } } if (!empty($compressed_js_files_not_found)) { $content = '/* WARNING ! file(s) not found : "' . implode(',', $compressed_js_files_not_found) . '" */' . "\n" . $content; } file_put_contents($compressed_js_path, $content); chmod($compressed_js_path, 0777); } // rebuild the original js_files array $url = str_replace(_PS_ROOT_DIR_ . '/', __PS_BASE_URI__, $compressed_js_path); return array_merge(array($protocol_link . Tools::getMediaServer($url) . $url), $js_external_files); }
public function canRename($newThemeName) { $result = $this->validate($newThemeName); if ($result['message']) { return $result; } if (file_exists(FilesHelper::normalizePath(getThemeDir($newThemeName)))) { $result['message'] = 'Theme with such name already exists'; } return $result; }
private function _checkPermissions($themeName) { $themeDir = FilesHelper::normalizePath(getThemeDir($themeName)); $previewDir = $themeDir . _PREVIEW_SUFFIX_; $dirs = array(_PS_OVERRIDE_DIR_, _PS_DOWNLOAD_DIR_, _PS_MODULE_DIR_, _PS_UPLOAD_DIR_, $themeDir, $previewDir); foreach ($dirs as $dir) { $rootOnly = strpos($dir, '/themes/') === FALSE; // check themes subdirectories only $check = FilesHelper::checkFiles($dir, true, true, $rootOnly); } return true; }