Skip to content

Instantly share code, notes, and snippets.

@Dh42
Created September 27, 2018 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dh42/313485a75d3aeb2301a5cfd74f3f1b65 to your computer and use it in GitHub Desktop.
Save Dh42/313485a75d3aeb2301a5cfd74f3f1b65 to your computer and use it in GitHub Desktop.
thirty bees front controller using cloudflare geo-location
<?php
/**
* 2007-2016 PrestaShop.
*
* thirty bees is an extension to the PrestaShop e-commerce software developed by PrestaShop SA
* Copyright (C) 2017-2018 thirty bees
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@thirtybees.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://www.thirtybees.com for more information.
*
* @author thirty bees <contact@thirtybees.com>
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2017-2018 thirty bees
* @copyright 2007-2016 PrestaShop SA
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* PrestaShop is an internationally registered trademark & property of PrestaShop SA
*/
/**
* Class FrontControllerCore.
*
* @since 1.0.0
*/
class FrontControllerCore extends Controller
{
/**
* True if controller has already been initialized.
* Prevents initializing controller more than once.
*
* @var bool
*/
public static $initialized = false;
/**
* @deprecated Deprecated shortcuts as of 1.1.0 - Use $context->smarty instead
*
* @var Smarty $smarty
*/
protected static $smarty;
/**
* @deprecated Deprecated shortcuts as of 1.1.0 - Use $context->cookie instead
*
* @var Cookie $cookie
*/
protected static $cookie;
/**
* @deprecated Deprecated shortcuts as of 1.1.0 - Use $context->link instead
*
* @var Link $link
*/
protected static $link;
/**
* @deprecated Deprecated shortcuts as of 1.1.0 - Use $context->cart instead
*
* @var Cart $cart
*/
protected static $cart;
/**
* @var array Holds current customer's groups.
*/
protected static $currentCustomerGroups;
/** @var $errorsarray */
public $errors = [];
/** @var string Language ISO code */
public $iso;
/** @var string ORDER BY field */
public $orderBy;
/** @var string Order way string ('ASC', 'DESC') */
public $orderWay;
/** @var int Current page number */
public $p;
/** @var int Items (products) per page */
public $n;
/** @var bool If set to true, will redirected user to login page during init function. */
public $auth = false;
/**
* If set to true, user can be logged in as guest when checking if logged in.
*
* @see $auth
*
* @var bool
*/
public $guestAllowed = false;
/**
* Route of PrestaShop page to redirect to after forced login.
*
* @see $auth
*
* @var bool
*/
public $authRedirection = false;
/** @var bool SSL connection flag */
public $ssl = false;
// @codingStandardsIgnoreStart
/** @var bool If false, does not build left page column content and hides it. */
public $display_column_left = true;
/** @var bool If false, does not build right page column content and hides it. */
public $display_column_right = true;
/** @var int */
public $nb_items_per_page;
/** @var bool If true, switches display to restricted country page during init. */
protected $restrictedCountry = false;
/** @var bool If true, forces display to maintenance page. */
protected $maintenance = false;
// @codingStandardsIgnoreEnd
/**
* Controller constructor.
*
* @global bool $useSSL SSL connection flag
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function __construct()
{
$this->controller_type = 'front';
global $useSSL;
parent::__construct();
if (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE')) {
$this->ssl = true;
}
if (isset($useSSL)) {
$this->ssl = $useSSL;
} else {
$useSSL = $this->ssl;
}
if (isset($this->php_self) && is_object($this->context->theme)) {
$columns = $this->context->theme->hasColumns($this->php_self);
// Don't use theme tables if not configured in DB
if ($columns) {
$this->display_column_left = $columns['left_column'];
$this->display_column_right = $columns['right_column'];
}
}
}
/**
* Sets and returns customer groups that the current customer(visitor) belongs to.
*
* @return array
*
* @throws PrestaShopDatabaseException
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
* @throws PrestaShopException
*/
public static function getCurrentCustomerGroups()
{
if (!Group::isFeatureActive()) {
return [];
}
$context = Context::getContext();
if (!isset($context->customer) || !$context->customer->id) {
return [];
}
if (!is_array(static::$currentCustomerGroups)) {
static::$currentCustomerGroups = [];
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(
(new DbQuery())
->select('`id_group`')
->from('customer_group')
->where('`id_customer` = '.(int) $context->customer->id)
);
foreach ($result as $row) {
static::$currentCustomerGroups[] = $row['id_group'];
}
}
return static::$currentCustomerGroups;
}
/**
* Check if the controller is available for the current user/visitor.
*
* @see Controller::checkAccess()
*
* @return bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function checkAccess()
{
return true;
}
/**
* Check if the current user/visitor has valid view permissions.
*
* @see Controller::viewAccess
*
* @return bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function viewAccess()
{
return true;
}
/**
* Method that is executed after init() and checkAccess().
* Used to process user input.
*
* @see Controller::run()
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function postProcess()
{
}
/**
* Initializes common front page content: header, footer and side columns.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
* @throws PrestaShopException
*/
public function initContent()
{
$this->process();
if (!isset($this->context->cart)) {
$this->context->cart = new Cart();
}
if (!$this->useMobileTheme()) {
// These hooks aren't used for the mobile theme.
// Needed hooks are called in the tpl files.
$hookHeader = Hook::exec('displayHeader');
$faviconTemplate = preg_replace('/\<br(\s*)?\/?\>/i', "\n", Configuration::get('TB_SOURCE_FAVICON_CODE'));
if (!empty(trim($faviconTemplate))) {
$dom = new DOMDocument();
$dom->loadHTML($faviconTemplate);
$links = [];
foreach ($dom->getElementsByTagName('link') as $elem) {
$links[] = $elem;
}
foreach ($dom->getElementsByTagName('meta') as $elem) {
$links[] = $elem;
}
$faviconHtml = '';
foreach ($links as $link) {
foreach ($link->attributes as $attribute) {
/** @var DOMElement $link */
if ($favicon = Tools::parseFaviconSizeTag(urldecode($attribute->value))) {
$attribute->value = Media::getMediaPath(_PS_IMG_DIR_."favicon/favicon_{$this->context->shop->id}_{$favicon['width']}_{$favicon['height']}.{$favicon['type']}");
}
}
$faviconHtml .= $dom->saveHTML($link);
}
if ($faviconHtml) {
$hookHeader .= $faviconHtml;
}
$hookHeader .= '<meta name="msapplication-config" content="'.Media::getMediaPath(_PS_IMG_DIR_."favicon/browserconfig_{$this->context->shop->id}.xml").'">';
$hookHeader .= '<link rel="manifest" href="'.Media::getMediaPath(_PS_IMG_DIR_."favicon/manifest_{$this->context->shop->id}.json").'">';
}
if (isset($this->php_self)) { // append some seo fields, canonical, hrefLang, rel prev/next
$hookHeader .= $this->getSeoFields();
}
// To be removed: append extra css and metas to the header hook
$extraCode = Configuration::getMultiple([Configuration::CUSTOMCODE_METAS, Configuration::CUSTOMCODE_CSS]);
$extraCss = $extraCode[Configuration::CUSTOMCODE_CSS] ? '<style>'.$extraCode[Configuration::CUSTOMCODE_CSS].'</style>' : '';
$hookHeader .= $extraCode[Configuration::CUSTOMCODE_METAS].$extraCss;
$this->context->smarty->assign(
[
'HOOK_HEADER' => $hookHeader,
'HOOK_TOP' => Hook::exec('displayTop'),
'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''),
'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', ['cart' => $this->context->cart]) : ''),
]
);
} else {
$this->context->smarty->assign('HOOK_MOBILE_HEADER', Hook::exec('displayMobileHeader'));
}
}
/**
* Called before compiling common page sections (header, footer, columns).
* Good place to modify smarty variables.
*
* @see FrontController::initContent()
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function process()
{
}
/**
* Checks if mobile theme is active and in use.
*
* @staticvar bool|null $use_mobile_template
*
* @return bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function useMobileTheme()
{
static $useMobileTemplate = null;
// The mobile theme must have a layout to be used
if ($useMobileTemplate === null) {
$useMobileTemplate = ($this->context->getMobileDevice() && file_exists(_PS_THEME_MOBILE_DIR_.'layout.tpl'));
}
return $useMobileTemplate;
}
/**
* Generates html for additional seo tags.
*
* @return string html code for the new tags
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
* @throws PrestaShopException
*/
public function getSeoFields()
{
$content = '';
$languages = Language::getLanguages();
$defaultLang = Configuration::get('PS_LANG_DEFAULT');
switch ($this->php_self) {
case 'product': // product page
$idProduct = (int) Tools::getValue('id_product');
$canonical = $this->context->link->getProductLink($idProduct);
$hreflang = $this->getHrefLang('product', $idProduct, $languages, $defaultLang);
break;
case 'category':
$idCategory = (int) Tools::getValue('id_category');
$content .= $this->getRelPrevNext('category', $idCategory);
$canonical = $this->context->link->getCategoryLink((int) $idCategory);
$hreflang = $this->getHrefLang('category', $idCategory, $languages, $defaultLang);
break;
case 'manufacturer':
$idManufacturer = (int) Tools::getValue('id_manufacturer');
$content .= $this->getRelPrevNext('manufacturer', $idManufacturer);
$hreflang = $this->getHrefLang('manufacturer', $idManufacturer, $languages, $defaultLang);
if (!$idManufacturer) {
$canonical = $this->context->link->getPageLink('manufacturer');
} else {
$canonical = $this->context->link->getManufacturerLink($idManufacturer);
}
break;
case 'supplier':
$idSupplier = (int) Tools::getValue('id_supplier');
$content .= $this->getRelPrevNext('supplier', $idSupplier);
$hreflang = $this->getHrefLang('supplier', $idSupplier, $languages, $defaultLang);
if (!Tools::getValue('id_supplier')) {
$canonical = $this->context->link->getPageLink('supplier');
} else {
$canonical = $this->context->link->getSupplierLink((int) Tools::getValue('id_supplier'));
}
break;
case 'cms':
$idCms = Tools::getValue('id_cms');
$idCmsCategory = Tools::getValue('id_cms_category');
if ($idCms) {
$canonical = $this->context->link->getCMSLink((int) $idCms);
$hreflang = $this->getHrefLang('cms', (int) $idCms, $languages, $defaultLang);
} else {
$canonical = $this->context->link->getCMSCategoryLink((int) $idCmsCategory);
$hreflang = $this->getHrefLang('cms_category', (int) $idCmsCategory, $languages, $defaultLang);
}
break;
default:
$canonical = $this->context->link->getPageLink($this->php_self);
$hreflang = $this->getHrefLang($this->php_self, 0, $languages, $defaultLang);
break;
}
// build new content
$content .= '<link rel="canonical" href="'.$canonical.'">'."\n";
if (is_array($hreflang) && !empty($hreflang)) {
foreach ($hreflang as $lang) {
$content .= "$lang\n";
}
}
return $content;
}
/**
* creates hrefLang links for various entities.
*
* @param string $entity name of the object/page to get the link for
* @param int $idItem eventual id of the object (if any)
* @param array $languages list of languages
* @param int $idLangDefault id of the default language
*
* @return string[] HTML of the hreflang tags
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function getHrefLang($entity, $idItem, $languages, $idLangDefault)
{
$links = [];
foreach ($languages as $lang) {
switch ($entity) {
case 'product':
$lnk = $this->context->link->getProductLink((int) $idItem, null, null, null, $lang['id_lang']);
break;
case 'category':
$lnk = $this->context->link->getCategoryLink((int) $idItem, null, $lang['id_lang']);
break;
case 'manufacturer':
if (!$idItem) {
$lnk = $this->context->link->getPageLink('manufacturer', null, $lang['id_lang']);
} else {
$lnk = $this->context->link->getManufacturerLink((int) $idItem, null, $lang['id_lang']);
}
break;
case 'supplier':
if (!$idItem) {
$lnk = $this->context->link->getPageLink('supplier', null, $lang['id_lang']);
} else {
$lnk = $this->context->link->getSupplierLink((int) $idItem, null, $lang['id_lang']);
}
break;
case 'cms':
$lnk = $this->context->link->getCMSLink((int) $idItem, null, null, $lang['id_lang']);
break;
case 'cms_category':
$lnk = $this->context->link->getCMSCategoryLink((int) $idItem, null, $lang['id_lang']);
break;
default:
$lnk = $this->context->link->getPageLink($entity, null, $lang['id_lang']);
break;
}
// append page number
if ($p = Tools::getValue('p')) {
$lnk .= "?p=$p";
}
$links[] = '<link rel="alternate" href="'.$lnk.'" hreflang="'.$lang['language_code'].'">';
if ($lang['id_lang'] == $idLangDefault) {
$links[] = '<link rel="alternate" href="'.$lnk.'" hreflang="x-default">';
}
}
return $links;
}
/**
* Get rel prev/next tags for paginated pages.
*
* @param string $entity type of object
* @param int $idItem id of he object
*
* @return string string containing the new tags
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function getRelPrevNext($entity, $idItem)
{
switch ($entity) {
case 'category':
$category = new Category((int) $idItem);
$nbProducts = $category->getProducts(null, null, null, null, null, true);
break;
case 'manufacturer':
$manufacturer = new Manufacturer($idItem);
$nbProducts = $manufacturer->getProducts($manufacturer->id, null, null, null, null, null, true);
break;
case 'supplier':
$supplier = new Supplier($idItem);
$nbProducts = $supplier->getProducts($supplier->id, null, null, null, null, null, true);
break;
default:
return '';
}
$p = Tools::getValue('p');
$n = (int) Configuration::get('PS_PRODUCTS_PER_PAGE');
$totalPages = ceil($nbProducts / $n);
$linkprev = '';
$linknext = '';
$requestPage = $this->context->link->getPaginationLink($entity, $idItem, $n, false, 1, false);
if (!$p) {
$p = 1;
}
if ($p > 1) { // we need prev
$linkprev = $this->context->link->goPage($requestPage, $p - 1);
}
if ($totalPages > 1 && $p + 1 <= $totalPages) {
$linknext = $this->context->link->goPage($requestPage, $p + 1);
}
$return = '';
if ($linkprev) {
$return .= '<link rel="prev" href="'.$linkprev.'">';
}
if ($linknext) {
$return .= '<link rel="next" href="'.$linknext.'">';
}
return $return;
}
/**
* Compiles and outputs page header section (including HTML <head>).
*
* @param bool $display If true, renders visual page header section
*
* @deprecated 2.0.0
*/
public function displayHeader($display = true)
{
Tools::displayAsDeprecated();
$this->initHeader();
$hookHeader = Hook::exec('displayHeader');
if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache')) {
// CSS compressor management
if (Configuration::get('PS_CSS_THEME_CACHE')) {
$this->css_files = Media::cccCss($this->css_files);
}
//JS compressor management
if (Configuration::get('PS_JS_THEME_CACHE')) {
$this->js_files = Media::cccJs($this->js_files);
}
}
// Call hook before assign of css_files and js_files in order to include correctly all css and javascript files
$this->context->smarty->assign(
[
'HOOK_HEADER' => $hookHeader,
'HOOK_TOP' => Hook::exec('displayTop'),
'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''),
'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', ['cart' => $this->context->cart]) : ''),
'HOOK_FOOTER' => Hook::exec('displayFooter'),
]
);
$this->context->smarty->assign(
[
'css_files' => $this->css_files,
'js_files' => ($this->getLayout() && (bool) Configuration::get('PS_JS_DEFER')) ? [] : $this->js_files,
]
);
$this->display_header = $display;
$this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl');
}
/**
* Initializes page header variables.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function initHeader()
{
// Added powered by for builtwith.com
header('Powered-By: thirty bees');
// Hooks are voluntary out the initialize array (need those variables already assigned)
$this->context->smarty->assign(
[
'time' => time(),
'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'),
'static_token' => Tools::getToken(false),
'token' => Tools::getToken(),
'priceDisplayPrecision' => _PS_PRICE_DISPLAY_PRECISION_,
'content_only' => (int) Tools::getValue('content_only'),
]
);
$this->context->smarty->assign($this->initLogoAndFavicon());
}
/**
* Returns logo and favicon variables, depending
* on active theme type (regular or mobile).
*
* @return array
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function initLogoAndFavicon()
{
$mobileDevice = $this->context->getMobileDevice();
if ($mobileDevice && Configuration::get('PS_LOGO_MOBILE')) {
$logo = $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO_MOBILE').'?'.Configuration::get('PS_IMG_UPDATE_TIME'));
} else {
$logo = $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO'));
}
return [
'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'),
'logo_image_width' => ($mobileDevice == false ? Configuration::get('SHOP_LOGO_WIDTH') : Configuration::get('SHOP_LOGO_MOBILE_WIDTH')),
'logo_image_height' => ($mobileDevice == false ? Configuration::get('SHOP_LOGO_HEIGHT') : Configuration::get('SHOP_LOGO_MOBILE_HEIGHT')),
'logo_url' => $logo,
];
}
/**
* Returns the layout corresponding to the current page by using the override system
* Ex:
* On the url: http://localhost/index.php?id_product=1&controller=product, this method will
* check if the layout exists in the following files (in that order), and return the first found:
* - /themes/default/override/layout-product-1.tpl
* - /themes/default/override/layout-product.tpl
* - /themes/default/layout.tpl.
*
* @return bool|string
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function getLayout()
{
$entity = $this->php_self;
$idItem = (int) Tools::getValue('id_'.$entity);
$layoutDir = $this->getThemeDir();
$layoutOverrideDir = $this->getOverrideThemeDir();
$layout = false;
if ($entity) {
if ($idItem > 0 && file_exists($layoutOverrideDir.'layout-'.$entity.'-'.$idItem.'.tpl')) {
$layout = $layoutOverrideDir.'layout-'.$entity.'-'.$idItem.'.tpl';
} elseif (file_exists($layoutOverrideDir.'layout-'.$entity.'.tpl')) {
$layout = $layoutOverrideDir.'layout-'.$entity.'.tpl';
}
}
if (!$layout && file_exists($layoutDir.'layout.tpl')) {
$layout = $layoutDir.'layout.tpl';
}
return $layout;
}
/**
* Returns theme directory (regular or mobile).
*
* @return string
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function getThemeDir()
{
return $this->useMobileTheme() ? _PS_THEME_MOBILE_DIR_ : _PS_THEME_DIR_;
}
/**
* Returns theme override directory (regular or mobile).
*
* @return string
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function getOverrideThemeDir()
{
return $this->useMobileTheme() ? _PS_THEME_MOBILE_OVERRIDE_DIR_ : _PS_THEME_OVERRIDE_DIR_;
}
/**
* Renders controller templates and generates page content.
*
* @param array|string $content Template file(s) to be rendered
*
* @throws Exception
* @throws SmartyException
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function smartyOutputContent($content)
{
if (!Configuration::get('TB_CACHE_ENABLED') || !Configuration::get('TB_PAGE_CACHE_ENABLED')) {
parent::smartyOutputContent($content);
return;
}
$html = '';
$jsTag = 'js_def';
$this->context->smarty->assign($jsTag, $jsTag);
if (is_array($content)) {
foreach ($content as $tpl) {
$html .= $this->context->smarty->fetch($tpl);
}
} else {
$html = $this->context->smarty->fetch($content);
}
$html = trim($html);
if (in_array($this->controller_type, ['front', 'modulefront']) && !empty($html) && $this->getLayout()) {
$liveEditContent = '';
$domAvailable = extension_loaded('dom') ? true : false;
$defer = (bool) Configuration::get('PS_JS_DEFER');
if ($defer && $domAvailable) {
$html = Media::deferInlineScripts($html);
}
$html = trim(str_replace(['</body>', '</html>'], '', $html))."\n";
$this->context->smarty->assign([$jsTag => Media::getJsDef(), 'js_files' => $defer ? array_unique($this->js_files) : [], 'js_inline' => ($defer && $domAvailable) ? Media::getInlineScript() : []]);
$javascript = $this->context->smarty->fetch(_PS_ALL_THEMES_DIR_.'javascript.tpl');
// $template = ($defer ? $html.$javascript : preg_replace('/(?<!\$)'.$js_tag.'/', $javascript, $html)).$live_edit_content.((!Tools::getIsset($this->ajax) || ! $this->ajax) ? '</body></html>' : '');
if ($defer && (!Tools::getIsset($this->ajax) || !$this->ajax)) {
$templ = $html.$javascript;
} else {
$templ = preg_replace('/(?<!\$)'.$jsTag.'/', $javascript, $html);
}
$templ .= $liveEditContent.((!Tools::getIsset($this->ajax) || !$this->ajax) ? '</body></html>' : '');
// $templ = ($defer ? $html . $javascript : str_replace($js_tag, $javascript, $html)) . $live_edit_content . ((!Tools::getIsset($this->ajax) || !$this->ajax) ? '</body></html>' : '');
} else {
$templ = $html;
}
//merge two arrays 1- static params to be removed and 2 - dynamic ones from the config.
$paramsToIgnore = ['refresh_cache', 'no_cache'];
$paramsToIgnoreSaved = Configuration::get('TB_PAGE_CACHE_IGNOREPARAMS');
if ($paramsToIgnoreSaved) {
$paramsToIgnoreSaved = explode(',', $paramsToIgnoreSaved);
}
if (is_array($paramsToIgnoreSaved)) {
$paramsToIgnore = array_merge($paramsToIgnore, $paramsToIgnoreSaved);
}
$url = explode('?', $_SERVER['REQUEST_URI']);
$uri = $url[0];
$queryString = isset($url[1]) ? $url[1] : '';
parse_str($queryString, $queryStringParams);
foreach ($paramsToIgnore as $param) {
if (isset($queryStringParams[$param])) {
unset($queryStringParams[$param]);
}
}
$protocol = Configuration::get('PS_SSL_ENABLED') ? 'https://' : 'http://';
$newQueryString = http_build_query($queryStringParams);
if ($queryString == '') {
$newUrl = $protocol.$_SERVER['HTTP_HOST'].$uri;
} else {
$newUrl = $protocol.$_SERVER['HTTP_HOST'].$uri.'?'.$newQueryString;
}
$ajaxCalling = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && mb_strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
if (!Tools::getValue('no_cache') && !$ajaxCalling) {
$entityType = Dispatcher::getInstance()->getController();
$cachedControllers = json_decode(Configuration::get('TB_PAGE_CACHE_CONTROLLERS'));
if (in_array($entityType, $cachedControllers) && !Tools::isSubmit('live_edit') && !Tools::isSubmit('live_configurator_token')) {
$idPage = Tools::encrypt($newUrl);
$idCurrency = (int) $this->context->currency->id;
$idLang = (int) $this->context->language->id;
$idCountry = (int) $this->context->country->id;
$idShop = (int) $this->context->shop->id;
$pageKey = Tools::encrypt('pagecache_public_'.$idPage.$idCurrency.$idLang.$idCountry.$idShop);
$idEntity = (int) Tools::getValue('id_'.$entityType);
$cache = Cache::getInstance();
$cache->set($pageKey, $templ);
PageCache::cacheKey($pageKey, $idCurrency, $idLang, $idCountry, $idShop, $entityType, $idEntity);
}
}
echo $templ;
}
/**
* Compiles and outputs page footer section.
*
* @param bool $display
*
* @deprecated 2.0.0
*/
public function displayFooter($display = true)
{
Tools::displayAsDeprecated();
$this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl');
}
/**
* Renders and outputs maintenance page and ends controller process.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function initCursedPage()
{
$this->displayMaintenancePage();
}
/**
* Displays maintenance page if shop is closed.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function displayMaintenancePage()
{
if ($this->maintenance == true || !(int) Configuration::get('PS_SHOP_ENABLE')) {
$this->maintenance = true;
if (!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP')))) {
header('HTTP/1.1 503 temporarily overloaded');
$this->context->smarty->assign($this->initLogoAndFavicon());
$this->context->smarty->assign(
[
'HOOK_MAINTENANCE' => Hook::exec('displayMaintenance', []),
]
);
// If the controller is a module, then getTemplatePath will try to find the template in the modules, so we need to instanciate a real frontcontroller
$frontController = preg_match('/ModuleFrontController$/', get_class($this)) ? new FrontController() : $this;
$this->smartyOutputContent($frontController->getTemplatePath($this->getThemeDir().'maintenance.tpl'));
exit;
}
}
}
/**
* Returns template path.
*
* @param string $template
*
* @return string
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function getTemplatePath($template)
{
if (!$this->useMobileTheme()) {
return $template;
}
$tplFile = basename($template);
$dirname = dirname($template).(substr(dirname($template), -1, 1) == '/' ? '' : '/');
if ($dirname == _PS_THEME_DIR_) {
if (file_exists(_PS_THEME_MOBILE_DIR_.$tplFile)) {
$template = _PS_THEME_MOBILE_DIR_.$tplFile;
}
} elseif ($dirname == _PS_THEME_MOBILE_DIR_) {
if (!file_exists(_PS_THEME_MOBILE_DIR_.$tplFile) && file_exists(_PS_THEME_DIR_.$tplFile)) {
$template = _PS_THEME_DIR_.$tplFile;
}
}
return $template;
}
/**
* Compiles and outputs full page content.
*
* @return bool
*
* @throws Exception
* @throws SmartyException
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function display()
{
Tools::safePostVars();
// assign css_files and js_files at the very last time
if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache')) {
// CSS compressor management
if (Configuration::get('PS_CSS_THEME_CACHE')) {
$this->css_files = Media::cccCss($this->css_files);
}
//JS compressor management
if (Configuration::get('PS_JS_THEME_CACHE') && !$this->useMobileTheme()) {
$this->js_files = Media::cccJs($this->js_files);
}
}
$this->context->smarty->assign(
[
'css_files' => $this->css_files,
'js_files' => ($this->getLayout() && (bool) Configuration::get('PS_JS_DEFER')) ? [] : $this->js_files,
'js_defer' => (bool) Configuration::get('PS_JS_DEFER'),
'errors' => $this->errors,
'display_header' => $this->display_header,
'display_footer' => $this->display_footer,
'img_formats' => ['webp' => 'image/webp', 'jpg' => 'image/jpeg']
]
);
$layout = $this->getLayout();
if ($layout) {
if ($this->template) {
$template = $this->context->smarty->fetch($this->template);
} else {
// For retrocompatibility with 1.4 controller
ob_start();
$this->displayContent();
$template = ob_get_contents();
ob_clean();
}
$this->context->smarty->assign('template', $template);
$this->smartyOutputContent($layout);
} else {
Tools::displayAsDeprecated('layout.tpl is missing in your theme directory');
if ($this->display_header) {
$this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl');
}
if ($this->template) {
$this->smartyOutputContent($this->template);
} else { // For retrocompatibility with 1.4 controller
$this->displayContent();
}
if ($this->display_footer) {
$this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl');
}
}
return true;
}
/**
* Renders page content.
* Used for retrocompatibility with PS 1.4.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function displayContent()
{
}
/**
* Sets controller CSS and JS files.
*
* @return bool
*/
public function setMedia()
{
/*
* If website is accessed by mobile device
* @see FrontControllerCore::setMobileMedia()
*/
if ($this->useMobileTheme()) {
$this->setMobileMedia();
return true;
}
$this->addCSS(_THEME_CSS_DIR_.'grid_prestashop.css', 'all'); // retro compat themes 1.5.0.1
$this->addCSS(_THEME_CSS_DIR_.'global.css', 'all');
$this->addJquery();
$this->addJqueryPlugin('easing');
$this->addJS(_PS_JS_DIR_.'tools.js');
$this->addJS(_THEME_JS_DIR_.'global.js');
// @since 1.0.2
Media::addJsDef(['currencyModes' => Currency::getModes()]);
// @since 1.0.4
Media::addJsDef([
'useLazyLoad' => (bool) Configuration::get('TB_LAZY_LOAD'),
'useWebp' => (bool) Configuration::get('TB_USE_WEBP') && function_exists('imagewebp'),
]);
// Automatically add js files from js/autoload directory in the template
if (@filemtime($this->getThemeDir().'js/autoload/')) {
foreach (scandir($this->getThemeDir().'js/autoload/', 0) as $file) {
if (preg_match('/^[^.].*\.js$/', $file)) {
$this->addJS($this->getThemeDir().'js/autoload/'.$file);
}
}
}
// Automatically add css files from css/autoload directory in the template
if (@filemtime($this->getThemeDir().'css/autoload/')) {
foreach (scandir($this->getThemeDir().'css/autoload', 0) as $file) {
if (preg_match('/^[^.].*\.css$/', $file)) {
$this->addCSS($this->getThemeDir().'css/autoload/'.$file);
}
}
}
if (Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getAdminToken('AdminModulesPositions'.(int) Tab::getIdFromClassName('AdminModulesPositions').(int) Tools::getValue('id_employee'))) {
$this->addJqueryUI('ui.sortable');
$this->addjqueryPlugin('fancybox');
$this->addJS(_PS_JS_DIR_.'hookLiveEdit.js');
}
if (Configuration::get('PS_QUICK_VIEW')) {
$this->addjqueryPlugin('fancybox');
}
if (Configuration::get('PS_COMPARATOR_MAX_ITEM') > 0) {
$this->addJS(_THEME_JS_DIR_.'products-comparison.js');
}
// Execute Hook FrontController SetMedia
Hook::exec('actionFrontControllerSetMedia', []);
return true;
}
/**
* Specific medias for mobile device.
* If autoload directory is present in the mobile theme, these files will not be loaded.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function setMobileMedia()
{
$this->addJquery();
if (!file_exists($this->getThemeDir().'js/autoload/')) {
$this->addJS(_THEME_MOBILE_JS_DIR_.'jquery.mobile-1.3.0.min.js');
$this->addJS(_THEME_MOBILE_JS_DIR_.'jqm-docs.js');
$this->addJS(_PS_JS_DIR_.'tools.js');
$this->addJS(_THEME_MOBILE_JS_DIR_.'global.js');
$this->addJqueryPlugin('fancybox');
}
if (!file_exists($this->getThemeDir().'css/autoload/')) {
$this->addCSS(_THEME_MOBILE_CSS_DIR_.'jquery.mobile-1.3.0.min.css', 'all');
$this->addCSS(_THEME_MOBILE_CSS_DIR_.'jqm-docs.css', 'all');
$this->addCSS(_THEME_MOBILE_CSS_DIR_.'global.css', 'all');
}
}
/**
* Add one or several JS files for front, checking if js files are overridden in theme/js/modules/ directory.
*
* @see Controller::addJS()
*
* @param array|string $jsUri Path to file, or an array of paths
* @param bool $checkPath If true, checks if files exists
*
* @return bool
*/
public function addJS($jsUri, $checkPath = true)
{
return $this->addMedia($jsUri, null, null, false, $checkPath);
}
/**
* Adds a media file(s) (CSS, JS) to page header.
*
* @param string|array $mediaUri Path to file, or an array of paths like: array(array(uri => media_type), ...)
* @param string|null $cssMediaType CSS media type
* @param int|null $offset
* @param bool $remove If True, removes media files
* @param bool $checkPath If true, checks if files exists
*
* @return bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function addMedia($mediaUri, $cssMediaType = null, $offset = null, $remove = false, $checkPath = true)
{
if (!is_array($mediaUri)) {
if ($cssMediaType) {
$mediaUri = [$mediaUri => $cssMediaType];
} else {
$mediaUri = [$mediaUri];
}
}
$listUri = [];
foreach ($mediaUri as $file => $media) {
if (!Validate::isAbsoluteUrl($media)) {
$different = 0;
$differentCss = 0;
$type = 'css';
if (!$cssMediaType) {
$type = 'js';
$file = $media;
}
if (strpos($file, __PS_BASE_URI__.'modules/') === 0) {
$overridePath = str_replace(__PS_BASE_URI__.'modules/', _PS_ROOT_DIR_.'/themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different);
if (strrpos($overridePath, $type.'/'.basename($file)) !== false) {
$overridePathCss = str_replace($type.'/'.basename($file), basename($file), $overridePath, $differentCss);
}
if ($different && @filemtime($overridePath)) {
$file = str_replace(__PS_BASE_URI__.'modules/', __PS_BASE_URI__.'themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different);
} elseif ($differentCss && isset($overridePathCss) && @filemtime($overridePathCss)) {
$file = $overridePathCss;
}
if ($cssMediaType) {
$listUri[$file] = $media;
} else {
$listUri[] = $file;
}
} else {
$listUri[$file] = $media;
}
} else {
$listUri[$file] = $media;
}
}
if ($remove) {
if ($cssMediaType) {
parent::removeCSS($listUri, $cssMediaType);
return true;
}
parent::removeJS($listUri);
return true;
}
if ($cssMediaType) {
parent::addCSS($listUri, $cssMediaType, $offset, $checkPath);
return true;
}
parent::addJS($listUri, $checkPath);
return true;
}
/**
* Add one or several CSS for front, checking if css files are overridden in theme/css/modules/ directory.
*
* @see Controller::addCSS()
*
* @param array|string $cssUri $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...)
* @param string $cssMediaType CSS media type
* @param int|null $offset
* @param bool $checkPath If true, checks if files exists
*
* @return bool
*/
public function addCSS($cssUri, $cssMediaType = 'all', $offset = null, $checkPath = true)
{
return $this->addMedia($cssUri, $cssMediaType, $offset = null, false, $checkPath);
}
/**
* Initializes page footer variables.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function initFooter()
{
$hookFooter = Hook::exec('displayFooter');
$extraJs = Configuration::get(Configuration::CUSTOMCODE_JS);
$extraJsConf = '';
if (isset($this->php_self) && $this->php_self == 'order-confirmation') {
$extraJsConf = Configuration::get(Configuration::CUSTOMCODE_ORDERCONF_JS);
}
$hookFooter .= '<script>'.$extraJs.$extraJsConf.'</script>';
$this->context->smarty->assign(
[
'HOOK_FOOTER' => $hookFooter,
'conditions' => Configuration::get(Configuration::CONDITIONS),
'id_cgv' => Configuration::get(Configuration::CONDITIONS_CMS_ID),
'PS_SHOP_NAME' => Configuration::get(Configuration::SHOP_NAME),
'PS_ALLOW_MOBILE_DEVICE' => isset($_SERVER['HTTP_USER_AGENT']) && (bool) Configuration::get('PS_ALLOW_MOBILE_DEVICE') && @filemtime(_PS_THEME_MOBILE_DIR_),
]
);
/*
* RTL support
* rtl.css overrides theme css files for RTL
* iso_code.css overrides default font for every language (optional)
*/
if ($this->context->language->is_rtl) {
$this->addCSS(_THEME_CSS_DIR_.'rtl.css');
$this->addCSS(_THEME_CSS_DIR_.$this->context->language->iso_code.'.css');
}
}
/**
* Renders Live Edit widget.
*
* @return string HTML
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function getLiveEditFooter()
{
if ($this->checkLiveEditAccess()) {
$data = $this->context->smarty->createData();
// @codingStandardsIgnoreStart
$data->assign(
[
'ad' => Tools::getValue('ad'),
'live_edit' => true,
'hook_list' => Hook::$executed_hooks,
'id_shop' => $this->context->shop->id,
]
);
// @codingStandardsIgnoreEnd
return $this->context->smarty->createTemplate(_PS_ALL_THEMES_DIR_.'live_edit.tpl', $data)->fetch();
} else {
return '';
}
}
/**
* Checks if the user can use Live Edit feature.
*
* @return bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function checkLiveEditAccess()
{
if (!Tools::isSubmit('live_edit') || !Tools::getValue('ad') || !Tools::getValue('liveToken')) {
return false;
}
if (Tools::getValue('liveToken') != Tools::getAdminToken('AdminModulesPositions'.(int) Tab::getIdFromClassName('AdminModulesPositions').(int) Tools::getValue('id_employee'))) {
return false;
}
return is_dir(_PS_CORE_DIR_.DIRECTORY_SEPARATOR.Tools::getValue('ad'));
}
/**
* Assigns product list page sorting variables.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function productSort()
{
// $this->orderBy = Tools::getProductsOrder('by', Tools::getValue('orderby'));
// $this->orderWay = Tools::getProductsOrder('way', Tools::getValue('orderway'));
// 'orderbydefault' => Tools::getProductsOrder('by'),
// 'orderwayposition' => Tools::getProductsOrder('way'), // Deprecated: orderwayposition
// 'orderwaydefault' => Tools::getProductsOrder('way'),
$stockManagement = Configuration::get('PS_STOCK_MANAGEMENT') ? true : false; // no display quantity order if stock management disabled
$orderByValues = [0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference'];
$orderWayValues = [0 => 'asc', 1 => 'desc'];
$this->orderBy = mb_strtolower(Tools::getValue('orderby', $orderByValues[(int) Configuration::get('PS_PRODUCTS_ORDER_BY')]));
$this->orderWay = mb_strtolower(Tools::getValue('orderway', $orderWayValues[(int) Configuration::get('PS_PRODUCTS_ORDER_WAY')]));
if (!in_array($this->orderBy, $orderByValues)) {
$this->orderBy = $orderByValues[0];
}
if (!in_array($this->orderWay, $orderWayValues)) {
$this->orderWay = $orderWayValues[0];
}
$this->context->smarty->assign(
[
'orderby' => $this->orderBy,
'orderway' => $this->orderWay,
'orderbydefault' => $orderByValues[(int) Configuration::get('PS_PRODUCTS_ORDER_BY')],
'orderwayposition' => $orderWayValues[(int) Configuration::get('PS_PRODUCTS_ORDER_WAY')], // Deprecated: orderwayposition
'orderwaydefault' => $orderWayValues[(int) Configuration::get('PS_PRODUCTS_ORDER_WAY')],
'stock_management' => (int) $stockManagement,
]
);
}
/**
* Assigns product list page pagination variables.
*
* @param int|null $totalProducts
*
* @throws PrestaShopException
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function pagination($totalProducts = null)
{
if (!static::$initialized) {
$this->init();
}
// Retrieve the default number of products per page and the other available selections
$defaultProductsPerPage = max(1, (int) Configuration::get('PS_PRODUCTS_PER_PAGE'));
$nArray = [$defaultProductsPerPage, $defaultProductsPerPage * 2, $defaultProductsPerPage * 5];
if ((int) Tools::getValue('n') && (int) $totalProducts > 0) {
$nArray[] = $totalProducts;
}
// Retrieve the current number of products per page (either the default, the GET parameter or the one in the cookie)
$this->n = $defaultProductsPerPage;
if (isset($this->context->cookie->nb_item_per_page) && in_array($this->context->cookie->nb_item_per_page, $nArray)) {
$this->n = (int) $this->context->cookie->nb_item_per_page;
}
if ((int) Tools::getValue('n') && in_array((int) Tools::getValue('n'), $nArray)) {
$this->n = (int) Tools::getValue('n');
}
// Retrieve the page number (either the GET parameter or the first page)
$this->p = (int) Tools::getValue('p', 1);
// If the parameter is not correct then redirect (do not merge with the previous line, the redirect is required in order to avoid duplicate content)
if (!is_numeric($this->p) || $this->p < 1) {
Tools::redirect($this->context->link->getPaginationLink(false, false, $this->n, false, 1, false));
}
// Remove the page parameter in order to get a clean URL for the pagination template
$currentUrl = preg_replace('/(?:(\?)|&amp;)p=\d+/', '$1', Tools::htmlentitiesUTF8($_SERVER['REQUEST_URI']));
if ($this->n != $defaultProductsPerPage || isset($this->context->cookie->nb_item_per_page)) {
$this->context->cookie->nb_item_per_page = $this->n;
}
$pagesNb = ceil($totalProducts / (int) $this->n);
if ($this->p > $pagesNb && $totalProducts != 0) {
Tools::redirect($this->context->link->getPaginationLink(false, false, $this->n, false, $pagesNb, false));
}
$range = 2; /* how many pages around page selected */
$start = (int) ($this->p - $range);
if ($start < 1) {
$start = 1;
}
$stop = (int) ($this->p + $range);
if ($stop > $pagesNb) {
$stop = (int) $pagesNb;
}
$this->context->smarty->assign(
[
'nb_products' => $totalProducts,
'products_per_page' => $this->n,
'pages_nb' => $pagesNb,
'p' => $this->p,
'n' => $this->n,
'nArray' => $nArray,
'range' => $range,
'start' => $start,
'stop' => $stop,
'current_url' => $currentUrl,
]
);
}
/**
* Initializes front controller: sets smarty variables,
* class properties, redirects depending on context, etc.
*
* @global bool $useSSL SSL connection flag
* @global Cookie $cookie Visitor's cookie
* @global Smarty $smarty
* @global Cart $cart Visitor's cart
* @global string $iso Language ISO
* @global Country $defaultCountry Visitor's country object
* @global string $protocol_link
* @global string $protocol_content
* @global Link $link
* @global array $css_files
* @global array $js_files
* @global Currency $currency Visitor's selected currency
*
* @throws PrestaShopException
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function init()
{
/*
* Globals are DEPRECATED as of version 1.5.0.1
* Use the Context object to access objects instead.
* Example: $this->context->cart
*/
global $useSSL, $cookie, $smarty, $cart, $iso, $defaultCountry, $protocolLink, $protocolContent, $link, $cssFiles, $jsFiles, $currency;
if (static::$initialized) {
return;
}
static::$initialized = true;
parent::init();
// If current URL use SSL, set it true (used a lot for module redirect)
if (Tools::usingSecureMode()) {
$useSSL = true;
}
// For compatibility with globals, DEPRECATED as of version 1.5.0.1
$cssFiles = $this->css_files;
$jsFiles = $this->js_files;
$this->sslRedirection();
if ($this->ajax) {
$this->display_header = false;
$this->display_footer = false;
}
// If account created with the 2 steps register process, remove 'account_created' from cookie
if (isset($this->context->cookie->account_created)) {
$this->context->smarty->assign('account_created', 1);
unset($this->context->cookie->account_created);
}
// ob_start();
// Init cookie language
// @TODO This method must be moved into switchLanguage
Tools::setCookieLanguage($this->context->cookie);
$protocolLink = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://';
$useSSL = ((isset($this->ssl) && $this->ssl && Configuration::get('PS_SSL_ENABLED')) || Tools::usingSecureMode()) ? true : false;
$protocolContent = ($useSSL) ? 'https://' : 'http://';
$link = new Link($protocolLink, $protocolContent);
$this->context->link = $link;
if ($idCart = (int) $this->recoverCart()) {
$this->context->cookie->id_cart = (int) $idCart;
}
if ($this->auth && !$this->context->customer->isLogged($this->guestAllowed)) {
Tools::redirect('index.php?controller=authentication'.($this->authRedirection ? '&back='.$this->authRedirection : ''));
}
/* Theme is missing */
if (!is_dir(_PS_THEME_DIR_)) {
throw new PrestaShopException((sprintf(Tools::displayError('Current theme unavailable "%s". Please check your theme directory name and permissions.'), basename(rtrim(_PS_THEME_DIR_, '/\\')))));
}
Configuration::set('PS_GEOLOCATION_ENABLED', 1);
if (Configuration::get('PS_GEOLOCATION_ENABLED')) {
if (($newDefault = $this->geolocationManagement($this->context->country)) && Validate::isLoadedObject($newDefault)) {
$this->context->country = $newDefault;
}
} elseif (Configuration::get('PS_DETECT_COUNTRY')) {
$hasCurrency = isset($this->context->cookie->id_currency) && (int) $this->context->cookie->id_currency;
$hasCountry = isset($this->context->cookie->iso_code_country) && $this->context->cookie->iso_code_country;
$hasAddressType = false;
if ((int) $this->context->cookie->id_cart && ($cart = new Cart($this->context->cookie->id_cart)) && Validate::isLoadedObject($cart)) {
$hasAddressType = isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')};
}
if ((!$hasCurrency || $hasCountry) && !$hasAddressType) {
$idCountry = $hasCountry && !Validate::isLanguageIsoCode($this->context->cookie->iso_code_country) ?
(int) Country::getByIso(strtoupper($this->context->cookie->iso_code_country)) : (int) Tools::getCountry();
$country = new Country($idCountry, (int) $this->context->cookie->id_lang);
if (!$hasCurrency && validate::isLoadedObject($country) && $this->context->country->id !== $country->id) {
$this->context->country = $country;
$this->context->cookie->id_currency = (int) Currency::getCurrencyInstance($country->id_currency ? (int) $country->id_currency : (int) Configuration::get('PS_CURRENCY_DEFAULT'))->id;
$this->context->cookie->iso_code_country = strtoupper($country->iso_code);
}
}
}
$currency = Tools::setCurrency($this->context->cookie);
if (isset($_GET['logout']) || ($this->context->customer->logged && Customer::isBanned($this->context->customer->id))) {
$this->context->customer->logout();
Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null);
} elseif (isset($_GET['mylogout'])) {
$this->context->customer->mylogout();
Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null);
}
/* Cart already exists */
if ((int) $this->context->cookie->id_cart) {
if (!isset($cart)) {
$cart = new Cart($this->context->cookie->id_cart);
}
if (Validate::isLoadedObject($cart) && $cart->OrderExists()) {
Logger::addLog('Frontcontroller::init - Cart cannot be loaded or an order has already been placed using this cart', 1, null, 'Cart', (int) $this->context->cookie->id_cart, true);
unset($this->context->cookie->id_cart, $cart, $this->context->cookie->checkedTOS);
$this->context->cookie->check_cgv = false;
} /* Delete product of cart, if user can't make an order from his country */
elseif (intval(Configuration::get('PS_GEOLOCATION_ENABLED')) &&
!in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) &&
$cart->nbProducts() && intval(Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR')) != -1 &&
!FrontController::isInWhitelistForGeolocation() &&
!in_array($_SERVER['SERVER_NAME'], ['localhost', '127.0.0.1'])
) {
Logger::addLog('Frontcontroller::init - GEOLOCATION is deleting a cart', 1, null, 'Cart', (int) $this->context->cookie->id_cart, true);
unset($this->context->cookie->id_cart, $cart);
} // update cart values
elseif ($this->context->cookie->id_customer != $cart->id_customer || $this->context->cookie->id_lang != $cart->id_lang || $currency->id != $cart->id_currency) {
if ($this->context->cookie->id_customer) {
$cart->id_customer = (int) $this->context->cookie->id_customer;
}
$cart->id_lang = (int) $this->context->cookie->id_lang;
$cart->id_currency = (int) $currency->id;
$cart->update();
}
/* Select an address if not set */
if (isset($cart) && $this->context->cookie->id_customer
&& (!$cart->id_address_delivery || !$cart->id_address_invoice)) {
$idFirstAddress = (int) Address::getFirstCustomerAddressId($cart->id_customer);
if ($idFirstAddress) {
$toUpdate = false;
if (!$cart->id_address_delivery) {
$toUpdate = true;
$cart->id_address_delivery = $idFirstAddress;
}
if (!$cart->id_address_invoice) {
$toUpdate = true;
$cart->id_address_invoice = $idFirstAddress;
}
if ($toUpdate) {
$cart->update();
}
}
}
}
if (!isset($cart) || !$cart->id) {
$cart = new Cart();
$cart->id_lang = (int) $this->context->cookie->id_lang;
$cart->id_currency = (int) $this->context->cookie->id_currency;
$cart->id_guest = (int) $this->context->cookie->id_guest;
$cart->id_shop_group = (int) $this->context->shop->id_shop_group;
$cart->id_shop = $this->context->shop->id;
if ($this->context->cookie->id_customer) {
$cart->id_customer = (int) $this->context->cookie->id_customer;
$cart->id_address_delivery = (int) Address::getFirstCustomerAddressId($cart->id_customer);
$cart->id_address_invoice = (int) $cart->id_address_delivery;
} else {
$cart->id_address_delivery = 0;
$cart->id_address_invoice = 0;
}
// Needed if the merchant want to give a free product to every visitors
$this->context->cart = $cart;
CartRule::autoAddToCart($this->context);
} else {
$this->context->cart = $cart;
}
/* get page name to display it in body id */
// Are we in a payment module
$moduleName = '';
if (Validate::isModuleName(Tools::getValue('module'))) {
$moduleName = Tools::getValue('module');
}
if (!empty($this->page_name)) {
$pageName = $this->page_name;
} elseif (!empty($this->php_self)) {
$pageName = $this->php_self;
} elseif (Tools::getValue('fc') == 'module' && $moduleName != '' && (Module::getInstanceByName($moduleName) instanceof PaymentModule)) {
$pageName = 'module-payment-submit';
} elseif (preg_match('#^'.preg_quote($this->context->shop->physical_uri, '#').'modules/([a-zA-Z0-9_-]+?)/(.*)$#', $_SERVER['REQUEST_URI'], $m)) {
$pageName = 'module-'.$m[1].'-'.str_replace(['.php', '/'], ['', '-'], $m[2]);
} else {
$pageName = Dispatcher::getInstance()->getController();
$pageName = (preg_match('/^[0-9]/', $pageName) ? 'page_'.$pageName : $pageName);
}
$this->context->smarty->assign(Meta::getMetaTags($this->context->language->id, $pageName));
$this->context->smarty->assign('request_uri', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI'])));
/* Breadcrumb */
$navigationPipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>');
$this->context->smarty->assign('navigationPipe', $navigationPipe);
// Automatically redirect to the canonical URL if needed
if (!empty($this->php_self) && !Tools::getValue('ajax')) {
$this->canonicalRedirection($this->context->link->getPageLink($this->php_self, $this->ssl, $this->context->language->id));
}
Product::initPricesComputation();
$displayTaxLabel = $this->context->country->display_tax_label;
if (isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) {
$infos = Address::getCountryAndState((int) $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
$country = new Country((int) $infos['id_country']);
$this->context->country = $country;
if (Validate::isLoadedObject($country)) {
$displayTaxLabel = $country->display_tax_label;
}
}
$languages = Language::getLanguages(true, $this->context->shop->id);
$metaLanguage = [];
foreach ($languages as $lang) {
$metaLanguage[] = $lang['iso_code'];
}
$comparedProducts = [];
if (Configuration::get('PS_COMPARATOR_MAX_ITEM') && isset($this->context->cookie->id_compare)) {
$comparedProducts = CompareProduct::getCompareProducts($this->context->cookie->id_compare);
}
$this->context->smarty->assign(
[
// Useful for layout.tpl
'mobile_device' => $this->context->getMobileDevice(),
'link' => $link,
'cart' => $cart,
'currency' => $currency,
'currencyRate' => (float) $currency->getConversationRate(),
'cookie' => $this->context->cookie,
'page_name' => $pageName,
'hide_left_column' => !$this->display_column_left,
'hide_right_column' => !$this->display_column_right,
'base_dir' => _PS_BASE_URL_.__PS_BASE_URI__,
'base_dir_ssl' => $protocolLink.Tools::getShopDomainSsl().__PS_BASE_URI__,
'force_ssl' => Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE'),
'content_dir' => $protocolContent.Tools::getHttpHost().__PS_BASE_URI__,
'base_uri' => $protocolContent.Tools::getHttpHost().__PS_BASE_URI__.(!Configuration::get('PS_REWRITING_SETTINGS') ? 'index.php' : ''),
'tpl_dir' => _PS_THEME_DIR_,
'tpl_uri' => _THEME_DIR_,
'modules_dir' => _MODULE_DIR_,
'mail_dir' => _MAIL_DIR_,
'lang_iso' => $this->context->language->iso_code,
'lang_id' => (int) $this->context->language->id,
'isRtl' => $this->context->language->is_rtl,
'language_code' => $this->context->language->language_code ? $this->context->language->language_code : $this->context->language->iso_code,
'come_from' => Tools::getHttpHost(true, true).Tools::htmlentitiesUTF8(str_replace(['\'', '\\'], '', urldecode($_SERVER['REQUEST_URI']))),
'cart_qties' => (int) $cart->nbProducts(),
'currencies' => Currency::getCurrencies(),
'languages' => $languages,
'meta_language' => implode(',', $metaLanguage),
'priceDisplay' => Product::getTaxCalculationMethod((int) $this->context->cookie->id_customer),
'is_logged' => (bool) $this->context->customer->isLogged(),
'is_guest' => (bool) $this->context->customer->isGuest(),
'add_prod_display' => (int) Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY'),
'shop_name' => Configuration::get('PS_SHOP_NAME'),
'roundMode' => (int) Configuration::get('PS_PRICE_ROUND_MODE'),
'use_taxes' => (int) Configuration::get('PS_TAX'),
'show_taxes' => (int) (Configuration::get('PS_TAX_DISPLAY') == 1 && (int) Configuration::get('PS_TAX')),
'display_tax_label' => (bool) $displayTaxLabel,
'vat_management' => (int) Configuration::get('VATNUMBER_MANAGEMENT'),
'opc' => (bool) Configuration::get('PS_ORDER_PROCESS_TYPE'),
'PS_CATALOG_MODE' => (bool) Configuration::get('PS_CATALOG_MODE') || (Group::isFeatureActive() && !(bool) Group::getCurrent()->show_prices),
'b2b_enable' => (bool) Configuration::get('PS_B2B_ENABLE'),
'request' => $link->getPaginationLink(false, false, false, true),
'PS_STOCK_MANAGEMENT' => Configuration::get('PS_STOCK_MANAGEMENT'),
'quick_view' => (bool) Configuration::get('PS_QUICK_VIEW'),
'shop_phone' => Configuration::get('PS_SHOP_PHONE'),
'compared_products' => is_array($comparedProducts) ? $comparedProducts : [],
'comparator_max_item' => (int) Configuration::get('PS_COMPARATOR_MAX_ITEM'),
'currencySign' => $currency->sign, // backward compat, see global.tpl
'currencyFormat' => $currency->format, // backward compat
'currencyBlank' => $currency->blank, // backward compat
'high_dpi' => (bool) Configuration::get('PS_HIGHT_DPI'),
'lazy_load' => (bool) Configuration::get('TB_LAZY_LOAD'),
'webp' => (bool) Configuration::get('TB_USE_WEBP') && function_exists('imagewebp'),
]
);
// Add the tpl files directory for mobile
if ($this->useMobileTheme()) {
$this->context->smarty->assign(
[
'tpl_mobile_uri' => _PS_THEME_MOBILE_DIR_,
]
);
}
// Deprecated
$this->context->smarty->assign(
[
'id_currency_cookie' => (int) $currency->id,
'logged' => $this->context->customer->isLogged(),
'customerName' => ($this->context->customer->logged ? $this->context->cookie->customer_firstname.' '.$this->context->cookie->customer_lastname : false),
]
);
$assignArray = [
'img_ps_dir' => _PS_IMG_,
'img_cat_dir' => _THEME_CAT_DIR_,
'img_lang_dir' => _THEME_LANG_DIR_,
'img_prod_dir' => _THEME_PROD_DIR_,
'img_manu_dir' => _THEME_MANU_DIR_,
'img_sup_dir' => _THEME_SUP_DIR_,
'img_ship_dir' => _THEME_SHIP_DIR_,
'img_store_dir' => _THEME_STORE_DIR_,
'img_col_dir' => _THEME_COL_DIR_,
'img_dir' => _THEME_IMG_DIR_,
'css_dir' => _THEME_CSS_DIR_,
'js_dir' => _THEME_JS_DIR_,
'pic_dir' => _THEME_PROD_PIC_DIR_,
];
// Add the images directory for mobile
if ($this->useMobileTheme()) {
$assignArray['img_mobile_dir'] = _THEME_MOBILE_IMG_DIR_;
}
// Add the CSS directory for mobile
if ($this->useMobileTheme()) {
$assignArray['css_mobile_dir'] = _THEME_MOBILE_CSS_DIR_;
}
foreach ($assignArray as $assignKey => $assignValue) {
if (substr($assignValue, 0, 1) == '/' || $protocolContent == 'https://') {
$this->context->smarty->assign($assignKey, $protocolContent.Tools::getMediaServer($assignValue).$assignValue);
} else {
$this->context->smarty->assign($assignKey, $assignValue);
}
}
/*
* These shortcuts are DEPRECATED as of version 1.5.0.1
* Use the Context to access objects instead.
* Example: $this->context->cart
*/
static::$cookie = $this->context->cookie;
static::$cart = $cart;
static::$smarty = $this->context->smarty;
static::$link = $link;
$defaultCountry = $this->context->country;
$this->displayMaintenancePage();
if ($this->restrictedCountry) {
$this->displayRestrictedCountryPage();
}
if (Tools::isSubmit('live_edit') && !$this->checkLiveEditAccess()) {
Tools::redirect('index.php?controller=404');
}
$this->iso = $iso;
$this->context->cart = $cart;
$this->context->currency = $currency;
}
/**
* Redirects to correct protocol if settings and request methods don't match.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function sslRedirection()
{
// If we call a SSL controller without SSL or a non SSL controller with SSL, we redirect with the right protocol
if (Configuration::get('PS_SSL_ENABLED') && (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'POST') && $this->ssl != Tools::usingSecureMode()) {
$this->context->cookie->disallowWriting();
header('HTTP/1.1 301 Moved Permanently');
header('Cache-Control: no-cache');
if ($this->ssl) {
header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']);
} else {
header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']);
}
exit();
}
}
/**
* Recovers cart information.
*
* @return int|false
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function recoverCart()
{
if (($idCart = (int) Tools::getValue('recover_cart')) && Tools::getValue('token_cart') == md5(_COOKIE_KEY_.'recover_cart_'.$idCart)) {
$cart = new Cart((int) $idCart);
if (Validate::isLoadedObject($cart)) {
$customer = new Customer((int) $cart->id_customer);
if (Validate::isLoadedObject($customer)) {
$customer->logged = 1;
$this->context->customer = $customer;
$this->context->cookie->id_customer = (int) $customer->id;
$this->context->cookie->customer_lastname = $customer->lastname;
$this->context->cookie->customer_firstname = $customer->firstname;
$this->context->cookie->logged = 1;
$this->context->cookie->check_cgv = 1;
$this->context->cookie->is_guest = $customer->isGuest();
$this->context->cookie->passwd = $customer->passwd;
$this->context->cookie->email = $customer->email;
return $idCart;
}
}
} else {
return false;
}
return false;
}
/**
* Geolocation management.
*
* @param Country $defaultCountry
*
* @return Country|false
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function geolocationManagement($defaultCountry)
{
if(isset($_SERVER["HTTP_CF_IPCOUNTRY"]))
{
return $this->context->cookie->iso_code_country = strtolower($_SERVER["HTTP_CF_IPCOUNTRY"]);
}
if (!in_array($_SERVER['SERVER_NAME'], ['localhost', '127.0.0.1'])) {
/* Check if Maxmind Database exists */
if (@filemtime(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_)) {
if (!isset($this->context->cookie->iso_code_country) || (isset($this->context->cookie->iso_code_country) && !in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))))) {
$gi = geoip_open(realpath(_PS_GEOIP_DIR_._PS_GEOIP_CITY_FILE_), GEOIP_STANDARD);
$record = geoip_record_by_addr($gi, Tools::getRemoteAddr());
if (is_object($record)) {
if (!in_array(strtoupper($record->country_code), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) && !FrontController::isInWhitelistForGeolocation()) {
if (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_) {
$this->restrictedCountry = true;
} elseif (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_) {
$this->context->smarty->assign(
[
'restricted_country_mode' => true,
'geolocation_country' => $record->country_name,
]
);
}
} else {
$hasBeenSet = !isset($this->context->cookie->iso_code_country);
$this->context->cookie->iso_code_country = strtoupper($record->country_code);
}
}
}
if (isset($this->context->cookie->iso_code_country) && $this->context->cookie->iso_code_country && !Validate::isLanguageIsoCode($this->context->cookie->iso_code_country)) {
$this->context->cookie->iso_code_country = Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'));
}
if (isset($this->context->cookie->iso_code_country) && ($idCountry = (int) Country::getByIso(strtoupper($this->context->cookie->iso_code_country)))) {
/* Update defaultCountry */
if ($defaultCountry->iso_code != $this->context->cookie->iso_code_country) {
$defaultCountry = new Country($idCountry);
}
if (isset($hasBeenSet) && $hasBeenSet) {
$this->context->cookie->id_currency = (int) ($defaultCountry->id_currency ? (int) $defaultCountry->id_currency : (int) Configuration::get('PS_CURRENCY_DEFAULT'));
}
return $defaultCountry;
} elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_ && !FrontController::isInWhitelistForGeolocation()) {
$this->restrictedCountry = true;
} elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_ && !FrontController::isInWhitelistForGeolocation()) {
$this->context->smarty->assign(
[
'restricted_country_mode' => true,
'geolocation_country' => isset($record) && isset($record->country_name) && $record->country_name ? $record->country_name : 'Undefined',
]
);
}
}
}
return false;
}
/**
* Checks if user's location is whitelisted.
*
* @staticvar bool|null $allowed
*
* @return bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected static function isInWhitelistForGeolocation()
{
static $allowed = null;
if ($allowed !== null) {
return $allowed;
}
$allowed = false;
$userIp = Tools::getRemoteAddr();
$ips = [];
// retrocompatibility
$ipsOld = explode(';', Configuration::get('PS_GEOLOCATION_WHITELIST'));
if (is_array($ipsOld) && count($ipsOld)) {
foreach ($ipsOld as $ip) {
$ips = array_merge($ips, explode("\n", $ip));
}
}
$ips = array_map('trim', $ips);
if (is_array($ips) && count($ips)) {
foreach ($ips as $ip) {
if (!empty($ip) && preg_match('/^'.$ip.'.*/', $userIp)) {
$allowed = true;
}
}
}
return $allowed;
}
/**
* Redirects to canonical URL.
*
* @param string $canonicalUrl
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function canonicalRedirection($canonicalUrl = '')
{
if (!$canonicalUrl || !Configuration::get('PS_CANONICAL_REDIRECT') || strtoupper($_SERVER['REQUEST_METHOD']) != 'GET' || Tools::getValue('live_edit')) {
return;
}
$matchUrl = rawurldecode(Tools::getCurrentUrlProtocolPrefix().$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
if (Tools::usingSecureMode()) {
// Do not redirect to the same page on HTTP
if (substr_replace($canonicalUrl, 'https', 0, 4) === $matchUrl) {
return;
}
}
if (!preg_match('/^'.Tools::pRegexp(rawurldecode($canonicalUrl), '/').'([&?].*)?$/', $matchUrl)) {
$params = [];
$urlDetails = parse_url($canonicalUrl);
if (!empty($urlDetails['query'])) {
parse_str($urlDetails['query'], $query);
foreach ($query as $key => $value) {
$params[Tools::safeOutput($key)] = Tools::safeOutput($value);
}
}
$excludedKey = ['isolang', 'id_lang', 'controller', 'fc', 'id_product', 'id_category', 'id_manufacturer', 'id_supplier', 'id_cms'];
foreach ($_GET as $key => $value) {
if (!in_array($key, $excludedKey) && Validate::isUrl($key) && Validate::isUrl($value)) {
$params[Tools::safeOutput($key)] = Tools::safeOutput($value);
}
}
$strParams = http_build_query($params, '', '&');
if (!empty($strParams)) {
$finalUrl = preg_replace('/^([^?]*)?.*$/', '$1', $canonicalUrl).'?'.$strParams;
} else {
$finalUrl = preg_replace('/^([^?]*)?.*$/', '$1', $canonicalUrl);
}
// Don't send any cookie
$this->context->cookie->disallowWriting();
if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $_SERVER['REQUEST_URI'] != __PS_BASE_URI__) {
die('[Debug] This page has moved<br />Please use the following URL instead: <a href="'.$finalUrl.'">'.$finalUrl.'</a>');
}
$redirectType = Configuration::get('PS_CANONICAL_REDIRECT') == 2 ? '301' : '302';
header('HTTP/1.0 '.$redirectType.' Moved');
header('Cache-Control: no-cache');
Tools::redirectLink($finalUrl);
}
}
/**
* Displays 'country restricted' page if user's country is not allowed.
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function displayRestrictedCountryPage()
{
header('HTTP/1.1 503 temporarily overloaded');
$this->context->smarty->assign(
[
'shop_name' => $this->context->shop->name,
'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'),
'logo_url' => $this->context->link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO')),
]
);
$this->smartyOutputContent($this->getTemplatePath($this->getThemeDir().'restricted-country.tpl'));
exit;
}
/**
* Checks if token is valid.
*
* @return bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function isTokenValid()
{
if (!Configuration::get('PS_TOKEN_ENABLE')) {
return true;
}
return strcasecmp(Tools::getToken(false), Tools::getValue('token')) == 0;
}
/**
* Removes CSS file(s) from page header.
*
* @param array|string $cssUri $media_uri Path to file, or an array of paths like: array(array(uri => media_type), ...)
* @param string $cssMediaType CSS media type
* @param bool $checkPath If true, checks if files exists
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function removeCSS($cssUri, $cssMediaType = 'all', $checkPath = true)
{
return $this->removeMedia($cssUri, $cssMediaType, $checkPath);
}
/**
* Removes media file(s) from page header.
*
* @param string|array $mediaUri Path to file, or an array paths of like: array(array(uri => media_type), ...)
* @param string|null $cssMediaType CSS media type
* @param bool $checkPath If true, checks if files exists
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function removeMedia($mediaUri, $cssMediaType = null, $checkPath = true)
{
$this->addMedia($mediaUri, $cssMediaType, null, true, $checkPath);
}
/**
* Removes JS file(s) from page header.
*
* @param array|string $jsUri Path to file, or an array of paths
* @param bool $checkPath If true, checks if files exists
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function removeJS($jsUri, $checkPath = true)
{
return $this->removeMedia($jsUri, null, $checkPath);
}
/**
* Sets template file for page content output.
*
* @param string $defaultTemplate
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function setTemplate($defaultTemplate)
{
if ($this->useMobileTheme()) {
$this->setMobileTemplate($defaultTemplate);
} else {
$template = $this->getOverrideTemplate();
if ($template) {
parent::setTemplate($template);
} else {
parent::setTemplate($defaultTemplate);
}
}
}
/**
* Checks if the template set is available for mobile themes,
* otherwise front template is chosen.
*
* @param string $template
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function setMobileTemplate($template)
{
// Needed for site map
$blockmanufacturer = Module::getInstanceByName('blockmanufacturer');
$blocksupplier = Module::getInstanceByName('blocksupplier');
$this->context->smarty->assign(
[
'categoriesTree' => Category::getRootCategory()->recurseLiteCategTree(0),
'categoriescmsTree' => CMSCategory::getRecurseCategory($this->context->language->id, 1, 1, 1),
'voucherAllowed' => (int) CartRule::isFeatureActive(),
'display_manufacturer_link' => (bool) $blockmanufacturer->active,
'display_supplier_link' => (bool) $blocksupplier->active,
'PS_DISPLAY_SUPPLIERS' => Configuration::get('PS_DISPLAY_SUPPLIERS'),
'PS_DISPLAY_BEST_SELLERS' => Configuration::get('PS_DISPLAY_BEST_SELLERS'),
'display_store' => Configuration::get('PS_STORES_DISPLAY_SITEMAP'),
'conditions' => Configuration::get('PS_CONDITIONS'),
'id_cgv' => Configuration::get('PS_CONDITIONS_CMS_ID'),
'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'),
]
);
$template = $this->getTemplatePath($template);
$assign = [];
$assign['tpl_file'] = basename($template, '.tpl');
if (isset($this->php_self)) {
$assign['controller_name'] = $this->php_self;
}
$this->context->smarty->assign($assign);
$this->template = $template;
}
/**
* Returns an overridden template path (if any) for this controller.
* If not overridden, will return false. This method can be easily overriden in a
* specific controller.
*
* @return string|bool
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function getOverrideTemplate()
{
return Hook::exec('DisplayOverrideTemplate', ['controller' => $this]);
}
/**
* Renders and adds color list HTML for each product in a list.
*
* @param array $products
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
public function addColorsToProductList(&$products)
{
if (!is_array($products) || !count($products) || !file_exists(_PS_THEME_DIR_.'product-list-colors.tpl')) {
return;
}
$productsNeedCache = [];
foreach ($products as &$product) {
if (!$this->isCached(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product']))) {
$productsNeedCache[] = (int) $product['id_product'];
}
}
unset($product);
$colors = false;
if (count($productsNeedCache)) {
$colors = Product::getAttributesColorList($productsNeedCache);
}
Tools::enableCache();
foreach ($products as &$product) {
$tpl = $this->context->smarty->createTemplate(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product']));
if (isset($colors[$product['id_product']])) {
$tpl->assign(
[
'id_product' => $product['id_product'],
'colors_list' => $colors[$product['id_product']],
'link' => $this->context->link,
'img_col_dir' => _THEME_COL_DIR_,
'col_img_dir' => _PS_COL_IMG_DIR_,
]
);
}
if (!in_array($product['id_product'], $productsNeedCache) || isset($colors[$product['id_product']])) {
$product['color_list'] = $tpl->fetch(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product']));
} else {
$product['color_list'] = '';
}
}
Tools::restoreCacheSettings();
}
/**
* Returns cache ID for product color list.
*
* @param int $idProduct
*
* @return string
*
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function getColorsListCacheId($idProduct)
{
return Product::getColorsListCacheId($idProduct);
}
/**
* Redirects to redirect_after link.
*
* @see $redirect_after
* @since 1.0.0
*
* @version 1.0.0 Initial version
*/
protected function redirect()
{
Tools::redirectLink($this->redirect_after);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment