public function parseTemplate($templateType, $template) { $templateDefinition = new TemplateDefinition($template, $templateType); $hooks = array(); $this->walkDir($templateDefinition->getAbsolutePath(), $hooks); // load language message $locale = Lang::getDefaultLanguage()->getLocale(); $this->loadTrans($templateType, $locale); $ret = array(); foreach ($hooks as $hook) { try { $ret[] = $this->prepareHook($hook); } catch (\UnexpectedValueException $ex) { Tlog::getInstance()->warning($ex->getMessage()); } } return $ret; }
/** * Add all module's standard templates to the parser environment * * @param ParserInterface $parser the parser * @param Module $module the Module. */ protected function addStandardModuleTemplatesToParserEnvironment($parser, $module) { $stdTpls = TemplateDefinition::getStandardTemplatesSubdirsIterator(); foreach ($stdTpls as $templateType => $templateSubdirName) { $this->addModuleTemplateToParserEnvironment($parser, $module, $templateType, $templateSubdirName); } }
public function registerHooks() { $moduleHooks = $this->getHooks(); if (is_array($moduleHooks) && !empty($moduleHooks)) { $allowedTypes = (array) TemplateDefinition::getStandardTemplatesSubdirsIterator(); $defaultLang = Lang::getDefaultLanguage(); $defaultLocale = $defaultLang->getLocale(); $dispatcher = $this->container->get("event_dispatcher"); foreach ($moduleHooks as $hook) { $isValid = is_array($hook) && isset($hook["type"]) && array_key_exists($hook["type"], $allowedTypes) && isset($hook["code"]) && is_string($hook["code"]) && !empty($hook["code"]); if (!$isValid) { Tlog::getInstance()->notice("The module " . $this->getCode() . " tried to register an invalid hook"); continue; } /** * Create or update hook db entry. */ list($hookModel, $updateData) = $this->createOrUpdateHook($hook, $dispatcher, $defaultLocale); /** * Update translations */ $event = new HookUpdateEvent($hookModel->getId()); foreach ($updateData as $locale => $data) { $event->setCode($hookModel->getCode())->setNative($hookModel->getNative())->setByModule($hookModel->getByModule())->setActive($hookModel->getActivate())->setBlock($hookModel->getBlock())->setNative($hookModel->getNative())->setType($hookModel->getType())->setLocale($locale)->setChapo($data["chapo"])->setTitle($data["title"])->setDescription($data["description"]); $dispatcher->dispatch(TheliaEvents::HOOK_UPDATE, $event); } } } }
protected function renderTemplate() { // Get related strings, if all input data are here $itemToTranslate = $this->getRequest()->get('item_to_translate'); $itemName = $this->getRequest()->get('item_name', ''); if ($itemToTranslate == 'mo' && !empty($itemName)) { $modulePart = $this->getRequest()->get('module_part', ''); } else { $modulePart = false; } $template = $directory = $i18nDirectory = false; $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; $templateArguments = array('item_to_translate' => $itemToTranslate, 'item_name' => $itemName, 'module_part' => $modulePart, 'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only'), 'max_input_vars_warning' => false); // Find the i18n directory, and the directory to examine. if (!empty($itemName) || $itemToTranslate == 'co' || $itemToTranslate == 'in') { switch ($itemToTranslate) { // Module core case 'mo': $module = $this->getModule($itemName); if ($modulePart == 'core') { $directory = $module->getAbsoluteBaseDir(); $domain = $module->getTranslationDomain(); $i18nDirectory = $module->getAbsoluteI18nPath(); $walkMode = TranslationEvent::WALK_MODE_PHP; } elseif ($modulePart == 'admin-includes') { $directory = $module->getAbsoluteAdminIncludesPath(); $domain = $module->getAdminIncludesTranslationDomain(); $i18nDirectory = $module->getAbsoluteAdminIncludesI18nPath(); $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; } elseif (!empty($modulePart)) { // Front, back, pdf or email office template, // form of $module_part is [bo|fo|pdf|email].subdir-name list($type, $subdir) = explode('.', $modulePart); switch ($type) { case 'bo': $directory = $module->getAbsoluteBackOfficeTemplatePath($subdir); $domain = $module->getBackOfficeTemplateTranslationDomain($subdir); $i18nDirectory = $module->getAbsoluteBackOfficeI18nTemplatePath($subdir); break; case 'fo': $directory = $module->getAbsoluteFrontOfficeTemplatePath($subdir); $domain = $module->getFrontOfficeTemplateTranslationDomain($subdir); $i18nDirectory = $module->getAbsoluteFrontOfficeI18nTemplatePath($subdir); break; case 'email': $directory = $module->getAbsoluteEmailTemplatePath($subdir); $domain = $module->getEmailTemplateTranslationDomain($subdir); $i18nDirectory = $module->getAbsoluteEmailI18nTemplatePath($subdir); break; case 'pdf': $directory = $module->getAbsolutePdfTemplatePath($subdir); $domain = $module->getPdfTemplateTranslationDomain($subdir); $i18nDirectory = $module->getAbsolutePdfI18nTemplatePath($subdir); break; default: throw new \InvalidArgumentException("Undefined module template type: '{$type}'."); } $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; } // Modules translations files are in the cache, and are not always // updated. Force a reload of the files to get last changes. if (!empty($domain)) { $this->loadTranslation($i18nDirectory, $domain); } // List front and back office templates defined by this module $templateArguments['back_office_templates'] = implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::BACK_OFFICE)); $templateArguments['front_office_templates'] = implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::FRONT_OFFICE)); $templateArguments['email_templates'] = implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::EMAIL)); $templateArguments['pdf_templates'] = implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::PDF)); // Check if we have admin-include files try { $finder = Finder::create()->files()->depth(0)->in($module->getAbsoluteAdminIncludesPath())->name('/\\.html$/i'); $hasAdminIncludes = $finder->count() > 0; } catch (\InvalidArgumentException $ex) { $hasAdminIncludes = false; } $templateArguments['has_admin_includes'] = $hasAdminIncludes; break; // Thelia Core // Thelia Core case 'co': $directory = THELIA_LIB; $domain = 'core'; $i18nDirectory = THELIA_LIB . 'Config' . DS . 'I18n'; $walkMode = TranslationEvent::WALK_MODE_PHP; break; // Thelia Install // Thelia Install case 'in': $directory = THELIA_SETUP_DIRECTORY; $domain = 'install'; $i18nDirectory = THELIA_SETUP_DIRECTORY . 'I18n'; $walkMode = TranslationEvent::WALK_MODE_TEMPLATE; // resources not loaded by default $this->loadTranslation($i18nDirectory, $domain); break; // Front-office template // Front-office template case 'fo': $template = new TemplateDefinition($itemName, TemplateDefinition::FRONT_OFFICE); break; // Back-office template // Back-office template case 'bo': $template = new TemplateDefinition($itemName, TemplateDefinition::BACK_OFFICE); break; // PDF templates // PDF templates case 'pf': $template = new TemplateDefinition($itemName, TemplateDefinition::PDF); break; // Email templates // Email templates case 'ma': $template = new TemplateDefinition($itemName, TemplateDefinition::EMAIL); break; } if ($template) { $directory = $template->getAbsolutePath(); $i18nDirectory = $template->getAbsoluteI18nPath(); $domain = $template->getTranslationDomain(); // Load translations files is this template is not the current template // as it is not loaded in Thelia.php if (!$this->getTemplateHelper()->isActive($template)) { $this->loadTranslation($i18nDirectory, $domain); } } // Load strings to translate if ($directory && !empty($domain)) { // Save the string set, if the form was submitted if ($i18nDirectory) { $save_mode = $this->getRequest()->get('save_mode', false); if ($save_mode !== false) { $texts = $this->getRequest()->get('text', array()); if (!empty($texts)) { $event = TranslationEvent::createWriteFileEvent(sprintf("%s" . DS . "%s.php", $i18nDirectory, $this->getCurrentEditionLocale()), $texts, $this->getRequest()->get('translation', []), true); $event->setDomain($domain)->setLocale($this->getCurrentEditionLocale())->setCustomFallbackStrings($this->getRequest()->get('translation_custom', []))->setGlobalFallbackStrings($this->getRequest()->get('translation_global', [])); $this->getDispatcher()->dispatch(TheliaEvents::TRANSLATION_WRITE_FILE, $event); if ($save_mode == 'stay') { return $this->generateRedirectFromRoute("admin.configuration.translations", $templateArguments); } else { return $this->generateRedirect(URL::getInstance()->adminViewUrl('configuration')); } } } } // Load strings $event = TranslationEvent::createGetStringsEvent($directory, $walkMode, $this->getCurrentEditionLocale(), $domain); $this->getDispatcher()->dispatch(TheliaEvents::TRANSLATION_GET_STRINGS, $event); // Estimate number of fields, and compare to php ini max_input_vars $stringsCount = $event->getTranslatableStringCount() * 4 + 6; if ($stringsCount > ini_get('max_input_vars')) { $templateArguments['max_input_vars_warning'] = true; $templateArguments['required_max_input_vars'] = $stringsCount; $templateArguments['current_max_input_vars'] = ini_get('max_input_vars'); } else { $templateArguments['all_strings'] = $event->getTranslatableStrings(); } $templateArguments['is_writable'] = $this->checkWritableI18nDirectory(THELIA_LOCAL_DIR . 'I18n'); } } return $this->render('translations', $templateArguments); }
/** * Return a list of existing templates for a given template type * * @param int $templateType the template type * @param string the template base (module or core, default to core). * @return TemplateDefinition[] of \Thelia\Core\Template\TemplateDefinition */ public function getList($templateType, $base = THELIA_TEMPLATE_DIR) { $list = $exclude = array(); $tplIterator = TemplateDefinition::getStandardTemplatesSubdirsIterator(); foreach ($tplIterator as $type => $subdir) { if ($templateType == $type) { $baseDir = rtrim($base, DS) . DS . $subdir; try { // Every subdir of the basedir is supposed to be a template. $di = new \DirectoryIterator($baseDir); /** @var \DirectoryIterator $file */ foreach ($di as $file) { // Ignore 'dot' elements if ($file->isDot() || !$file->isDir()) { continue; } // Ignore reserved directory names if (in_array($file->getFilename(), $exclude)) { continue; } $list[] = new TemplateDefinition($file->getFilename(), $templateType); } } catch (\UnexpectedValueException $ex) { // Ignore the exception and continue } } } return $list; }
/** * @return string the template path */ public function getTemplatePath() { return $this->templateDefinition->getPath(); }
protected function renderTemplate() { // Get related strings, if all input data are here $item_to_translate = $this->getRequest()->get('item_to_translate'); $item_name = $this->getRequest()->get('item_name', ''); if ($item_to_translate == 'mo' && !empty($item_name)) { $module_part = $this->getRequest()->get('module_part', ''); } else { $module_part = false; } $all_strings = array(); $template = $directory = $i18n_directory = false; $walkMode = TemplateHelper::WALK_MODE_TEMPLATE; $templateArguments = array('item_to_translate' => $item_to_translate, 'item_name' => $item_name, 'module_part' => $module_part, 'view_missing_traductions_only' => $this->getRequest()->get('view_missing_traductions_only', 0), 'max_input_vars_warning' => false); // Find the i18n directory, and the directory to examine. if (!empty($item_name) || $item_to_translate == 'co') { switch ($item_to_translate) { // Module core case 'mo': $module = $this->getModule($item_name); if ($module_part == 'core') { $directory = $module->getAbsoluteBaseDir(); $domain = $module->getTranslationDomain(); $i18n_directory = $module->getAbsoluteI18nPath(); $walkMode = TemplateHelper::WALK_MODE_PHP; } elseif ($module_part == 'admin-includes') { $directory = $module->getAbsoluteAdminIncludesPath(); $domain = $module->getAdminIncludesTranslationDomain(); $i18n_directory = $module->getAbsoluteAdminIncludesI18nPath(); $walkMode = TemplateHelper::WALK_MODE_TEMPLATE; } elseif (!empty($module_part)) { // Front or back office template, form of $module_part is [bo|fo].subdir-name list($type, $subdir) = explode('.', $module_part); if ($type == 'bo') { $directory = $module->getAbsoluteBackOfficeTemplatePath($subdir); $domain = $module->getBackOfficeTemplateTranslationDomain($subdir); $i18n_directory = $module->getAbsoluteBackOfficeI18nTemplatePath($subdir); } elseif ($type == 'fo') { $directory = $module->getAbsoluteFrontOfficeTemplatePath($subdir); $domain = $module->getFrontOfficeTemplateTranslationDomain($subdir); $i18n_directory = $module->getAbsoluteFrontOfficeI18nTemplatePath($subdir); } else { throw new \InvalidArgumentException("Undefined module template type: '{$type}'."); } $walkMode = TemplateHelper::WALK_MODE_TEMPLATE; } // Modules translations files are in the cache, and are not always // updated. Force a reload of the files to get last changes. if (!empty($domain)) { $this->loadTranslation($i18n_directory, $domain); } // List front and back office templates defined by this module $templateArguments['back_office_templates'] = implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::BACK_OFFICE)); $templateArguments['front_office_templates'] = implode(',', $this->getModuleTemplateNames($module, TemplateDefinition::FRONT_OFFICE)); // Check if we have admin-include files try { $finder = Finder::create()->files()->depth(0)->in($module->getAbsoluteAdminIncludesPath())->name('/\\.html$/i'); $hasAdminIncludes = $finder->count() > 0; } catch (\InvalidArgumentException $ex) { $hasAdminIncludes = false; } $templateArguments['has_admin_includes'] = $hasAdminIncludes; break; // Thelia Core // Thelia Core case 'co': $directory = THELIA_ROOT . 'core/lib/Thelia'; $domain = 'core'; $i18n_directory = THELIA_ROOT . 'core/lib/Thelia/Config/I18n'; $walkMode = TemplateHelper::WALK_MODE_PHP; break; // Front-office template // Front-office template case 'fo': $template = new TemplateDefinition($item_name, TemplateDefinition::FRONT_OFFICE); break; // Back-office template // Back-office template case 'bo': $template = new TemplateDefinition($item_name, TemplateDefinition::BACK_OFFICE); break; // PDF templates // PDF templates case 'pf': $template = new TemplateDefinition($item_name, TemplateDefinition::PDF); break; // Email templates // Email templates case 'ma': $template = new TemplateDefinition($item_name, TemplateDefinition::EMAIL); break; } if ($template) { $directory = $template->getAbsolutePath(); $i18n_directory = $template->getAbsoluteI18nPath(); $domain = $template->getTranslationDomain(); // Load translations files is this template is not the current template // as it is not loaded in Thelia.php if (!TemplateHelper::getInstance()->isActive($template)) { $this->loadTranslation($i18n_directory, $domain); } } // Load strings to translate if ($directory && !empty($domain)) { // Save the string set, if the form was submitted if ($i18n_directory) { $save_mode = $this->getRequest()->get('save_mode', false); if ($save_mode !== false) { $texts = $this->getRequest()->get('text', array()); if (!empty($texts)) { $file = sprintf("%s" . DS . "%s.php", $i18n_directory, $this->getCurrentEditionLocale()); $translations = $this->getRequest()->get('translation', array()); TemplateHelper::getInstance()->writeTranslation($file, $texts, $translations, true); if ($save_mode == 'stay') { return $this->generateRedirectFromRoute("admin.configuration.translations", $templateArguments); } else { return $this->generateRedirect(URL::getInstance()->adminViewUrl('configuration')); } } } } // Load strings $stringsCount = TemplateHelper::getInstance()->walkDir($directory, $walkMode, $this->getTranslator(), $this->getCurrentEditionLocale(), $domain, $all_strings); // Estimate number of fields, and compare to php ini max_input_vars $stringsCount = $stringsCount * 2 + 6; if ($stringsCount > ini_get('max_input_vars')) { $templateArguments['max_input_vars_warning'] = true; $templateArguments['required_max_input_vars'] = $stringsCount; $templateArguments['current_max_input_vars'] = ini_get('max_input_vars'); } else { $templateArguments['all_strings'] = $all_strings; } } } return $this->render('translations', $templateArguments); }
/** * Retrieve asset URL * * @param string $assetType js|css|image * @param array $params Parameters * - file File path in the default template * - source module asset * - filters filter to apply * - debug * - template if you want to load asset from another template * @param \Smarty_Internal_Template $template Smarty Template * * @return string * @throws \Exception */ public function computeAssetUrl($assetType, $params, \Smarty_Internal_Template $template) { $assetUrl = ""; $file = $params['file']; // The 'file' parameter is mandatory if (empty($file)) { throw new \InvalidArgumentException("The 'file' parameter is missing in an asset directive (type is '{$assetType}')"); } $assetOrigin = isset($params['source']) ? $params['source'] : SmartyParser::TEMPLATE_ASSETS_KEY; $filters = isset($params['filters']) ? $params['filters'] : ''; $debug = isset($params['debug']) ? trim(strtolower($params['debug'])) == 'true' : false; $templateName = isset($params['template']) ? $params['template'] : false; Tlog::getInstance()->debug("Searching asset {$file} in source {$assetOrigin}, with template {$templateName}"); /** @var \TheliaSmarty\Template\SmartyParser $smartyParser */ $smartyParser = $template->smarty; if (false !== $templateName) { // We have to be sure that this external template assets have been properly prepared. // We will assume the following: // 1) this template have the same type as the current template, // 2) this template assets have the same structure as the current template // (which is in self::$assetsDirectory) $currentTemplate = $smartyParser->getTemplateDefinition(); $templateDefinition = new TemplateDefinition($templateName, $currentTemplate->getType()); /* Add this templates directory to the current list */ $smartyParser->addTemplateDirectory($templateDefinition->getType(), $templateDefinition->getName(), THELIA_TEMPLATE_DIR . $templateDefinition->getPath(), SmartyParser::TEMPLATE_ASSETS_KEY); $this->prepareTemplateAssets($templateDefinition, self::$assetsDirectory, $smartyParser); } $assetSource = $this->assetsResolver->resolveAssetSourcePath($assetOrigin, $templateName, $file, $smartyParser); if (null !== $assetSource) { $assetUrl = $this->assetsResolver->resolveAssetURL($assetOrigin, $file, $assetType, $smartyParser, $filters, $debug, self::$assetsDirectory, $templateName); } else { // Log the problem Tlog::getInstance()->addError("Failed to find asset source file " . $params['file']); } return $assetUrl; }