* @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ declare(strict_types=1); namespace PrestaShopBundle\Bridge\Smarty; use Cookie; use Country; use Currency; use Language; use Link; use Media; use PrestaShop\PrestaShop\Adapter\Configuration; use PrestaShop\PrestaShop\Adapter\LegacyContext; use PrestaShop\PrestaShop\Core\Action\ActionsBarButtonsCollection; use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface; use PrestaShop\PrestaShop\Core\Hook\RenderedHookInterface; use PrestaShop\PrestaShop\Core\Localization\Locale; use PrestaShop\PrestaShop\Core\Localization\Specification\Number as NumberSpecification; use PrestaShop\PrestaShop\Core\Localization\Specification\Price as PriceSpecification; use PrestaShopBundle\Bridge\AdminController\ControllerConfiguration; use QuickAccess; use Shop; use Symfony\Contracts\Translation\TranslatorInterface; use Tab; use Tools; /** * Sets template variables for header. * For example notification tips, employee information, quick access... */ class HeaderConfigurator implements ConfiguratorInterface { /** * @var Cookie */ private $cookie; /** * @var Country */ private $country; /** * @var Currency */ private $currency; /** * @var Locale */ private $currentLocale; /** * @var Language */ private $language; /** * @var Link */ private $link; /** * @var Shop */ private $shop; /** * @var TranslatorInterface */ private $translator; /** * @var HookDispatcherInterface */ private $hookDispatcher; /** * @var Configuration */ private $configuration; /** * @param TranslatorInterface $translator * @param LegacyContext $legacyContext * @param HookDispatcherInterface $hookDispatcher * @param Configuration $configuration */ public function __construct( TranslatorInterface $translator, LegacyContext $legacyContext, HookDispatcherInterface $hookDispatcher, Configuration $configuration ) { $this->cookie = $legacyContext->getContext()->cookie; $this->country = $legacyContext->getContext()->country; $this->link = $legacyContext->getContext()->link; $this->language = $legacyContext->getLanguage(); $this->currency = $legacyContext->getContext()->currency; $this->currentLocale = $legacyContext->getContext()->getCurrentLocale(); $this->shop = $legacyContext->getContext()->shop; $this->translator = $translator; $this->hookDispatcher = $hookDispatcher; $this->configuration = $configuration; } /** * Assign smarty variables for the header. * * @param ControllerConfiguration $controllerConfiguration * * @return void */ public function configure(ControllerConfiguration $controllerConfiguration): void { $controllerConfiguration->templateVars['table'] = $controllerConfiguration->tableName; $controllerConfiguration->templateVars['token'] = $controllerConfiguration->token; $controllerConfiguration->templateVars['host_mode'] = (int) defined('_PS_HOST_MODE_'); $controllerConfiguration->templateVars['stock_management'] = (int) $this->configuration->get('PS_STOCK_MANAGEMENT'); $controllerConfiguration->templateVars['no_order_tip'] = $this->getNotificationTip('order'); $controllerConfiguration->templateVars['no_customer_tip'] = $this->getNotificationTip('customer'); $controllerConfiguration->templateVars['no_customer_message_tip'] = $this->getNotificationTip('customer_message'); if ($controllerConfiguration->displayHeader) { $controllerConfiguration->templateVars['displayBackOfficeHeader'] = $this->getDisplayHookRender( $this->hookDispatcher->dispatchRenderingWithParameters('displayBackOfficeHeader', []) ); } $menuLinksCollections = new ActionsBarButtonsCollection(); $this->hookDispatcher->dispatchWithParameters( 'displayBackOfficeEmployeeMenu', [ 'links' => $menuLinksCollections, ] ); $controllerConfiguration->templateVars['displayBackOfficeTop'] = $this->getDisplayHookRender( $this->hookDispatcher->dispatchRenderingWithParameters('displayBackOfficeTop', []) ); $controllerConfiguration->templateVars['displayBackOfficeEmployeeMenu'] = $menuLinksCollections; $controllerConfiguration->templateVars['submit_form_ajax'] = (int) Tools::getValue('submitFormAjax'); $tabs = $this->getTabs($controllerConfiguration); $currentTabLevel = 0; foreach ($tabs as $tab) { $currentTabLevel = isset($tab['current_level']) ? $tab['current_level'] : $currentTabLevel; } $controllerConfiguration->templateVars['bo_query'] = Tools::safeOutput(Tools::stripslashes(Tools::getValue('bo_query'))); $controllerConfiguration->templateVars['collapse_menu'] = isset($this->cookie->collapse_menu) ? (int) $this->cookie->collapse_menu : 0; $controllerConfiguration->templateVars['default_tab_link'] = $this->link->getAdminLink(Tab::getClassNameById((int) $controllerConfiguration->getUser()->getData()->default_tab)); $controllerConfiguration->templateVars['employee'] = $controllerConfiguration->getUser()->getData(); $controllerConfiguration->templateVars['help_box'] = $this->configuration->get('PS_HELPBOX'); $controllerConfiguration->templateVars['is_multishop'] = Shop::isFeatureActive(); $controllerConfiguration->templateVars['login_link'] = $this->link->getAdminLink('AdminLogin'); $controllerConfiguration->templateVars['logout_link'] = $this->link->getAdminLink('AdminLogin', true, [], ['logout' => 1]); $controllerConfiguration->templateVars['multi_shop'] = Shop::isFeatureActive(); $controllerConfiguration->templateVars['quick_access'] = QuickAccess::getQuickAccessesWithToken($this->language->id, (int) $controllerConfiguration->getUser()->getData()->id); $controllerConfiguration->templateVars['round_mode'] = $this->configuration->get('PS_PRICE_ROUND_MODE'); $controllerConfiguration->templateVars['base_url'] = $this->shop->getBaseURL(true); $controllerConfiguration->templateVars['bootstrap'] = $controllerConfiguration->bootstrap; $controllerConfiguration->templateVars['controller_name'] = $controllerConfiguration->legacyControllerName; $controllerConfiguration->templateVars['country_iso_code'] = $this->country->iso_code; $controllerConfiguration->templateVars['currentIndex'] = $controllerConfiguration->legacyCurrentIndex; $controllerConfiguration->templateVars['current_tab_level'] = $currentTabLevel; $controllerConfiguration->templateVars['default_language'] = (int) $this->configuration->get('PS_LANG_DEFAULT'); $controllerConfiguration->templateVars['full_language_code'] = $this->language->language_code; $controllerConfiguration->templateVars['full_cldr_language_code'] = $this->currentLocale->getCode(); $controllerConfiguration->templateVars['img_dir'] = _PS_IMG_; $controllerConfiguration->templateVars['install_dir_exists'] = file_exists(_PS_ADMIN_DIR_ . '/../install'); $controllerConfiguration->templateVars['iso'] = $this->language->iso_code; $controllerConfiguration->templateVars['iso_user'] = $this->language->iso_code; $controllerConfiguration->templateVars['lang_is_rtl'] = $this->language->is_rtl; $controllerConfiguration->templateVars['link'] = $this->link; $controllerConfiguration->templateVars['shop_name'] = $this->configuration->get('PS_SHOP_NAME'); $controllerConfiguration->templateVars['tabs'] = $tabs; $controllerConfiguration->templateVars['version'] = _PS_VERSION_; $controllerConfiguration->templateVars['multishop_context'] = $controllerConfiguration->multiShopContext; Media::addJsDef( [ 'currency_specifications' => $this->preparePriceSpecifications(), 'number_specifications' => $this->prepareNumberSpecifications(), ] ); } /** * @param string $type * * @return string */ private function getNotificationTip(string $type): string { $tips = [ 'order' => [ $this->translator->trans( 'Have you checked your [1][2]abandoned carts[/2][/1]?[3]Your next order could be hiding there!', [ '[1]' => '', '[/1]' => '', '[2]' => '', '[/2]' => '', '[3]' => '
', ], 'Admin.Navigation.Notification' ), ], 'customer' => [ $this->translator->trans('Are you active on social media these days?', [], 'Admin.Navigation.Notification'), ], 'customer_message' => [ $this->translator->trans('Seems like all your customers are happy :)', [], 'Admin.Navigation.Notification'), ], ]; if (!isset($tips[$type])) { return ''; } return $tips[$type][array_rand($tips[$type])]; } /** * @param RenderedHookInterface $renderedHook * * @return string|null */ private function getDisplayHookRender(RenderedHookInterface $renderedHook): ?string { if (!$content = $renderedHook->getContent()) { return null; } $result = ''; foreach ($content as $hookContent) { $result .= implode($hookContent); } return $result; } /** * @param ControllerConfiguration $controllerConfiguration * @param int $parentId * @param int $level * * @return array */ private function getTabs(ControllerConfiguration $controllerConfiguration, $parentId = 0, $level = 0): array { $tabs = Tab::getTabs($this->language->id, $parentId); $current_id = Tab::getCurrentParentId(); foreach ($tabs as $index => $tab) { if (!Tab::checkTabRights($tab['id_tab']) || !$tab['enabled'] || ($tab['class_name'] == 'AdminStock' && $this->configuration->get('PS_ADVANCED_STOCK_MANAGEMENT') == 0) || $tab['class_name'] == 'AdminCarrierWizard') { unset($tabs[$index]); continue; } // tab[class_name] does not contains the "Controller" suffix if (($tab['class_name'] . 'Controller' == $controllerConfiguration->legacyControllerName) || ($current_id == $tab['id_tab']) || $tab['class_name'] == $controllerConfiguration->legacyControllerName) { $tabs[$index]['current'] = true; $tabs[$index]['current_level'] = $level; } else { $tabs[$index]['current'] = false; } $tabs[$index]['img'] = null; $tabs[$index]['href'] = $this->link->getTabLink($tab); $tabs[$index]['sub_tabs'] = array_values($this->getTabs($controllerConfiguration, $tab['id_tab'], $level + 1)); $subTabHref = $this->getTabLinkFromSubTabs($tabs[$index]['sub_tabs']); if (!empty($subTabHref)) { $tabs[$index]['href'] = $subTabHref; } elseif (0 == $tabs[$index]['id_parent'] && '' == $tabs[$index]['icon']) { unset($tabs[$index]); } elseif (empty($tabs[$index]['icon'])) { $tabs[$index]['icon'] = 'extension'; } if (array_key_exists($index, $tabs) && array_key_exists('sub_tabs', $tabs[$index])) { foreach ($tabs[$index]['sub_tabs'] as $sub_tab) { if ((int) $sub_tab['current'] == true) { $tabs[$index]['current'] = true; $tabs[$index]['current_level'] = $sub_tab['current_level']; } } } } return $tabs; } /** * Get the url of the first active sub-tab. * * @param array[] $subtabs * * @return string Url, or empty if no active sub-tab */ private function getTabLinkFromSubTabs(array $subtabs): string { foreach ($subtabs as $tab) { if ($tab['active'] && $tab['enabled']) { return $tab['href']; } } return ''; } /** * Prepare price specifications to display cldr prices in javascript context. * * @return array */ private function preparePriceSpecifications(): array { /* @var PriceSpecification */ $priceSpecification = $this->currentLocale->getPriceSpecification($this->currency->iso_code); return array_merge( ['symbol' => $priceSpecification->getSymbolsByNumberingSystem(Locale::NUMBERING_SYSTEM_LATIN)->toArray()], $priceSpecification->toArray() ); } /** * Prepare number specifications to display cldr numbers in javascript context. * * @return array */ private function prepareNumberSpecifications(): array { /* @var NumberSpecification */ $numberSpecification = $this->currentLocale->getNumberSpecification(); return array_merge( ['symbol' => $numberSpecification->getSymbolsByNumberingSystem(Locale::NUMBERING_SYSTEM_LATIN)->toArray()], $numberSpecification->toArray() ); } }