PageRenderTime 61ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/classes/controller/FrontController.php

https://github.com/netplayer/PrestaShop
PHP | 1309 lines | 983 code | 162 blank | 164 comment | 228 complexity | 59201cf275b514bfd32f6af245f8700e MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * 2007-2014 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@prestashop.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  18. * versions in the future. If you wish to customize PrestaShop for your
  19. * needs please refer to http://www.prestashop.com for more information.
  20. *
  21. * @author PrestaShop SA <contact@prestashop.com>
  22. * @copyright 2007-2014 PrestaShop SA
  23. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  24. * International Registered Trademark & Property of PrestaShop SA
  25. */
  26. class FrontControllerCore extends Controller
  27. {
  28. public $errors = array();
  29. /**
  30. * @deprecated Deprecated shortcuts as of 1.5 - Use $context->var instead
  31. */
  32. protected static $smarty, $cookie, $link, $cart;
  33. public $iso;
  34. public $orderBy;
  35. public $orderWay;
  36. public $p;
  37. public $n;
  38. public $auth = false;
  39. public $guestAllowed = false;
  40. public $authRedirection = false;
  41. public $ssl = false;
  42. protected $restrictedCountry = false;
  43. protected $maintenance = false;
  44. public $display_column_left = true;
  45. public $display_column_right = true;
  46. public static $initialized = false;
  47. protected static $currentCustomerGroups;
  48. public $nb_items_per_page;
  49. public function __construct()
  50. {
  51. $this->controller_type = 'front';
  52. global $useSSL;
  53. parent::__construct();
  54. if (Configuration::get('PS_SSL_ENABLED') && Configuration::get('PS_SSL_ENABLED_EVERYWHERE'))
  55. $this->ssl = true;
  56. if (isset($useSSL))
  57. $this->ssl = $useSSL;
  58. else
  59. $useSSL = $this->ssl;
  60. if (isset($this->php_self) && is_object(Context::getContext()->theme))
  61. {
  62. $colums = Context::getContext()->theme->hasColumns($this->php_self);
  63. // don't use theme tables if not configurated in DB
  64. if ($colums)
  65. {
  66. $this->display_column_left = $colums['left_column'];
  67. $this->display_column_right = $colums['right_column'];
  68. }
  69. }
  70. }
  71. /**
  72. * @see Controller::checkAccess()
  73. *
  74. * @return boolean
  75. */
  76. public function checkAccess()
  77. {
  78. return true;
  79. }
  80. /**
  81. * @see Controller::viewAccess
  82. *
  83. * @return boolean
  84. */
  85. public function viewAccess()
  86. {
  87. return true;
  88. }
  89. public function init()
  90. {
  91. /*
  92. * Globals are DEPRECATED as of version 1.5.
  93. * Use the Context to access objects instead.
  94. * Example: $this->context->cart
  95. */
  96. global $useSSL, $cookie, $smarty, $cart, $iso, $defaultCountry, $protocol_link, $protocol_content, $link, $css_files, $js_files, $currency;
  97. if (self::$initialized)
  98. return;
  99. self::$initialized = true;
  100. parent::init();
  101. // If current URL use SSL, set it true (used a lot for module redirect)
  102. if (Tools::usingSecureMode())
  103. $useSSL = true;
  104. // For compatibility with globals, DEPRECATED as of version 1.5
  105. $css_files = $this->css_files;
  106. $js_files = $this->js_files;
  107. // If we call a SSL controller without SSL or a non SSL controller with SSL, we redirect with the right protocol
  108. if (Configuration::get('PS_SSL_ENABLED') && $_SERVER['REQUEST_METHOD'] != 'POST' && $this->ssl != Tools::usingSecureMode())
  109. {
  110. header('HTTP/1.1 301 Moved Permanently');
  111. header('Cache-Control: no-cache');
  112. if ($this->ssl)
  113. header('Location: '.Tools::getShopDomainSsl(true).$_SERVER['REQUEST_URI']);
  114. else
  115. header('Location: '.Tools::getShopDomain(true).$_SERVER['REQUEST_URI']);
  116. exit();
  117. }
  118. if ($this->ajax)
  119. {
  120. $this->display_header = false;
  121. $this->display_footer = false;
  122. }
  123. // if account created with the 2 steps register process, remove 'accoun_created' from cookie
  124. if (isset($this->context->cookie->account_created))
  125. {
  126. $this->context->smarty->assign('account_created', 1);
  127. unset($this->context->cookie->account_created);
  128. }
  129. ob_start();
  130. // Init cookie language
  131. // @TODO This method must be moved into switchLanguage
  132. Tools::setCookieLanguage($this->context->cookie);
  133. $protocol_link = (Configuration::get('PS_SSL_ENABLED') || Tools::usingSecureMode()) ? 'https://' : 'http://';
  134. $useSSL = ((isset($this->ssl) && $this->ssl && Configuration::get('PS_SSL_ENABLED')) || Tools::usingSecureMode()) ? true : false;
  135. $protocol_content = ($useSSL) ? 'https://' : 'http://';
  136. $link = new Link($protocol_link, $protocol_content);
  137. $this->context->link = $link;
  138. if ($id_cart = (int)$this->recoverCart())
  139. $this->context->cookie->id_cart = (int)$id_cart;
  140. if ($this->auth && !$this->context->customer->isLogged($this->guestAllowed))
  141. Tools::redirect('index.php?controller=authentication'.($this->authRedirection ? '&back='.$this->authRedirection : ''));
  142. /* Theme is missing */
  143. if (!is_dir(_PS_THEME_DIR_))
  144. throw new PrestaShopException((sprintf(Tools::displayError('Current theme unavailable "%s". Please check your theme directory name and permissions.'), basename(rtrim(_PS_THEME_DIR_, '/\\')))));
  145. if (Configuration::get('PS_GEOLOCATION_ENABLED'))
  146. if (($newDefault = $this->geolocationManagement($this->context->country)) && Validate::isLoadedObject($newDefault))
  147. $this->context->country = $newDefault;
  148. $currency = Tools::setCurrency($this->context->cookie);
  149. if (isset($_GET['logout']) || ($this->context->customer->logged && Customer::isBanned($this->context->customer->id)))
  150. {
  151. $this->context->customer->logout();
  152. Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null);
  153. }
  154. elseif (isset($_GET['mylogout']))
  155. {
  156. $this->context->customer->mylogout();
  157. Tools::redirect(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null);
  158. }
  159. /* Cart already exists */
  160. if ((int)$this->context->cookie->id_cart)
  161. {
  162. $cart = new Cart($this->context->cookie->id_cart);
  163. if ($cart->OrderExists())
  164. {
  165. unset($this->context->cookie->id_cart, $cart, $this->context->cookie->checkedTOS);
  166. $this->context->cookie->check_cgv = false;
  167. }
  168. /* Delete product of cart, if user can't make an order from his country */
  169. elseif (intval(Configuration::get('PS_GEOLOCATION_ENABLED')) &&
  170. !in_array(strtoupper($this->context->cookie->iso_code_country), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) &&
  171. $cart->nbProducts() && intval(Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR')) != -1 &&
  172. !FrontController::isInWhitelistForGeolocation() &&
  173. !in_array($_SERVER['SERVER_NAME'], array('localhost', '127.0.0.1')))
  174. unset($this->context->cookie->id_cart, $cart);
  175. // update cart values
  176. elseif ($this->context->cookie->id_customer != $cart->id_customer || $this->context->cookie->id_lang != $cart->id_lang || $currency->id != $cart->id_currency)
  177. {
  178. if ($this->context->cookie->id_customer)
  179. $cart->id_customer = (int)($this->context->cookie->id_customer);
  180. $cart->id_lang = (int)($this->context->cookie->id_lang);
  181. $cart->id_currency = (int)$currency->id;
  182. $cart->update();
  183. }
  184. /* Select an address if not set */
  185. if (isset($cart) && (!isset($cart->id_address_delivery) || $cart->id_address_delivery == 0 ||
  186. !isset($cart->id_address_invoice) || $cart->id_address_invoice == 0) && $this->context->cookie->id_customer)
  187. {
  188. $to_update = false;
  189. if (!isset($cart->id_address_delivery) || $cart->id_address_delivery == 0)
  190. {
  191. $to_update = true;
  192. $cart->id_address_delivery = (int)Address::getFirstCustomerAddressId($cart->id_customer);
  193. }
  194. if (!isset($cart->id_address_invoice) || $cart->id_address_invoice == 0)
  195. {
  196. $to_update = true;
  197. $cart->id_address_invoice = (int)Address::getFirstCustomerAddressId($cart->id_customer);
  198. }
  199. if ($to_update)
  200. $cart->update();
  201. }
  202. }
  203. if (!isset($cart) || !$cart->id)
  204. {
  205. $cart = new Cart();
  206. $cart->id_lang = (int)($this->context->cookie->id_lang);
  207. $cart->id_currency = (int)($this->context->cookie->id_currency);
  208. $cart->id_guest = (int)($this->context->cookie->id_guest);
  209. $cart->id_shop_group = (int)$this->context->shop->id_shop_group;
  210. $cart->id_shop = $this->context->shop->id;
  211. if ($this->context->cookie->id_customer)
  212. {
  213. $cart->id_customer = (int)($this->context->cookie->id_customer);
  214. $cart->id_address_delivery = (int)(Address::getFirstCustomerAddressId($cart->id_customer));
  215. $cart->id_address_invoice = $cart->id_address_delivery;
  216. }
  217. else
  218. {
  219. $cart->id_address_delivery = 0;
  220. $cart->id_address_invoice = 0;
  221. }
  222. // Needed if the merchant want to give a free product to every visitors
  223. $this->context->cart = $cart;
  224. CartRule::autoAddToCart($this->context);
  225. }
  226. else
  227. $this->context->cart = $cart;
  228. /* get page name to display it in body id */
  229. // Are we in a payment module
  230. $module_name = '';
  231. if (Validate::isModuleName(Tools::getValue('module')))
  232. $module_name = Tools::getValue('module');
  233. if (!empty($this->page_name))
  234. $page_name = $this->page_name;
  235. elseif (!empty($this->php_self))
  236. $page_name = $this->php_self;
  237. elseif (Tools::getValue('fc') == 'module' && $module_name != '' && (Module::getInstanceByName($module_name) instanceof PaymentModule))
  238. $page_name = 'module-payment-submit';
  239. // @retrocompatibility Are we in a module ?
  240. elseif (preg_match('#^'.preg_quote($this->context->shop->physical_uri, '#').'modules/([a-zA-Z0-9_-]+?)/(.*)$#', $_SERVER['REQUEST_URI'], $m))
  241. $page_name = 'module-'.$m[1].'-'.str_replace(array('.php', '/'), array('', '-'), $m[2]);
  242. else
  243. {
  244. $page_name = Dispatcher::getInstance()->getController();
  245. $page_name = (preg_match('/^[0-9]/', $page_name) ? 'page_'.$page_name : $page_name);
  246. }
  247. $this->context->smarty->assign(Meta::getMetaTags($this->context->language->id, $page_name));
  248. $this->context->smarty->assign('request_uri', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI'])));
  249. /* Breadcrumb */
  250. $navigationPipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>');
  251. $this->context->smarty->assign('navigationPipe', $navigationPipe);
  252. // Automatically redirect to the canonical URL if needed
  253. if (!empty($this->php_self) && !Tools::getValue('ajax'))
  254. $this->canonicalRedirection($this->context->link->getPageLink($this->php_self, $this->ssl, $this->context->language->id));
  255. Product::initPricesComputation();
  256. $display_tax_label = $this->context->country->display_tax_label;
  257. if (isset($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}) && $cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')})
  258. {
  259. $infos = Address::getCountryAndState((int)($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
  260. $country = new Country((int)$infos['id_country']);
  261. $this->context->country = $country;
  262. if (Validate::isLoadedObject($country))
  263. $display_tax_label = $country->display_tax_label;
  264. }
  265. $languages = Language::getLanguages(true, $this->context->shop->id);
  266. $meta_language = array();
  267. foreach ($languages as $lang)
  268. $meta_language[] = $lang['iso_code'];
  269. $compared_products = array();
  270. if (Configuration::get('PS_COMPARATOR_MAX_ITEM') && isset($this->context->cookie->id_compare))
  271. $compared_products = CompareProduct::getCompareProducts($this->context->cookie->id_compare);
  272. $this->context->smarty->assign(array(
  273. // Usefull for layout.tpl
  274. 'mobile_device' => $this->context->getMobileDevice(),
  275. 'link' => $link,
  276. 'cart' => $cart,
  277. 'currency' => $currency,
  278. 'cookie' => $this->context->cookie,
  279. 'page_name' => $page_name,
  280. 'hide_left_column' => !$this->display_column_left,
  281. 'hide_right_column' => !$this->display_column_right,
  282. 'base_dir' => _PS_BASE_URL_.__PS_BASE_URI__,
  283. 'base_dir_ssl' => $protocol_link.Tools::getShopDomainSsl().__PS_BASE_URI__,
  284. 'content_dir' => $protocol_content.Tools::getHttpHost().__PS_BASE_URI__,
  285. 'base_uri' => $protocol_content.Tools::getHttpHost().__PS_BASE_URI__.(!Configuration::get('PS_REWRITING_SETTINGS') ? 'index.php' : ''),
  286. 'tpl_dir' => _PS_THEME_DIR_,
  287. 'modules_dir' => _MODULE_DIR_,
  288. 'mail_dir' => _MAIL_DIR_,
  289. 'lang_iso' => $this->context->language->iso_code,
  290. 'come_from' => Tools::getHttpHost(true, true).Tools::htmlentitiesUTF8(str_replace(array('\'', '\\'), '', urldecode($_SERVER['REQUEST_URI']))),
  291. 'cart_qties' => (int)$cart->nbProducts(),
  292. 'currencies' => Currency::getCurrencies(),
  293. 'languages' => $languages,
  294. 'meta_language' => implode(',', $meta_language),
  295. 'priceDisplay' => Product::getTaxCalculationMethod((int)$this->context->cookie->id_customer),
  296. 'is_logged' => (bool)$this->context->customer->isLogged(),
  297. 'is_guest' => (bool)$this->context->customer->isGuest(),
  298. 'add_prod_display' => (int)Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY'),
  299. 'shop_name' => Configuration::get('PS_SHOP_NAME'),
  300. 'roundMode' => (int)Configuration::get('PS_PRICE_ROUND_MODE'),
  301. 'use_taxes' => (int)Configuration::get('PS_TAX'),
  302. 'show_taxes' => (int)(Configuration::get('PS_TAX_DISPLAY') == 1 && (int)Configuration::get('PS_TAX')),
  303. 'display_tax_label' => (bool)$display_tax_label,
  304. 'vat_management' => (int)Configuration::get('VATNUMBER_MANAGEMENT'),
  305. 'opc' => (bool)Configuration::get('PS_ORDER_PROCESS_TYPE'),
  306. 'PS_CATALOG_MODE' => (bool)Configuration::get('PS_CATALOG_MODE') || !(bool)Group::getCurrent()->show_prices,
  307. 'b2b_enable' => (bool)Configuration::get('PS_B2B_ENABLE'),
  308. 'request' => $link->getPaginationLink(false, false, false, true),
  309. 'PS_STOCK_MANAGEMENT' => Configuration::get('PS_STOCK_MANAGEMENT'),
  310. 'quick_view' => (bool)Configuration::get('PS_QUICK_VIEW'),
  311. 'shop_phone' => Configuration::get('PS_SHOP_PHONE'),
  312. 'compared_products' => is_array($compared_products) ? $compared_products : array(),
  313. 'comparator_max_item' => (int)Configuration::get('PS_COMPARATOR_MAX_ITEM')
  314. ));
  315. // Add the tpl files directory for mobile
  316. if ($this->useMobileTheme())
  317. $this->context->smarty->assign(array(
  318. 'tpl_mobile_uri' => _PS_THEME_MOBILE_DIR_,
  319. ));
  320. // Deprecated
  321. $this->context->smarty->assign(array(
  322. 'id_currency_cookie' => (int)$currency->id,
  323. 'logged' => $this->context->customer->isLogged(),
  324. 'customerName' => ($this->context->customer->logged ? $this->context->cookie->customer_firstname.' '.$this->context->cookie->customer_lastname : false)
  325. ));
  326. $assign_array = array(
  327. 'img_ps_dir' => _PS_IMG_,
  328. 'img_cat_dir' => _THEME_CAT_DIR_,
  329. 'img_lang_dir' => _THEME_LANG_DIR_,
  330. 'img_prod_dir' => _THEME_PROD_DIR_,
  331. 'img_manu_dir' => _THEME_MANU_DIR_,
  332. 'img_sup_dir' => _THEME_SUP_DIR_,
  333. 'img_ship_dir' => _THEME_SHIP_DIR_,
  334. 'img_store_dir' => _THEME_STORE_DIR_,
  335. 'img_col_dir' => _THEME_COL_DIR_,
  336. 'img_dir' => _THEME_IMG_DIR_,
  337. 'css_dir' => _THEME_CSS_DIR_,
  338. 'js_dir' => _THEME_JS_DIR_,
  339. 'pic_dir' => _THEME_PROD_PIC_DIR_
  340. );
  341. // Add the images directory for mobile
  342. if ($this->useMobileTheme())
  343. $assign_array['img_mobile_dir'] = _THEME_MOBILE_IMG_DIR_;
  344. // Add the CSS directory for mobile
  345. if ($this->useMobileTheme())
  346. $assign_array['css_mobile_dir'] = _THEME_MOBILE_CSS_DIR_;
  347. foreach ($assign_array as $assign_key => $assign_value)
  348. if (substr($assign_value, 0, 1) == '/' || $protocol_content == 'https://')
  349. $this->context->smarty->assign($assign_key, $protocol_content.Tools::getMediaServer($assign_value).$assign_value);
  350. else
  351. $this->context->smarty->assign($assign_key, $assign_value);
  352. /*
  353. * These shortcuts are DEPRECATED as of version 1.5.
  354. * Use the Context to access objects instead.
  355. * Example: $this->context->cart
  356. */
  357. self::$cookie = $this->context->cookie;
  358. self::$cart = $cart;
  359. self::$smarty = $this->context->smarty;
  360. self::$link = $link;
  361. $defaultCountry = $this->context->country;
  362. $this->displayMaintenancePage();
  363. if ($this->restrictedCountry)
  364. $this->displayRestrictedCountryPage();
  365. if (Tools::isSubmit('live_edit') && !$this->checkLiveEditAccess())
  366. Tools::redirect('index.php?controller=404');
  367. $this->iso = $iso;
  368. $this->context->cart = $cart;
  369. $this->context->currency = $currency;
  370. }
  371. public function postProcess()
  372. {
  373. }
  374. public function initContent()
  375. {
  376. $this->process();
  377. if (!isset($this->context->cart))
  378. $this->context->cart = new Cart();
  379. if (!$this->useMobileTheme())
  380. {
  381. // These hooks aren't used for the mobile theme.
  382. // Needed hooks are called in the tpl files.
  383. $this->context->smarty->assign(array(
  384. 'HOOK_HEADER' => Hook::exec('displayHeader'),
  385. 'HOOK_TOP' => Hook::exec('displayTop'),
  386. 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''),
  387. 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''),
  388. ));
  389. }
  390. else
  391. $this->context->smarty->assign('HOOK_MOBILE_HEADER', Hook::exec('displayMobileHeader'));
  392. }
  393. /**
  394. * @deprecated 1.5.0
  395. */
  396. public function displayHeader($display = true)
  397. {
  398. Tools::displayAsDeprecated();
  399. $this->initHeader();
  400. $hook_header = Hook::exec('displayHeader');
  401. if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache'))
  402. {
  403. // CSS compressor management
  404. if (Configuration::get('PS_CSS_THEME_CACHE'))
  405. $this->css_files = Media::cccCSS($this->css_files);
  406. //JS compressor management
  407. if (Configuration::get('PS_JS_THEME_CACHE'))
  408. $this->js_files = Media::cccJs($this->js_files);
  409. }
  410. // Call hook before assign of css_files and js_files in order to include correctly all css and javascript files
  411. $this->context->smarty->assign(array(
  412. 'HOOK_HEADER' => $hook_header,
  413. 'HOOK_TOP' => Hook::exec('displayTop'),
  414. 'HOOK_LEFT_COLUMN' => ($this->display_column_left ? Hook::exec('displayLeftColumn') : ''),
  415. 'HOOK_RIGHT_COLUMN' => ($this->display_column_right ? Hook::exec('displayRightColumn', array('cart' => $this->context->cart)) : ''),
  416. 'HOOK_FOOTER' => Hook::exec('displayFooter')
  417. ));
  418. $this->context->smarty->assign(array(
  419. 'css_files' => $this->css_files,
  420. 'js_files' => ($this->getLayout() && (bool)Configuration::get('PS_JS_DEFER')) ? array() : $this->js_files
  421. ));
  422. $this->display_header = $display;
  423. $this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl');
  424. }
  425. /**
  426. * @deprecated 1.5.0
  427. */
  428. public function displayFooter($display = true)
  429. {
  430. Tools::displayAsDeprecated();
  431. $this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl');
  432. }
  433. public function initCursedPage()
  434. {
  435. return $this->displayMaintenancePage();
  436. }
  437. public function process()
  438. {
  439. }
  440. public function redirect()
  441. {
  442. Tools::redirectLink($this->redirect_after);
  443. }
  444. /**
  445. * 1.4 retrocompatibility
  446. */
  447. public function displayContent()
  448. {
  449. }
  450. public function display()
  451. {
  452. Tools::safePostVars();
  453. // assign css_files and js_files at the very last time
  454. if ((Configuration::get('PS_CSS_THEME_CACHE') || Configuration::get('PS_JS_THEME_CACHE')) && is_writable(_PS_THEME_DIR_.'cache'))
  455. {
  456. // CSS compressor management
  457. if (Configuration::get('PS_CSS_THEME_CACHE'))
  458. $this->css_files = Media::cccCSS($this->css_files);
  459. //JS compressor management
  460. if (Configuration::get('PS_JS_THEME_CACHE') && !$this->useMobileTheme())
  461. $this->js_files = Media::cccJs($this->js_files);
  462. }
  463. $this->context->smarty->assign(array(
  464. 'css_files' => $this->css_files,
  465. 'js_files' => ($this->getLayout() && (bool)Configuration::get('PS_JS_DEFER')) ? array() : $this->js_files,
  466. 'js_defer' => (bool)Configuration::get('PS_JS_DEFER'),
  467. 'errors' => $this->errors,
  468. 'display_header' => $this->display_header,
  469. 'display_footer' => $this->display_footer,
  470. ));
  471. $layout = $this->getLayout();
  472. if ($layout)
  473. {
  474. if ($this->template)
  475. $template = $this->context->smarty->fetch($this->template);
  476. else // For retrocompatibility with 1.4 controller
  477. {
  478. ob_start();
  479. $this->displayContent();
  480. $template = ob_get_contents();
  481. ob_clean();
  482. }
  483. $template = $this->context->smarty->assign('template', $template);
  484. $this->smartyOutputContent($layout);
  485. }
  486. else
  487. {
  488. Tools::displayAsDeprecated('layout.tpl is missing in your theme directory');
  489. if ($this->display_header)
  490. $this->smartyOutputContent(_PS_THEME_DIR_.'header.tpl');
  491. if ($this->template)
  492. $this->smartyOutputContent($this->template);
  493. else // For retrocompatibility with 1.4 controller
  494. $this->displayContent();
  495. if ($this->display_footer)
  496. $this->smartyOutputContent(_PS_THEME_DIR_.'footer.tpl');
  497. }
  498. return true;
  499. }
  500. /* Display a maintenance page if shop is closed */
  501. protected function displayMaintenancePage()
  502. {
  503. if ($this->maintenance == true || !(int)Configuration::get('PS_SHOP_ENABLE'))
  504. {
  505. $this->maintenance = true;
  506. if (!in_array(Tools::getRemoteAddr(), explode(',', Configuration::get('PS_MAINTENANCE_IP'))))
  507. {
  508. header('HTTP/1.1 503 temporarily overloaded');
  509. $this->context->smarty->assign($this->initLogoAndFavicon());
  510. $this->context->smarty->assign(array(
  511. 'HOOK_MAINTENANCE' => Hook::exec('displayMaintenance', array()),
  512. ));
  513. $this->smartyOutputContent($this->getTemplatePath($this->getThemeDir().'maintenance.tpl'));
  514. exit;
  515. }
  516. }
  517. }
  518. /* Display a specific page if the user country is not allowed */
  519. protected function displayRestrictedCountryPage()
  520. {
  521. header('HTTP/1.1 503 temporarily overloaded');
  522. $this->context->smarty->assign(array(
  523. 'shop_name' => Context::getContext()->shop->name,
  524. 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'),
  525. 'logo_url' => self::$link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO'))
  526. ));
  527. $this->smartyOutputContent($this->getTemplatePath($this->getThemeDir().'restricted-country.tpl'));
  528. exit;
  529. }
  530. protected function canonicalRedirection($canonical_url = '')
  531. {
  532. if (!$canonical_url || !Configuration::get('PS_CANONICAL_REDIRECT') || strtoupper($_SERVER['REQUEST_METHOD']) != 'GET' || Tools::getValue('live_edit'))
  533. return;
  534. $match_url = rawurldecode(Tools::getCurrentUrlProtocolPrefix().$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
  535. if (!preg_match('/^'.Tools::pRegexp(rawurldecode($canonical_url), '/').'([&?].*)?$/', $match_url))
  536. {
  537. $params = array();
  538. $str_params = '';
  539. $url_details = parse_url($canonical_url);
  540. if (!empty($url_details['query']))
  541. {
  542. parse_str($url_details['query'], $query);
  543. foreach ($query as $key => $value)
  544. $params[Tools::safeOutput($key)] = Tools::safeOutput($value);
  545. }
  546. $excluded_key = array('isolang', 'id_lang', 'controller', 'fc', 'id_product', 'id_category', 'id_manufacturer', 'id_supplier', 'id_cms');
  547. foreach ($_GET as $key => $value)
  548. if (!in_array($key, $excluded_key) && Validate::isUrl($key) && Validate::isUrl($value))
  549. $params[Tools::safeOutput($key)] = Tools::safeOutput($value);
  550. $str_params = http_build_query($params, '', '&');
  551. if (!empty($str_params))
  552. $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url).'?'.$str_params;
  553. else
  554. $final_url = preg_replace('/^([^?]*)?.*$/', '$1', $canonical_url);
  555. // Don't send any cookie
  556. Context::getContext()->cookie->disallowWriting();
  557. if (defined('_PS_MODE_DEV_') && _PS_MODE_DEV_ && $_SERVER['REQUEST_URI'] != __PS_BASE_URI__)
  558. die('[Debug] This page has moved<br />Please use the following URL instead: <a href="'.$final_url.'">'.$final_url.'</a>');
  559. $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT') == 2 ? '301' : '302';
  560. header('HTTP/1.0 '.$redirect_type.' Moved');
  561. header('Cache-Control: no-cache');
  562. Tools::redirectLink($final_url);
  563. }
  564. }
  565. protected function geolocationManagement($default_country)
  566. {
  567. if (!in_array($_SERVER['SERVER_NAME'], array('localhost', '127.0.0.1')))
  568. {
  569. /* Check if Maxmind Database exists */
  570. if (file_exists(_PS_GEOIP_DIR_.'GeoLiteCity.dat'))
  571. {
  572. 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')))))
  573. {
  574. include_once(_PS_GEOIP_DIR_.'geoipcity.inc');
  575. $gi = geoip_open(realpath(_PS_GEOIP_DIR_.'GeoLiteCity.dat'), GEOIP_STANDARD);
  576. $record = geoip_record_by_addr($gi, Tools::getRemoteAddr());
  577. if (is_object($record))
  578. {
  579. if (!in_array(strtoupper($record->country_code), explode(';', Configuration::get('PS_ALLOWED_COUNTRIES'))) && !FrontController::isInWhitelistForGeolocation())
  580. {
  581. if (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_)
  582. $this->restrictedCountry = true;
  583. elseif (Configuration::get('PS_GEOLOCATION_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_)
  584. $this->context->smarty->assign(array(
  585. 'restricted_country_mode' => true,
  586. 'geolocation_country' => $record->country_name
  587. ));
  588. }
  589. else
  590. {
  591. $has_been_set = !isset($this->context->cookie->iso_code_country);
  592. $this->context->cookie->iso_code_country = strtoupper($record->country_code);
  593. }
  594. }
  595. }
  596. if (isset($this->context->cookie->iso_code_country) && $this->context->cookie->iso_code_country && !Validate::isLanguageIsoCode($this->context->cookie->iso_code_country))
  597. $this->context->cookie->iso_code_country = Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'));
  598. if (isset($this->context->cookie->iso_code_country) && ($id_country = Country::getByIso(strtoupper($this->context->cookie->iso_code_country))))
  599. {
  600. /* Update defaultCountry */
  601. if ($default_country->iso_code != $this->context->cookie->iso_code_country)
  602. $default_country = new Country($id_country);
  603. if (isset($has_been_set) && $has_been_set)
  604. $this->context->cookie->id_currency = (int)(Currency::getCurrencyInstance($default_country->id_currency ? (int)$default_country->id_currency : Configuration::get('PS_CURRENCY_DEFAULT'))->id);
  605. return $default_country;
  606. }
  607. elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_CATALOG_ && !FrontController::isInWhitelistForGeolocation())
  608. $this->restrictedCountry = true;
  609. elseif (Configuration::get('PS_GEOLOCATION_NA_BEHAVIOR') == _PS_GEOLOCATION_NO_ORDER_ && !FrontController::isInWhitelistForGeolocation())
  610. $this->context->smarty->assign(array(
  611. 'restricted_country_mode' => true,
  612. 'geolocation_country' => 'Undefined'
  613. ));
  614. }
  615. /* If not exists we disabled the geolocation feature */
  616. else
  617. Configuration::updateValue('PS_GEOLOCATION_ENABLED', 0);
  618. }
  619. return false;
  620. }
  621. /**
  622. * Specific medias for mobile device.
  623. * if autoload directory is present in the mobile theme, these files will not be loaded
  624. */
  625. public function setMobileMedia()
  626. {
  627. $this->addjquery();
  628. if (!file_exists($this->getThemeDir().'js/autoload/'))
  629. {
  630. $this->addJS(_THEME_MOBILE_JS_DIR_.'jquery.mobile-1.3.0.min.js');
  631. $this->addJS(_THEME_MOBILE_JS_DIR_.'jqm-docs.js');
  632. $this->addJS(_PS_JS_DIR_.'tools.js');
  633. $this->addJS(_THEME_MOBILE_JS_DIR_.'global.js');
  634. $this->addjqueryPlugin('fancybox');
  635. }
  636. if (!file_exists($this->getThemeDir().'css/autoload/'))
  637. {
  638. $this->addCSS(_THEME_MOBILE_CSS_DIR_.'jquery.mobile-1.3.0.min.css', 'all');
  639. $this->addCSS(_THEME_MOBILE_CSS_DIR_.'jqm-docs.css', 'all');
  640. $this->addCSS(_THEME_MOBILE_CSS_DIR_.'global.css', 'all');
  641. }
  642. }
  643. public function setMedia()
  644. {
  645. // if website is accessed by mobile device
  646. // @see FrontControllerCore::setMobileMedia()
  647. if ($this->useMobileTheme())
  648. {
  649. $this->setMobileMedia();
  650. return true;
  651. }
  652. $this->addCSS(_THEME_CSS_DIR_.'grid_prestashop.css', 'all'); // retro compat themes 1.5
  653. $this->addCSS(_THEME_CSS_DIR_.'global.css', 'all');
  654. $this->addjquery();
  655. $this->addjqueryPlugin('easing');
  656. $this->addJS(_PS_JS_DIR_.'tools.js');
  657. $this->addJS(_THEME_JS_DIR_.'global.js');
  658. // Automatically add js files from js/autoload directory in the template
  659. if (@filemtime($this->getThemeDir().'js/autoload/'))
  660. foreach (scandir($this->getThemeDir().'js/autoload/', 0) as $file)
  661. if (preg_match('/^[^.].*\.js$/', $file))
  662. $this->addJS($this->getThemeDir().'js/autoload/'.$file);
  663. // Automatically add css files from css/autoload directory in the template
  664. if (@filemtime($this->getThemeDir().'css/autoload/'))
  665. foreach (scandir($this->getThemeDir().'css/autoload', 0) as $file)
  666. if (preg_match('/^[^.].*\.css$/', $file))
  667. $this->addCSS($this->getThemeDir().'css/autoload/'.$file);
  668. if (Tools::isSubmit('live_edit') && Tools::getValue('ad') && Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
  669. {
  670. $this->addJqueryUI('ui.sortable');
  671. $this->addjqueryPlugin('fancybox');
  672. $this->addJS(_PS_JS_DIR_.'hookLiveEdit.js');
  673. }
  674. if (Configuration::get('PS_QUICK_VIEW'))
  675. $this->addjqueryPlugin('fancybox');
  676. if (Configuration::get('PS_COMPARATOR_MAX_ITEM') > 0)
  677. $this->addJS(_THEME_JS_DIR_.'products-comparison.js');
  678. // Execute Hook FrontController SetMedia
  679. Hook::exec('actionFrontControllerSetMedia', array());
  680. }
  681. public function initHeader()
  682. {
  683. // P3P Policies (http://www.w3.org/TR/2002/REC-P3P-20020416/#compact_policies)
  684. header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
  685. /* Hooks are volontary out the initialize array (need those variables already assigned) */
  686. $this->context->smarty->assign(array(
  687. 'time' => time(),
  688. 'img_update_time' => Configuration::get('PS_IMG_UPDATE_TIME'),
  689. 'static_token' => Tools::getToken(false),
  690. 'token' => Tools::getToken(),
  691. 'priceDisplayPrecision' => _PS_PRICE_DISPLAY_PRECISION_,
  692. 'content_only' => (int)Tools::getValue('content_only'),
  693. ));
  694. $this->context->smarty->assign($this->initLogoAndFavicon());
  695. }
  696. public function initFooter()
  697. {
  698. $this->context->smarty->assign(array(
  699. 'HOOK_FOOTER' => Hook::exec('displayFooter'),
  700. 'conditions' => Configuration::get('PS_CONDITIONS'),
  701. 'id_cgv' => Configuration::get('PS_CONDITIONS_CMS_ID'),
  702. 'PS_SHOP_NAME' => Configuration::get('PS_SHOP_NAME'),
  703. 'PS_ALLOW_MOBILE_DEVICE' => isset($_SERVER['HTTP_USER_AGENT']) && (bool)Configuration::get('PS_ALLOW_MOBILE_DEVICE') && @filemtime(_PS_THEME_MOBILE_DIR_)
  704. ));
  705. //RTL support
  706. //rtl.css overrides theme css files for rtl
  707. //iso_code.css overrides default font for every language (optional)
  708. if ($this->context->language->is_rtl)
  709. {
  710. $this->addCSS(_THEME_CSS_DIR_.'rtl.css');
  711. $this->addCSS(_THEME_CSS_DIR_.$this->context->language->iso_code.'.css');
  712. }
  713. }
  714. public function checkLiveEditAccess()
  715. {
  716. if (!Tools::isSubmit('live_edit') || !Tools::getValue('ad') || !Tools::getValue('liveToken'))
  717. return false;
  718. if (Tools::getValue('liveToken') != Tools::getAdminToken('AdminModulesPositions'.(int)Tab::getIdFromClassName('AdminModulesPositions').(int)Tools::getValue('id_employee')))
  719. return false;
  720. return is_dir(_PS_CORE_DIR_.DIRECTORY_SEPARATOR.Tools::getValue('ad'));
  721. }
  722. public function getLiveEditFooter()
  723. {
  724. if ($this->checkLiveEditAccess())
  725. {
  726. $data = $this->context->smarty->createData();
  727. $data->assign(array(
  728. 'ad' => Tools::getValue('ad'),
  729. 'live_edit' => true,
  730. 'hook_list' => Hook::$executed_hooks,
  731. 'id_shop' => $this->context->shop->id
  732. ));
  733. return $this->context->smarty->createTemplate(_PS_ALL_THEMES_DIR_.'live_edit.tpl', $data)->fetch();
  734. }
  735. else
  736. return '';
  737. }
  738. public function productSort()
  739. {
  740. // $this->orderBy = Tools::getProductsOrder('by', Tools::getValue('orderby'));
  741. // $this->orderWay = Tools::getProductsOrder('way', Tools::getValue('orderway'));
  742. // 'orderbydefault' => Tools::getProductsOrder('by'),
  743. // 'orderwayposition' => Tools::getProductsOrder('way'), // Deprecated: orderwayposition
  744. // 'orderwaydefault' => Tools::getProductsOrder('way'),
  745. $stock_management = Configuration::get('PS_STOCK_MANAGEMENT') ? true : false; // no display quantity order if stock management disabled
  746. $order_by_values = array(0 => 'name', 1 => 'price', 2 => 'date_add', 3 => 'date_upd', 4 => 'position', 5 => 'manufacturer_name', 6 => 'quantity', 7 => 'reference');
  747. $order_way_values = array(0 => 'asc', 1 => 'desc');
  748. $this->orderBy = Tools::strtolower(Tools::getValue('orderby', $order_by_values[(int)Configuration::get('PS_PRODUCTS_ORDER_BY')]));
  749. $this->orderWay = Tools::strtolower(Tools::getValue('orderway', $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')]));
  750. if (!in_array($this->orderBy, $order_by_values))
  751. $this->orderBy = $order_by_values[0];
  752. if (!in_array($this->orderWay, $order_way_values))
  753. $this->orderWay = $order_way_values[0];
  754. $this->context->smarty->assign(array(
  755. 'orderby' => $this->orderBy,
  756. 'orderway' => $this->orderWay,
  757. 'orderbydefault' => $order_by_values[(int)Configuration::get('PS_PRODUCTS_ORDER_BY')],
  758. 'orderwayposition' => $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')], // Deprecated: orderwayposition
  759. 'orderwaydefault' => $order_way_values[(int)Configuration::get('PS_PRODUCTS_ORDER_WAY')],
  760. 'stock_management' => (int)$stock_management));
  761. }
  762. public function pagination($total_products = null)
  763. {
  764. if (!self::$initialized)
  765. $this->init();
  766. elseif (!$this->context)
  767. $this->context = Context::getContext();
  768. // Retrieve the default number of products per page and the other available selections
  769. $default_products_per_page = max(1, (int)Configuration::get('PS_PRODUCTS_PER_PAGE'));
  770. $nArray = array($default_products_per_page, $default_products_per_page * 2, $default_products_per_page * 5);
  771. if ((int)Tools::getValue('n') && (int)$total_products > 0)
  772. $nArray[] = $total_products;
  773. // Retrieve the current number of products per page (either the default, the GET parameter or the one in the cookie)
  774. $this->n = $default_products_per_page;
  775. if ((int)Tools::getValue('n') && in_array((int)Tools::getValue('n'), $nArray))
  776. {
  777. $this->n = (int)Tools::getValue('n');
  778. if (isset($this->context->cookie->nb_item_per_page) && in_array($this->context->cookie->nb_item_per_page, $nArray))
  779. $this->n = (int)$this->context->cookie->nb_item_per_page;
  780. }
  781. // Retrieve the page number (either the GET parameter or the first page)
  782. $this->p = (int)Tools::getValue('p', 1);
  783. // 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)
  784. if (!is_numeric($this->p) || $this->p < 1)
  785. Tools::redirect(self::$link->getPaginationLink(false, false, $this->n, false, 1, false));
  786. // Remove the page parameter in order to get a clean URL for the pagination template
  787. $current_url = preg_replace('/(\?)?(&amp;)?p=\d+/', '$1', Tools::htmlentitiesUTF8($_SERVER['REQUEST_URI']));
  788. if ($this->n != $default_products_per_page)
  789. $this->context->cookie->nb_item_per_page = $this->n;
  790. $pages_nb = ceil($total_products / (int)$this->n);
  791. if ($this->p > $pages_nb && $total_products != 0)
  792. Tools::redirect(self::$link->getPaginationLink(false, false, $this->n, false, $pages_nb, false));
  793. $range = 2; /* how many pages around page selected */
  794. $start = (int)($this->p - $range);
  795. if ($start < 1)
  796. $start = 1;
  797. $stop = (int)($this->p + $range);
  798. if ($stop > $pages_nb)
  799. $stop = (int)$pages_nb;
  800. $this->context->smarty->assign(array(
  801. 'nb_products' => $total_products,
  802. 'products_per_page' => $this->n,
  803. 'pages_nb' => $pages_nb,
  804. 'p' => $this->p,
  805. 'n' => $this->n,
  806. 'nArray' => $nArray,
  807. 'range' => $range,
  808. 'start' => $start,
  809. 'stop' => $stop,
  810. 'current_url' => $current_url
  811. ));
  812. }
  813. public static function getCurrentCustomerGroups()
  814. {
  815. if (!Group::isFeatureActive())
  816. return array();
  817. $context = Context::getContext();
  818. if (!isset($context->customer) || !$context->customer->id)
  819. return array();
  820. if (!is_array(self::$currentCustomerGroups))
  821. {
  822. self::$currentCustomerGroups = array();
  823. $result = Db::getInstance()->executeS('SELECT id_group FROM '._DB_PREFIX_.'customer_group WHERE id_customer = '.(int)$context->customer->id);
  824. foreach ($result as $row)
  825. self::$currentCustomerGroups[] = $row['id_group'];
  826. }
  827. return self::$currentCustomerGroups;
  828. }
  829. protected static function isInWhitelistForGeolocation()
  830. {
  831. $allowed = false;
  832. $user_ip = Tools::getRemoteAddr();
  833. $ips = array();
  834. // retrocompatibility
  835. $ips_old = explode(';', Configuration::get('PS_GEOLOCATION_WHITELIST'));
  836. if (is_array($ips_old) && count($ips_old))
  837. foreach ($ips_old as $ip)
  838. $ips = array_merge($ips, explode("\n", $ip));
  839. $ips = array_map('trim', $ips);
  840. if (is_array($ips) && count($ips))
  841. foreach ($ips as $ip)
  842. if (!empty($ip) && preg_match('/^'.$ip.'.*/', $user_ip))
  843. $allowed = true;
  844. return $allowed;
  845. }
  846. /**
  847. * Check if token is valid
  848. *
  849. * @since 1.5.0
  850. * @return bool
  851. */
  852. public function isTokenValid()
  853. {
  854. if (!Configuration::get('PS_TOKEN_ENABLE'))
  855. return true;
  856. return (strcasecmp(Tools::getToken(false), Tools::getValue('token')) == 0);
  857. }
  858. public function addMedia($media_uri, $css_media_type = null, $offset = null, $remove = false)
  859. {
  860. if (!is_array($media_uri))
  861. {
  862. if ($css_media_type)
  863. $media_uri = array($media_uri => $css_media_type);
  864. else
  865. $media_uri = array($media_uri);
  866. }
  867. $list_uri = array();
  868. foreach ($media_uri as $file => $media)
  869. {
  870. if (!preg_match('/^http(s?):\/\//i', $media))
  871. {
  872. $different = 0;
  873. $different_css = 0;
  874. $type = 'css';
  875. if (!$css_media_type)
  876. {
  877. $type = 'js';
  878. $file = $media;
  879. }
  880. $override_path = str_replace(__PS_BASE_URI__.'modules/', _PS_ROOT_DIR_.'/themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different);
  881. $override_path_css = str_replace(basename ($file), $type.'/'.basename ($file), str_replace(__PS_BASE_URI__, _PS_ROOT_DIR_.'/', $file), $different_css );
  882. if ($different && file_exists($override_path))
  883. $file = str_replace(__PS_BASE_URI__.'modules/', __PS_BASE_URI__.'themes/'._THEME_NAME_.'/'.$type.'/modules/', $file, $different);
  884. elseif ($different_css && file_exists($override_path_css))
  885. $file = $override_path_css;
  886. if ($css_media_type)
  887. $list_uri[$file] = $media;
  888. else
  889. $list_uri[] = $file;
  890. }
  891. else
  892. $list_uri[$file] = $media;
  893. }
  894. if ($remove)
  895. {
  896. if ($css_media_type)
  897. return parent::removeCSS($list_uri, $css_media_type);
  898. return parent::removeJS($list_uri);
  899. }
  900. if ($css_media_type)
  901. return parent::addCSS($list_uri, $css_media_type, $offset);
  902. return parent::addJS($list_uri);
  903. }
  904. public function removeMedia($media_uri, $css_media_type = null)
  905. {
  906. Frontcontroller::addMedia($media_uri, $css_media_type, null, true);
  907. }
  908. /**
  909. * Add one or several CSS for front, checking if css files are overriden in theme/css/modules/ directory
  910. *
  911. * @see Controller::addCSS()
  912. */
  913. public function addCSS($css_uri, $css_media_type = 'all', $offset = null)
  914. {
  915. return Frontcontroller::addMedia($css_uri, $css_media_type, $offset = null);
  916. }
  917. public function removeCSS($css_uri, $css_media_type = 'all')
  918. {
  919. return Frontcontroller::removeMedia($css_uri, $css_media_type);
  920. }
  921. /**
  922. * Add one or several JS files for front, checking if js files are overriden in theme/js/modules/ directory
  923. *
  924. * @see Controller::addJS()
  925. */
  926. public function addJS($js_uri)
  927. {
  928. return Frontcontroller::addMedia($js_uri);
  929. }
  930. public function removeJS($js_uri)
  931. {
  932. return Frontcontroller::removeMedia($js_uri);
  933. }
  934. protected function recoverCart()
  935. {
  936. if (($id_cart = (int)Tools::getValue('recover_cart')) && Tools::getValue('token_cart') == md5(_COOKIE_KEY_.'recover_cart_'.$id_cart))
  937. {
  938. $cart = new Cart((int)$id_cart);
  939. if (Validate::isLoadedObject($cart))
  940. {
  941. $customer = new Customer((int)$cart->id_customer);
  942. if (Validate::isLoadedObject($customer))
  943. {
  944. $customer->logged = 1;
  945. $this->context->customer = $customer;
  946. $this->context->cookie->id_customer = (int)$customer->id;
  947. $this->context->cookie->customer_lastname = $customer->lastname;
  948. $this->context->cookie->customer_firstname = $customer->firstname;
  949. $this->context->cookie->logged = 1;
  950. $this->context->cookie->check_cgv = 1;
  951. $this->context->cookie->is_guest = $customer->isGuest();
  952. $this->context->cookie->passwd = $customer->passwd;
  953. $this->context->cookie->email = $customer->email;
  954. return $id_cart;
  955. }
  956. }
  957. }
  958. else
  959. return false;
  960. }
  961. /**
  962. * This is overrided to manage is behaviour
  963. * if a customer access to the site with mobile device.
  964. */
  965. public function setTemplate($default_template)
  966. {
  967. if ($this->useMobileTheme())
  968. $this->setMobileTemplate($default_template);
  969. else
  970. {
  971. $template = $this->getOverrideTemplate();
  972. if ($template)
  973. parent::setTemplate($template);
  974. else
  975. parent::setTemplate($default_template);
  976. }
  977. }
  978. /**
  979. * Returns the template corresponding to the current page.
  980. * By default this method return false but could easily be overridden in a specific controller
  981. *
  982. * @since 1.5
  983. * @return bool
  984. */
  985. public function getOverrideTemplate()
  986. {
  987. return Hook::exec('DisplayOverrideTemplate', array('controller' => $this));
  988. }
  989. protected function useMobileTheme()
  990. {
  991. static $use_mobile_template = null;
  992. // The mobile theme must have a layout to be used
  993. if ($use_mobile_template === null)
  994. $use_mobile_template = ($this->context->getMobileDevice() && file_exists(_PS_THEME_MOBILE_DIR_.'layout.tpl'));
  995. return $use_mobile_template;
  996. }
  997. protected function getThemeDir()
  998. {
  999. return $this->useMobileTheme() ? _PS_THEME_MOBILE_DIR_ : _PS_THEME_DIR_;
  1000. }
  1001. protected function getOverrideThemeDir()
  1002. {
  1003. return $this->useMobileTheme() ? _PS_THEME_MOBILE_OVERRIDE_DIR_ : _PS_THEME_OVERRIDE_DIR_;
  1004. }
  1005. /**
  1006. * Returns the layout corresponding to the current page by using the override system
  1007. * Ex:
  1008. * On the url: http://localhost/index.php?id_product=1&controller=product, this method will
  1009. * check if the layout exists in the following files (in that order), and return the first found:
  1010. * - /themes/default/override/layout-product-1.tpl
  1011. * - /themes/default/override/layout-product.tpl
  1012. * - /themes/default/layout.tpl
  1013. *
  1014. * @since 1.5
  1015. * @return bool|string
  1016. */
  1017. public function getLayout()
  1018. {
  1019. $entity = $this->php_self;
  1020. $id_item = (int)Tools::getValue('id_'.$entity);
  1021. $layout_dir = $this->getThemeDir();
  1022. $layout_override_dir = $this->getOverrideThemeDir();
  1023. $layout = false;
  1024. if ($entity)
  1025. {
  1026. if ($id_item > 0 && file_exists($layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl'))
  1027. $layout = $layout_override_dir.'layout-'.$entity.'-'.$id_item.'.tpl';
  1028. elseif (file_exists($layout_override_dir.'layout-'.$entity.'.tpl'))
  1029. $layout = $layout_override_dir.'layout-'.$entity.'.tpl';
  1030. }
  1031. if (!$layout && file_exists($layout_dir.'layout.tpl'))
  1032. $layout = $layout_dir.'layout.tpl';
  1033. return $layout;
  1034. }
  1035. public function getTemplatePath($template)
  1036. {
  1037. if (!$this->useMobileTheme())
  1038. return $template;
  1039. $tpl_file = basename($template);
  1040. $dirname = dirname($template).(substr(dirname($template), -1, 1) == '/' ? '' : '/');
  1041. if ($dirname == _PS_THEME_DIR_)
  1042. {
  1043. if (file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file))
  1044. $template = _PS_THEME_MOBILE_DIR_.$tpl_file;
  1045. }
  1046. elseif ($dirname == _PS_THEME_MOBILE_DIR_)
  1047. {
  1048. if (!file_exists(_PS_THEME_MOBILE_DIR_.$tpl_file) && file_exists(_PS_THEME_DIR_.$tpl_file))
  1049. $template = _PS_THEME_DIR_.$tpl_file;
  1050. }
  1051. return $template;
  1052. }
  1053. /**
  1054. * This checks if the template set is available for mobile themes,
  1055. * otherwise the front template is choosen.
  1056. */
  1057. public function setMobileTemplate($template)
  1058. {
  1059. // Needed for site map
  1060. $blockmanufacturer = Module::getInstanceByName('blockmanufacturer');
  1061. $blocksupplier = Module::getInstanceByName('blocksupplier');
  1062. $this->context->smarty->assign('categoriesTree', Category::getRootCategory()->recurseLiteCategTree(0));
  1063. $this->context->smarty->assign('categoriescmsTree', CMSCategory::getRecurseCategory($this->context->language->id, 1, 1, 1));
  1064. $this->context->smarty->assign('voucherAllowed', (int)CartRule::isFeatureActive());
  1065. $this->context->smarty->assign('display_manufacturer_link', (bool)$blockmanufacturer->active);
  1066. $this->context->smarty->assign('display_supplier_link', (bool)$blocksupplier->active);
  1067. $this->context->smarty->assign('PS_DISPLAY_SUPPLIERS', Configuration::get('PS_DISPLAY_SUPPLIERS'));
  1068. $this->context->smarty->assign('PS_DISPLAY_BEST_SELLERS', Configuration::get('PS_DISPLAY_BEST_SELLERS'));
  1069. $this->context->smarty->assign('display_store', Configuration::get('PS_STORES_DISPLAY_SITEMAP'));
  1070. $this->context->smarty->assign('conditions', Configuration::get('PS_CONDITIONS'));
  1071. $this->context->smarty->assign('id_cgv', Configuration::get('PS_CONDITIONS_CMS_ID'));
  1072. $this->context->smarty->assign('PS_SHOP_NAME', Configuration::get('PS_SHOP_NAME'));
  1073. $template = $this->getTemplatePath($template);
  1074. $assign = array();
  1075. $assign['tpl_file'] = basename($template, '.tpl');
  1076. if (isset($this->php_self))
  1077. $assign['controller_name'] = $this->php_self;
  1078. $this->context->smarty->assign($assign);
  1079. $this->template = $template;
  1080. }
  1081. /**
  1082. * Return an array with specific logo and favicon,
  1083. * if mobile device
  1084. *
  1085. * @since 1.5
  1086. * @return array
  1087. */
  1088. public function initLogoAndFavicon()
  1089. {
  1090. $mobile_device = $this->context->getMobileDevice();
  1091. if ($mobile_device && Configuration::get('PS_LOGO_MOBILE'))
  1092. $logo = self::$link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO_MOBILE').'?'.Configuration::get('PS_IMG_UPDATE_TIME'));
  1093. else
  1094. $logo = self::$link->getMediaLink(_PS_IMG_.Configuration::get('PS_LOGO'));
  1095. return array(
  1096. 'favicon_url' => _PS_IMG_.Configuration::get('PS_FAVICON'),
  1097. 'logo_image_width' => ($mobile_device == false ? Configuration::get('SHOP_LOGO_WIDTH') : Configuration::get('SHOP_LOGO_MOBILE_WIDTH')),
  1098. 'logo_image_height' => ($mobile_device == false ? Configuration::get('SHOP_LOGO_HEIGHT') : Configuration::get('SHOP_LOGO_MOBILE_HEIGHT')),
  1099. 'logo_url' => $logo
  1100. );
  1101. }
  1102. public function addColorsToProductList(&$products)
  1103. {
  1104. if (!is_array($products) || !count($products) || !file_exists(_PS_THEME_DIR_.'product-list-colors.tpl'))
  1105. return;
  1106. $products_need_cache = array();
  1107. foreach ($products as &$product)
  1108. if (!$this->isCached(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product'])))
  1109. $products_need_cache[] = (int)$product['id_product'];
  1110. $colors = false;
  1111. if (count($products_need_cache))
  1112. $colors = Product::getAttributesColorList($products_need_cache);
  1113. Tools::enableCache();
  1114. foreach ($products as &$product)
  1115. {
  1116. $tpl = $this->context->smarty->createTemplate(_PS_THEME_DIR_.'product-list-colors.tpl');
  1117. if (isset($colors[$product['id_product']]))
  1118. $tpl->assign(array(
  1119. 'id_product' => $product['id_product'],
  1120. 'colors_list' => $colors[$product['id_product']],
  1121. 'link' => Context::getContext()->link,
  1122. 'img_col_dir' => _THEME_COL_DIR_,
  1123. 'col_img_dir' => _PS_COL_IMG_DIR_
  1124. ));
  1125. if (!in_array($product['id_product'], $products_need_cache) || isset($colors[$product['id_product']]))
  1126. $product['color_list'] = $tpl->fetch(_PS_THEME_DIR_.'product-list-colors.tpl', $this->getColorsListCacheId($product['id_product']));
  1127. else
  1128. $product['color_list'] = '';
  1129. }
  1130. Tools::restoreCacheSettings();
  1131. }
  1132. protected function getColorsListCacheId($id_product)
  1133. {
  1134. return Product::getColorsListCacheId($id_product);
  1135. }
  1136. }