PageRenderTime 55ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/controller/Controller.php

https://gitlab.com/mtellezgalindo/PrestaShop
PHP | 529 lines | 318 code | 70 blank | 141 comment | 88 complexity | d21ddefb7c5906f54663aee8d88e308c MD5 | raw file
Possible License(s): CC-BY-SA-3.0, 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. /**
  27. * @since 1.5.0
  28. */
  29. abstract class ControllerCore
  30. {
  31. /**
  32. * @var Context
  33. */
  34. protected $context;
  35. /**
  36. * @var array list of css files
  37. */
  38. public $css_files = array();
  39. /**
  40. * @var array list of javascript files
  41. */
  42. public $js_files = array();
  43. /**
  44. * @var array list of php error
  45. */
  46. public static $php_errors = array();
  47. /**
  48. * @var bool check if header will be displayed
  49. */
  50. protected $display_header;
  51. /**
  52. * @var string template name for page content
  53. */
  54. protected $template;
  55. /**
  56. * @var string check if footer will be displayed
  57. */
  58. protected $display_footer;
  59. /**
  60. * @var string check if only content will be displayed
  61. */
  62. protected $content_only = false;
  63. /**
  64. * @var bool If ajax parameter is detected in request, set this flag to true
  65. */
  66. public $ajax = false;
  67. protected $json = false;
  68. protected $status = '';
  69. protected $redirect_after = null;
  70. public $controller_type;
  71. public $php_self;
  72. /**
  73. * check that the controller is available for the current user/visitor
  74. */
  75. abstract public function checkAccess();
  76. /**
  77. * check that the current user/visitor has valid view permissions
  78. */
  79. abstract public function viewAccess();
  80. /**
  81. * Initialize the page
  82. */
  83. public function init()
  84. {
  85. if (_PS_MODE_DEV_ && $this->controller_type == 'admin')
  86. set_error_handler(array(__CLASS__, 'myErrorHandler'));
  87. if (!defined('_PS_BASE_URL_'))
  88. define('_PS_BASE_URL_', Tools::getShopDomain(true));
  89. if (!defined('_PS_BASE_URL_SSL_'))
  90. define('_PS_BASE_URL_SSL_', Tools::getShopDomainSsl(true));
  91. }
  92. /**
  93. * Do the page treatment : post process, ajax process, etc.
  94. */
  95. abstract public function postProcess();
  96. /**
  97. * Display page view
  98. */
  99. abstract public function display();
  100. /**
  101. * Redirect after process if no error
  102. */
  103. abstract protected function redirect();
  104. /**
  105. * Set default media list for controller
  106. */
  107. abstract public function setMedia();
  108. /**
  109. * Get an instance of a controller
  110. *
  111. * @param string $class_name
  112. * @param bool $auth
  113. * @param bool $ssl
  114. */
  115. public static function getController($class_name, $auth = false, $ssl = false)
  116. {
  117. return new $class_name($auth, $ssl);
  118. }
  119. public function __construct()
  120. {
  121. if (is_null($this->display_header))
  122. $this->display_header = true;
  123. if (is_null($this->display_footer))
  124. $this->display_footer = true;
  125. $this->context = Context::getContext();
  126. $this->context->controller = $this;
  127. // Usage of ajax parameter is deprecated
  128. $this->ajax = Tools::getValue('ajax') || Tools::isSubmit('ajax');
  129. if (!headers_sent()
  130. && isset($_SERVER['HTTP_USER_AGENT'])
  131. && (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false
  132. || strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') !== false))
  133. header('X-UA-Compatible: IE=edge,chrome=1');
  134. }
  135. /**
  136. * Start controller process (this method shouldn't be overriden !)
  137. */
  138. public function run()
  139. {
  140. $this->init();
  141. if ($this->checkAccess())
  142. {
  143. // setMedia MUST be called before postProcess
  144. if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className)))
  145. $this->setMedia();
  146. // postProcess handles ajaxProcess
  147. $this->postProcess();
  148. if (!empty($this->redirect_after))
  149. $this->redirect();
  150. if (!$this->content_only && ($this->display_header || (isset($this->className) && $this->className)))
  151. $this->initHeader();
  152. if ($this->viewAccess())
  153. $this->initContent();
  154. else
  155. $this->errors[] = Tools::displayError('Access denied.');
  156. if (!$this->content_only && ($this->display_footer || (isset($this->className) && $this->className)))
  157. $this->initFooter();
  158. // default behavior for ajax process is to use $_POST[action] or $_GET[action]
  159. // then using displayAjax[action]
  160. if ($this->ajax)
  161. {
  162. $action = Tools::toCamelCase(Tools::getValue('action'), true);
  163. if (!empty($action) && method_exists($this, 'displayAjax'.$action))
  164. $this->{'displayAjax'.$action}();
  165. elseif (method_exists($this, 'displayAjax'))
  166. $this->displayAjax();
  167. }
  168. else
  169. $this->display();
  170. }
  171. else
  172. {
  173. $this->initCursedPage();
  174. $this->smartyOutputContent($this->layout);
  175. }
  176. }
  177. public function displayHeader($display = true)
  178. {
  179. $this->display_header = $display;
  180. }
  181. public function displayFooter($display = true)
  182. {
  183. $this->display_footer = $display;
  184. }
  185. public function setTemplate($template)
  186. {
  187. $this->template = $template;
  188. }
  189. /**
  190. * Assign smarty variables for the page header
  191. */
  192. abstract public function initHeader();
  193. /**
  194. * Assign smarty variables for the page main content
  195. */
  196. abstract public function initContent();
  197. /**
  198. * Assign smarty variables when access is forbidden
  199. */
  200. abstract public function initCursedPage();
  201. /**
  202. * Assign smarty variables for the page footer
  203. */
  204. abstract public function initFooter();
  205. /**
  206. * Add a new stylesheet in page header.
  207. *
  208. * @param mixed $css_uri Path to css file, or list of css files like this : array(array(uri => media_type), ...)
  209. * @param string $css_media_type
  210. * @param integer $offset
  211. * @param bool $check_path
  212. * @return true
  213. */
  214. public function addCSS($css_uri, $css_media_type = 'all', $offset = null, $check_path = true)
  215. {
  216. if (!is_array($css_uri))
  217. $css_uri = array($css_uri);
  218. foreach ($css_uri as $css_file => $media)
  219. {
  220. if (is_string($css_file) && strlen($css_file) > 1)
  221. {
  222. if ($check_path)
  223. $css_path = Media::getCSSPath($css_file, $media);
  224. else
  225. $css_path = array($css_file => $media);
  226. }
  227. else
  228. {
  229. if ($check_path)
  230. $css_path = Media::getCSSPath($media, $css_media_type);
  231. else
  232. $css_path = array($media => $css_media_type);
  233. }
  234. $key = is_array($css_path) ? key($css_path) : $css_path;
  235. if ($css_path && (!isset($this->css_files[$key]) || ($this->css_files[$key] != reset($css_path))))
  236. {
  237. $size = count($this->css_files);
  238. if ($offset === null || $offset > $size || $offset < 0 || !is_numeric($offset))
  239. $offset = $size;
  240. $this->css_files = array_merge(array_slice($this->css_files, 0, $offset), $css_path, array_slice($this->css_files, $offset));
  241. }
  242. }
  243. }
  244. public function removeCSS($css_uri, $css_media_type = 'all', $check_path = true)
  245. {
  246. if (!is_array($css_uri))
  247. $css_uri = array($css_uri);
  248. foreach ($css_uri as $css_file => $media)
  249. {
  250. if (is_string($css_file) && strlen($css_file) > 1)
  251. {
  252. if ($check_path)
  253. $css_path = Media::getCSSPath($css_file, $media);
  254. else
  255. $css_path = array($css_file => $media);
  256. }
  257. else
  258. {
  259. if ($check_path)
  260. $css_path = Media::getCSSPath($media, $css_media_type);
  261. else
  262. $css_path = array($media => $css_media_type);
  263. }
  264. if ($css_path && isset($this->css_files[key($css_path)]) && ($this->css_files[key($css_path)] == reset($css_path)))
  265. unset($this->css_files[key($css_path)]);
  266. }
  267. }
  268. /**
  269. * Add a new javascript file in page header.
  270. *
  271. * @param mixed $js_uri
  272. * @param bool $check_path
  273. * @return void
  274. */
  275. public function addJS($js_uri, $check_path = true)
  276. {
  277. if (is_array($js_uri))
  278. foreach ($js_uri as $js_file)
  279. {
  280. $js_path = $js_file;
  281. if ($check_path)
  282. $js_path = Media::getJSPath($js_file);
  283. $key = is_array($js_path) ? key($js_path) : $js_path;
  284. if ($js_path && !in_array($js_path, $this->js_files))
  285. $this->js_files[] = $js_path;
  286. }
  287. else
  288. {
  289. $js_path = $js_uri;
  290. if ($check_path)
  291. $js_path = Media::getJSPath($js_uri);
  292. if ($js_path && !in_array($js_path, $this->js_files))
  293. $this->js_files[] = $js_path;
  294. }
  295. }
  296. public function removeJS($js_uri)
  297. {
  298. if (is_array($js_uri))
  299. foreach ($js_uri as $js_file)
  300. {
  301. $js_path = $js_file;
  302. if ($check_path)
  303. $js_path = Media::getJSPath($js_file);
  304. if ($js_path && in_array($js_path, $this->js_files))
  305. unset($this->js_files[array_search($js_path, $this->js_files)]);
  306. }
  307. else
  308. {
  309. $js_path = $js_uri;
  310. if ($check_path)
  311. $js_path = Media::getJSPath($js_uri);
  312. if ($js_path)
  313. unset($this->js_files[array_search($js_path, $this->js_files)]);
  314. }
  315. }
  316. /**
  317. * Add a new javascript file in page header.
  318. *
  319. * @param mixed $js_uri
  320. * @return void
  321. */
  322. public function addJquery($version = null, $folder = null, $minifier = true)
  323. {
  324. $this->addJS(Media::getJqueryPath($version, $folder, $minifier), false);
  325. }
  326. /**
  327. * Add a new javascript file in page header.
  328. *
  329. * @param mixed $js_uri
  330. * @return void
  331. */
  332. public function addJqueryUI($component, $theme = 'base', $check_dependencies = true)
  333. {
  334. $ui_path = array();
  335. if (!is_array($component))
  336. $component = array($component);
  337. foreach ($component as $ui)
  338. {
  339. $ui_path = Media::getJqueryUIPath($ui, $theme, $check_dependencies);
  340. $this->addCSS($ui_path['css'], null, false);
  341. $this->addJS($ui_path['js'], false);
  342. }
  343. }
  344. /**
  345. * Add a new javascript file in page header.
  346. *
  347. * @param $name
  348. * @param null $folder
  349. * @param bool $css
  350. */
  351. public function addJqueryPlugin($name, $folder = null, $css = true)
  352. {
  353. if (!is_array($name))
  354. $name = array($name);
  355. if (is_array($name))
  356. {
  357. foreach ($name as $plugin)
  358. {
  359. $plugin_path = Media::getJqueryPluginPath($plugin, $folder);
  360. if (!empty($plugin_path['js']))
  361. $this->addJS($plugin_path['js'], false);
  362. if ($css && !empty($plugin_path['css']))
  363. $this->addCSS(key($plugin_path['css']), 'all', null, false);
  364. }
  365. }
  366. }
  367. /**
  368. * @since 1.5
  369. * @return bool return true if Controller is called from XmlHttpRequest
  370. */
  371. public function isXmlHttpRequest()
  372. {
  373. return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
  374. }
  375. protected function smartyOutputContent($content)
  376. {
  377. $this->context->cookie->write();
  378. $js_tag = 'js_def';
  379. $this->context->smarty->assign($js_tag, $js_tag);
  380. if (is_array($content))
  381. foreach ($content as $tpl)
  382. $html = $this->context->smarty->fetch($tpl);
  383. else
  384. $html = $this->context->smarty->fetch($content);
  385. $html = trim($html);
  386. if ($this->controller_type == 'front' && !empty($html) && $this->getLayout())
  387. {
  388. $live_edit_content = '';
  389. if (!$this->useMobileTheme() && $this->checkLiveEditAccess())
  390. $live_edit_content = $this->getLiveEditFooter();
  391. $dom_available = extension_loaded('dom') ? true : false;
  392. $defer = (bool)Configuration::get('PS_JS_DEFER');
  393. if ($defer && $dom_available)
  394. $html = Media::deferInlineScripts($html);
  395. $html = trim(str_replace(array('</body>', '</html>'), '', $html))."\n";
  396. $this->context->smarty->assign(array(
  397. $js_tag => Media::getJsDef(),
  398. 'js_files' => $defer ? array_unique($this->js_files) : array(),
  399. 'js_inline' => ($defer && $dom_available) ? Media::getInlineScript() : array()
  400. ));
  401. $javascript = $this->context->smarty->fetch(_PS_ALL_THEMES_DIR_.'javascript.tpl');
  402. echo ($defer ? $html.$javascript : preg_replace('/(?<!\$)'.$js_tag.'/', $javascript, $html)).$live_edit_content.((!isset($this->ajax) || ! $this->ajax) ? '</body></html>' : '');
  403. }
  404. else
  405. echo $html;
  406. }
  407. protected function isCached($template, $cacheId = null, $compileId = null)
  408. {
  409. Tools::enableCache();
  410. $res = $this->context->smarty->isCached($template, $cacheId, $compileId);
  411. Tools::restoreCacheSettings();
  412. return $res;
  413. }
  414. public static function myErrorHandler($errno, $errstr, $errfile, $errline)
  415. {
  416. if (error_reporting() === 0)
  417. return false;
  418. switch ($errno)
  419. {
  420. case E_USER_ERROR:
  421. case E_ERROR:
  422. die('Fatal error: '.$errstr.' in '.$errfile.' on line '.$errline);
  423. break;
  424. case E_USER_WARNING:
  425. case E_WARNING:
  426. $type = 'Warning';
  427. break;
  428. case E_USER_NOTICE:
  429. case E_NOTICE:
  430. $type = 'Notice';
  431. break;
  432. default:
  433. $type = 'Unknow error';
  434. break;
  435. }
  436. Controller::$php_errors[] = array(
  437. 'type' => $type,
  438. 'errline' => (int)$errline,
  439. 'errfile' => str_replace('\\', '\\\\', $errfile), // Hack for Windows paths
  440. 'errno' => (int)$errno,
  441. 'errstr' => $errstr
  442. );
  443. Context::getContext()->smarty->assign('php_errors', Controller::$php_errors);
  444. return true;
  445. }
  446. protected function ajaxDie($value = null, $controller = null, $method = null)
  447. {
  448. if ($controller === null)
  449. $controller = get_class($this);
  450. if ($method === null)
  451. {
  452. $bt = debug_backtrace();
  453. $method = $bt[1]['function'];
  454. }
  455. Hook::exec('actionBeforeAjaxDie', array('controller' => $controller, 'method' => $method, 'value' => $value));
  456. Hook::exec('actionBeforeAjaxDie'.$controller.$method, array('value' => $value));
  457. die($value);
  458. }
  459. }