PageRenderTime 65ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 1ms

/classes/controller/AdminController.php

https://github.com/OnjanirinaPro/PrestaShop
PHP | 3861 lines | 2880 code | 475 blank | 506 comment | 763 complexity | 6366fbe0beb391373768ff6c94a464ae MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  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 AdminControllerCore extends Controller
  27. {
  28. public $path;
  29. public static $currentIndex;
  30. public $content;
  31. public $warnings = array();
  32. public $informations = array();
  33. public $confirmations = array();
  34. public $shopShareDatas = false;
  35. public $_languages = array();
  36. public $default_form_language;
  37. public $allow_employee_form_lang;
  38. public $layout = 'layout.tpl';
  39. public $bootstrap = false ;
  40. protected $meta_title;
  41. public $template = 'content.tpl';
  42. /** @var string Associated table name */
  43. public $table = 'configuration';
  44. public $list_id;
  45. /** @var string Object identifier inside the associated table */
  46. protected $identifier = false;
  47. protected $identifier_name = 'name';
  48. /** @var string Tab name */
  49. public $className;
  50. /** @var array tabAccess */
  51. public $tabAccess;
  52. /** @var integer Tab id */
  53. public $id = -1;
  54. public $required_database = false;
  55. /** @var string Security token */
  56. public $token;
  57. /** @var string shop | group_shop */
  58. public $shopLinkType;
  59. /** @var string Default ORDER BY clause when $_orderBy is not defined */
  60. protected $_defaultOrderBy = false;
  61. protected $_defaultOrderWay = 'ASC';
  62. public $tpl_form_vars = array();
  63. public $tpl_list_vars = array();
  64. public $tpl_delete_link_vars = array();
  65. public $tpl_option_vars = array();
  66. public $tpl_view_vars = array();
  67. public $tpl_required_fields_vars = array();
  68. public $base_tpl_view = null;
  69. public $base_tpl_form = null;
  70. /** @var bool if you want more fieldsets in the form */
  71. public $multiple_fieldsets = false;
  72. public $fields_value = false;
  73. /** @var array Errors displayed after post processing */
  74. public $errors = array();
  75. /** @var define if the header of the list contains filter and sorting links or not */
  76. protected $list_simple_header;
  77. /** @var array list to be generated */
  78. protected $fields_list;
  79. /** @var array modules list filters */
  80. protected $filter_modules_list = null;
  81. /** @var array modules list filters */
  82. protected $modules_list = array();
  83. /** @var array edit form to be generated */
  84. protected $fields_form;
  85. /** @var override of $fields_form */
  86. protected $fields_form_override;
  87. /** @var override form action */
  88. protected $submit_action;
  89. /** @var array list of option forms to be generated */
  90. protected $fields_options = array();
  91. protected $shopLink;
  92. /** @var string SQL query */
  93. protected $_listsql = '';
  94. /** @var array Cache for query results */
  95. protected $_list = array();
  96. /** @var define if the header of the list contains filter and sorting links or not */
  97. protected $toolbar_title;
  98. /** @var array list of toolbar buttons */
  99. protected $toolbar_btn = null;
  100. /** @var boolean scrolling toolbar */
  101. protected $toolbar_scroll = true;
  102. /** @var boolean set to false to hide toolbar and page title */
  103. protected $show_toolbar = true;
  104. /** @var boolean set to true to show toolbar and page title for options */
  105. protected $show_toolbar_options = false;
  106. /** @var integer Number of results in list */
  107. protected $_listTotal = 0;
  108. /** @var boolean Automatically join language table if true */
  109. public $lang = false;
  110. /** @var array WHERE clause determined by filter fields */
  111. protected $_filter;
  112. /** @var array Temporary SQL table WHERE clause determinated by filter fields */
  113. protected $_tmpTableFilter = '';
  114. /** @var array Number of results in list per page (used in select field) */
  115. protected $_pagination = array(20, 50, 100, 300, 1000);
  116. /** @var integer Default number of results in list per page */
  117. protected $_default_pagination = 50;
  118. /** @var string ORDER BY clause determined by field/arrows in list header */
  119. protected $_orderBy;
  120. /** @var string Order way (ASC, DESC) determined by arrows in list header */
  121. protected $_orderWay;
  122. /** @var array list of available actions for each list row - default actions are view, edit, delete, duplicate */
  123. protected $actions_available = array('view', 'edit', 'duplicate', 'delete');
  124. /** @var array list of required actions for each list row */
  125. protected $actions = array();
  126. /** @var array list of row ids associated with a given action for witch this action have to not be available */
  127. protected $list_skip_actions = array();
  128. /* @var boolean don't show header & footer */
  129. protected $lite_display = false;
  130. /** @var bool boolean List content lines are clickable if true */
  131. protected $list_no_link = false;
  132. protected $allow_export = false;
  133. /** @var array $cache_lang cache for traduction */
  134. public static $cache_lang = array();
  135. /** @var array required_fields to display in the Required Fields form */
  136. public $required_fields = array();
  137. /** @var Helper */
  138. protected $helper;
  139. /**
  140. * @var array actions to execute on multiple selections
  141. * Usage:
  142. * array(
  143. * 'actionName' => array(
  144. * 'text' => $this->l('Message displayed on the submit button (mandatory)'),
  145. * 'confirm' => $this->l('If set, this confirmation message will pop-up (optional)')),
  146. * 'anotherAction' => array(...)
  147. * );
  148. *
  149. * If your action is named 'actionName', you need to have a method named bulkactionName() that will be executed when the button is clicked.
  150. */
  151. protected $bulk_actions;
  152. /**
  153. * @var array ids of the rows selected
  154. */
  155. protected $boxes;
  156. /** @var string Do not automatically select * anymore but select only what is necessary */
  157. protected $explicitSelect = false;
  158. /** @var string Add fields into data query to display list */
  159. protected $_select;
  160. /** @var string Join tables into data query to display list */
  161. protected $_join;
  162. /** @var string Add conditions into data query to display list */
  163. protected $_where;
  164. /** @var string Group rows into data query to display list */
  165. protected $_group;
  166. /** @var string Having rows into data query to display list */
  167. protected $_having;
  168. protected $is_cms = false;
  169. /** @var string identifier to use for changing positions in lists (can be omitted if positions cannot be changed) */
  170. protected $position_identifier;
  171. protected $position_group_identifier;
  172. /** @var boolean Table records are not deleted but marked as deleted if set to true */
  173. protected $deleted = false;
  174. /**
  175. * @var bool is a list filter set
  176. */
  177. protected $filter;
  178. protected $noLink;
  179. protected $specificConfirmDelete = null;
  180. protected $colorOnBackground;
  181. /** @var bool If true, activates color on hover */
  182. protected $row_hover = true;
  183. /** @string Action to perform : 'edit', 'view', 'add', ... */
  184. protected $action;
  185. protected $display;
  186. protected $_includeContainer = true;
  187. protected $tab_modules_list = array('default_list' => array(), 'slider_list' => array());
  188. public $tpl_folder;
  189. protected $bo_theme;
  190. /** @var bool Redirect or not ater a creation */
  191. protected $_redirect = true;
  192. /** @var array Name and directory where class image are located */
  193. public $fieldImageSettings = array();
  194. /** @var string Image type */
  195. public $imageType = 'jpg';
  196. /** @var instanciation of the class associated with the AdminController */
  197. protected $object;
  198. /** @var int current object ID */
  199. protected $id_object;
  200. /**
  201. * @var current controller name without suffix
  202. */
  203. public $controller_name;
  204. public $multishop_context = -1;
  205. public $multishop_context_group = true;
  206. /**
  207. * Current breadcrumb position as an array of tab names
  208. */
  209. protected $breadcrumbs;
  210. //Bootstrap variable
  211. public $show_page_header_toolbar = false;
  212. public $page_header_toolbar_title;
  213. public $page_header_toolbar_btn = array();
  214. public $show_form_cancel_button;
  215. public $admin_webpath;
  216. protected $list_natives_modules = array();
  217. protected $list_partners_modules = array();
  218. public $modals = array();
  219. protected $logged_on_addons = false;
  220. public function __construct()
  221. {
  222. global $timer_start;
  223. $this->timer_start = $timer_start;
  224. // Has to be remove for the next Prestashop version
  225. global $token;
  226. $this->controller_type = 'admin';
  227. $this->controller_name = get_class($this);
  228. if (strpos($this->controller_name, 'Controller'))
  229. $this->controller_name = substr($this->controller_name, 0, -10);
  230. parent::__construct();
  231. if ($this->multishop_context == -1)
  232. $this->multishop_context = Shop::CONTEXT_ALL | Shop::CONTEXT_GROUP | Shop::CONTEXT_SHOP;
  233. $this->bo_theme = ((Validate::isLoadedObject($this->context->employee) && $this->context->employee->bo_theme) ? $this->context->employee->bo_theme : 'default');
  234. if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'template'))
  235. $this->bo_theme = 'default';
  236. $this->bo_css = ((Validate::isLoadedObject($this->context->employee) && $this->context->employee->bo_css) ? $this->context->employee->bo_css : 'admin-theme.css');
  237. if (!file_exists(_PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'css'.DIRECTORY_SEPARATOR.$this->bo_css))
  238. $this->bo_css = 'admin-theme.css';
  239. $this->context->smarty->setTemplateDir(array(
  240. _PS_BO_ALL_THEMES_DIR_.$this->bo_theme.DIRECTORY_SEPARATOR.'template',
  241. _PS_OVERRIDE_DIR_.'controllers'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'templates'
  242. ));
  243. $this->id = Tab::getIdFromClassName($this->controller_name);
  244. $this->token = Tools::getAdminToken($this->controller_name.(int)$this->id.(int)$this->context->employee->id);
  245. $token = $this->token;
  246. $this->_conf = array(
  247. 1 => $this->l('Successful deletion'),
  248. 2 => $this->l('The selection has been successfully deleted.'),
  249. 3 => $this->l('Successful creation'),
  250. 4 => $this->l('Successful update'),
  251. 5 => $this->l('The status has been successfully updated.'),
  252. 6 => $this->l('The settings have been successfully updated.'),
  253. 7 => $this->l('The image was successfully deleted.'),
  254. 8 => $this->l('The module was successfully downloaded.'),
  255. 9 => $this->l('The thumbnails were successfully regenerated.'),
  256. 10 => $this->l('The message was successfully sent to the customer.'),
  257. 11 => $this->l('Comment successfully added'),
  258. 12 => $this->l('Module(s) installed successfully.'),
  259. 13 => $this->l('Module(s) uninstalled successfully.'),
  260. 14 => $this->l('The translation was successfully copied.'),
  261. 15 => $this->l('The translations have been successfully added.'),
  262. 16 => $this->l('The module transplanted successfully to the hook.'),
  263. 17 => $this->l('The module was successfully removed from the hook.'),
  264. 18 => $this->l('Successful upload'),
  265. 19 => $this->l('Duplication was completed successfully.'),
  266. 20 => $this->l('The translation was added successfully, but the language has not been created.'),
  267. 21 => $this->l('Module reset successfully.'),
  268. 22 => $this->l('Module deleted successfully.'),
  269. 23 => $this->l('Localization pack imported successfully.'),
  270. 24 => $this->l('Localization pack imported successfully.'),
  271. 25 => $this->l('The selected images have successfully been moved.'),
  272. 26 => $this->l('Your cover image selection has been saved.'),
  273. 27 => $this->l('The image\'s shop association has been modified.'),
  274. 28 => $this->l('A zone has been assigned to the selection successfully.'),
  275. 29 => $this->l('Successful upgrade'),
  276. 30 => $this->l('A partial refund was successfully created.'),
  277. 31 => $this->l('The discount was successfully generated.'),
  278. 32 => $this->l('Successfully signed in to PrestaShop Addons')
  279. );
  280. if (!$this->identifier) $this->identifier = 'id_'.$this->table;
  281. if (!$this->_defaultOrderBy) $this->_defaultOrderBy = $this->identifier;
  282. $this->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, $this->id);
  283. // Fix for homepage
  284. if ($this->controller_name == 'AdminDashboard')
  285. $_POST['token'] = $this->token;
  286. if (!Shop::isFeatureActive())
  287. $this->shopLinkType = '';
  288. //$this->base_template_folder = _PS_BO_ALL_THEMES_DIR_.$this->bo_theme.'/template';
  289. $this->override_folder = Tools::toUnderscoreCase(substr($this->controller_name, 5)).'/';
  290. // Get the name of the folder containing the custom tpl files
  291. $this->tpl_folder = Tools::toUnderscoreCase(substr($this->controller_name, 5)).'/';
  292. $this->initShopContext();
  293. $this->context->currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
  294. $this->admin_webpath = str_ireplace(_PS_CORE_DIR_, '', _PS_ADMIN_DIR_);
  295. $this->admin_webpath = preg_replace('/^'.preg_quote(DIRECTORY_SEPARATOR, '/').'/', '', $this->admin_webpath);
  296. // Check if logged on Addons
  297. if (isset($this->context->cookie->username_addons) && isset($this->context->cookie->password_addons) && !empty($this->context->cookie->username_addons) && !empty($this->context->cookie->password_addons))
  298. $this->logged_on_addons = true;
  299. }
  300. /**
  301. * Set breadcrumbs array for the controller page
  302. */
  303. public function initBreadcrumbs($tab_id = null, $tabs = null)
  304. {
  305. if (is_array($tabs) || count($tabs))
  306. $tabs = array();
  307. if (is_null($tab_id))
  308. $tab_id = $this->id;
  309. $tabs = Tab::recursiveTab($tab_id, $tabs);
  310. $dummy = array('name' => '', 'href' => '', 'icon' => '');
  311. $breadcrumbs2 = array(
  312. 'container' => $dummy,
  313. 'tab' => $dummy,
  314. 'action' => $dummy
  315. );
  316. if (isset($tabs[0]))
  317. {
  318. $breadcrumbs2['tab']['name'] = $tabs[0]['name'];
  319. $breadcrumbs2['tab']['href'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_ ).'/'.$this->context->link->getAdminLink($tabs[0]['class_name']);
  320. if (!isset($tabs[1]))
  321. $breadcrumbs2['tab']['icon'] = 'icon-'.$tabs[0]['class_name'];
  322. }
  323. if (isset($tabs[1]))
  324. {
  325. $breadcrumbs2['container']['name'] = $tabs[1]['name'];
  326. $breadcrumbs2['container']['href'] = __PS_BASE_URI__.basename(_PS_ADMIN_DIR_ ).'/'.$this->context->link->getAdminLink($tabs[1]['class_name']);
  327. $breadcrumbs2['container']['icon'] = 'icon-'.$tabs[1]['class_name'];
  328. }
  329. /* content, edit, list, add, details, options, view */
  330. switch ($this->display)
  331. {
  332. case 'add':
  333. $breadcrumbs2['action']['name'] = $this->l('Add', null, null, false);
  334. $breadcrumbs2['action']['icon'] = 'icon-plus';
  335. break;
  336. case 'edit':
  337. $breadcrumbs2['action']['name'] = $this->l('Edit', null, null, false);
  338. $breadcrumbs2['action']['icon'] = 'icon-pencil';
  339. break;
  340. case '':
  341. case 'list':
  342. $breadcrumbs2['action']['name'] = $this->l('List', null, null, false);
  343. $breadcrumbs2['action']['icon'] = 'icon-th-list';
  344. break;
  345. case 'details':
  346. case 'view':
  347. $breadcrumbs2['action']['name'] = $this->l('View details', null, null, false);
  348. $breadcrumbs2['action']['icon'] = 'icon-zoom-in';
  349. break;
  350. case 'options':
  351. $breadcrumbs2['action']['name'] = $this->l('Options', null, null, false);
  352. $breadcrumbs2['action']['icon'] = 'icon-cogs';
  353. break;
  354. case 'generator':
  355. $breadcrumbs2['action']['name'] = $this->l('Generator', null, null, false);
  356. $breadcrumbs2['action']['icon'] = 'icon-flask';
  357. break;
  358. }
  359. $this->context->smarty->assign('breadcrumbs2', $breadcrumbs2);
  360. /* BEGIN - Backward compatibility < 1.6.0.3 */
  361. $this->breadcrumbs[] = $tabs[0]['name'];
  362. $navigationPipe = (Configuration::get('PS_NAVIGATION_PIPE') ? Configuration::get('PS_NAVIGATION_PIPE') : '>');
  363. $this->context->smarty->assign('navigationPipe', $navigationPipe);
  364. /* END - Backward compatibility < 1.6.0.3 */
  365. }
  366. /**
  367. * set default toolbar_title to admin breadcrumb
  368. *
  369. * @return void
  370. */
  371. public function initToolbarTitle()
  372. {
  373. $this->toolbar_title = is_array($this->breadcrumbs) ? array_unique($this->breadcrumbs) : array($this->breadcrumbs);
  374. switch ($this->display)
  375. {
  376. case 'edit':
  377. $this->toolbar_title[] = $this->l('Edit', null, null, false);
  378. break;
  379. case 'add':
  380. $this->toolbar_title[] = $this->l('Add new', null, null, false);
  381. break;
  382. case 'view':
  383. $this->toolbar_title[] = $this->l('View', null, null, false);
  384. break;
  385. }
  386. if ($filter = $this->addFiltersToBreadcrumbs())
  387. $this->toolbar_title[] = $filter;
  388. }
  389. public function addFiltersToBreadcrumbs()
  390. {
  391. if ($this->filter && is_array($this->fields_list))
  392. {
  393. $filters = array();
  394. foreach ($this->fields_list as $field => $t)
  395. {
  396. if (isset($t['filter_key']))
  397. $field = $t['filter_key'];
  398. if ($val = Tools::getValue($this->table.'Filter_'.$field))
  399. {
  400. if (!is_array($val))
  401. {
  402. $filter_value = '';
  403. if (isset($t['type']) && $t['type'] == 'bool')
  404. $filter_value = ((bool)$val) ? $this->l('yes') : $this->l('no');
  405. elseif (is_string($val))
  406. $filter_value = htmlspecialchars($val, ENT_QUOTES, 'UTF-8');
  407. if (!empty($filter_value))
  408. $filters[] = sprintf($this->l('%s: %s'), $t['title'], $filter_value);
  409. }
  410. else
  411. {
  412. $filter_value = '';
  413. foreach ($val as $v)
  414. if (is_string($v) && !empty($v))
  415. $filter_value .= ' - '.htmlspecialchars($v, ENT_QUOTES, 'UTF-8');
  416. $filter_value = ltrim($filter_value, ' -');
  417. if (!empty($filter_value))
  418. $filters[] = sprintf($this->l('%s: %s'), $t['title'], $filter_value);
  419. }
  420. }
  421. }
  422. if (count($filters))
  423. return sprintf($this->l('filter by %s'), implode(', ', $filters));
  424. }
  425. }
  426. /**
  427. * Check rights to view the current tab
  428. *
  429. * @param bool $disable
  430. * @return boolean
  431. */
  432. public function viewAccess($disable = false)
  433. {
  434. if ($disable)
  435. return true;
  436. if ($this->tabAccess['view'] === '1')
  437. return true;
  438. return false;
  439. }
  440. /**
  441. * Check for security token
  442. */
  443. public function checkToken()
  444. {
  445. $token = Tools::getValue('token');
  446. return (!empty($token) && $token === $this->token);
  447. }
  448. /**
  449. * Set the filters used for the list display
  450. */
  451. public function processFilter()
  452. {
  453. if (!isset($this->list_id))
  454. $this->list_id = $this->table;
  455. $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this)));
  456. if (isset($this->list_id))
  457. {
  458. foreach ($_POST as $key => $value)
  459. {
  460. if ($value === '')
  461. unset($this->context->cookie->{$prefix.$key});
  462. elseif (stripos($key, $this->list_id.'Filter_') === 0)
  463. $this->context->cookie->{$prefix.$key} = !is_array($value) ? $value : serialize($value);
  464. elseif (stripos($key, 'submitFilter') === 0)
  465. $this->context->cookie->$key = !is_array($value) ? $value : serialize($value);
  466. }
  467. foreach ($_GET as $key => $value)
  468. if (stripos($key, $this->list_id.'Orderby') === 0 && Validate::isOrderBy($value))
  469. {
  470. if ($value === '' || $value == $this->_defaultOrderBy)
  471. unset($this->context->cookie->{$prefix.$key});
  472. else
  473. $this->context->cookie->{$prefix.$key} = $value;
  474. }
  475. elseif (stripos($key, $this->list_id.'Orderway') === 0 && Validate::isOrderWay($value))
  476. {
  477. if ($value === '' || $value == $this->_defaultOrderWay)
  478. unset($this->context->cookie->{$prefix.$key});
  479. else
  480. $this->context->cookie->{$prefix.$key} = $value;
  481. }
  482. }
  483. $filters = $this->context->cookie->getFamily($prefix.$this->list_id.'Filter_');
  484. foreach ($filters as $key => $value)
  485. {
  486. /* Extracting filters from $_POST on key filter_ */
  487. if ($value != null && !strncmp($key, $prefix.$this->list_id.'Filter_', 7 + Tools::strlen($prefix.$this->list_id)))
  488. {
  489. $key = Tools::substr($key, 7 + Tools::strlen($prefix.$this->list_id));
  490. /* Table alias could be specified using a ! eg. alias!field */
  491. $tmp_tab = explode('!', $key);
  492. $filter = count($tmp_tab) > 1 ? $tmp_tab[1] : $tmp_tab[0];
  493. if ($field = $this->filterToField($key, $filter))
  494. {
  495. $type = (array_key_exists('filter_type', $field) ? $field['filter_type'] : (array_key_exists('type', $field) ? $field['type'] : false)); if (($type == 'date' || $type == 'datetime') && is_string($value))
  496. $value = Tools::unSerialize($value);
  497. $key = isset($tmp_tab[1]) ? $tmp_tab[0].'.`'.$tmp_tab[1].'`' : '`'.$tmp_tab[0].'`';
  498. // Assignement by reference
  499. if (array_key_exists('tmpTableFilter', $field))
  500. $sql_filter = & $this->_tmpTableFilter;
  501. elseif (array_key_exists('havingFilter', $field))
  502. $sql_filter = & $this->_filterHaving;
  503. else
  504. $sql_filter = & $this->_filter;
  505. /* Only for date filtering (from, to) */
  506. if (is_array($value))
  507. {
  508. if (isset($value[0]) && !empty($value[0]))
  509. {
  510. if (!Validate::isDate($value[0]))
  511. $this->errors[] = Tools::displayError('The \'From\' date format is invalid (YYYY-MM-DD)');
  512. else
  513. $sql_filter .= ' AND '.pSQL($key).' >= \''.pSQL(Tools::dateFrom($value[0])).'\'';
  514. }
  515. if (isset($value[1]) && !empty($value[1]))
  516. {
  517. if (!Validate::isDate($value[1]))
  518. $this->errors[] = Tools::displayError('The \'To\' date format is invalid (YYYY-MM-DD)');
  519. else
  520. $sql_filter .= ' AND '.pSQL($key).' <= \''.pSQL(Tools::dateTo($value[1])).'\'';
  521. }
  522. }
  523. else
  524. {
  525. $sql_filter .= ' AND ';
  526. $check_key = ($key == $this->identifier || $key == '`'.$this->identifier.'`');
  527. if ($type == 'int' || $type == 'bool')
  528. $sql_filter .= (($check_key || $key == '`active`') ? 'a.' : '').pSQL($key).' = '.(int)$value.' ';
  529. elseif ($type == 'decimal')
  530. $sql_filter .= ($check_key ? 'a.' : '').pSQL($key).' = '.(float)$value.' ';
  531. elseif ($type == 'select')
  532. $sql_filter .= ($check_key ? 'a.' : '').pSQL($key).' = \''.pSQL($value).'\' ';
  533. else
  534. {
  535. if ($type == 'price')
  536. $value = (float)str_replace(',', '.', $value);
  537. $sql_filter .= ($check_key ? 'a.' : '').pSQL($key).' LIKE \'%'.pSQL($value).'%\' ';
  538. }
  539. }
  540. }
  541. }
  542. }
  543. }
  544. /**
  545. * @todo uses redirectAdmin only if !$this->ajax
  546. */
  547. public function postProcess()
  548. {
  549. try {
  550. if ($this->ajax)
  551. {
  552. // from ajax-tab.php
  553. $action = Tools::getValue('action');
  554. // no need to use displayConf() here
  555. if (!empty($action) && method_exists($this, 'ajaxProcess'.Tools::toCamelCase($action)))
  556. {
  557. Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this));
  558. Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this));
  559. $return = $this->{'ajaxProcess'.Tools::toCamelCase($action)}();
  560. Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return));
  561. Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return));
  562. return $return;
  563. }
  564. elseif (!empty($action) && $this->controller_name == 'AdminModules' && Tools::getIsset('configure'))
  565. {
  566. $module_obj = Module::getInstanceByName(Tools::getValue('configure'));
  567. if (Validate::isLoadedObject($module_obj) && method_exists($module_obj, 'ajaxProcess'.$action))
  568. return $module_obj->{'ajaxProcess'.$action}();
  569. }
  570. elseif (method_exists($this, 'ajaxProcess'))
  571. return $this->ajaxProcess();
  572. }
  573. else
  574. {
  575. // Process list filtering
  576. if ($this->filter)
  577. $this->processFilter();
  578. // If the method named after the action exists, call "before" hooks, then call action method, then call "after" hooks
  579. if (!empty($this->action) && method_exists($this, 'process'.ucfirst(Tools::toCamelCase($this->action))))
  580. {
  581. // Hook before action
  582. Hook::exec('actionAdmin'.ucfirst($this->action).'Before', array('controller' => $this));
  583. Hook::exec('action'.get_class($this).ucfirst($this->action).'Before', array('controller' => $this));
  584. // Call process
  585. $return = $this->{'process'.Tools::toCamelCase($this->action)}();
  586. // Hook After Action
  587. Hook::exec('actionAdmin'.ucfirst($this->action).'After', array('controller' => $this, 'return' => $return));
  588. Hook::exec('action'.get_class($this).ucfirst($this->action).'After', array('controller' => $this, 'return' => $return));
  589. return $return;
  590. }
  591. }
  592. } catch (PrestaShopException $e) {
  593. $this->errors[] = $e->getMessage();
  594. };
  595. return false;
  596. }
  597. /**
  598. * Object Delete images
  599. */
  600. public function processDeleteImage()
  601. {
  602. if (Validate::isLoadedObject($object = $this->loadObject()))
  603. {
  604. if (($object->deleteImage()))
  605. {
  606. $redirect = self::$currentIndex.'&add'.$this->table.'&'.$this->identifier.'='.Tools::getValue($this->identifier).'&conf=7&token='.$this->token;
  607. if (!$this->ajax)
  608. $this->redirect_after = $redirect;
  609. else
  610. $this->content = 'ok';
  611. }
  612. }
  613. $this->errors[] = Tools::displayError('An error occurred while attempting to delete the image. (cannot load object).');
  614. return $object;
  615. }
  616. public function processExport($text_delimiter = '"')
  617. {
  618. // clean buffer
  619. if (ob_get_level() && ob_get_length() > 0)
  620. ob_clean();
  621. $this->getList($this->context->language->id, null, null, 0, false);
  622. if (!count($this->_list))
  623. return;
  624. header('Content-type: text/csv');
  625. header('Content-Type: application/force-download; charset=UTF-8');
  626. header('Cache-Control: no-store, no-cache');
  627. header('Content-disposition: attachment; filename="'.$this->table.'_'.date('Y-m-d_His').'.csv"');
  628. $headers = array();
  629. foreach ($this->fields_list as $datas)
  630. $headers[] = Tools::htmlentitiesDecodeUTF8($datas['title']);
  631. $content = array();
  632. foreach ($this->_list as $i => $row)
  633. {
  634. $content[$i] = array();
  635. $path_to_image = false;
  636. foreach ($this->fields_list as $key => $params)
  637. {
  638. $field_value = isset($row[$key]) ? Tools::htmlentitiesDecodeUTF8(
  639. Tools::nl2br($row[$key])) : '';
  640. if ($key == 'image')
  641. {
  642. if ($params['image'] != 'p' || Configuration::get('PS_LEGACY_IMAGES'))
  643. $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.$row['id_'.$this->table].(isset($row['id_image']) ? '-'.(int)$row['id_image'] : '').'.'.$this->imageType;
  644. else
  645. $path_to_image = Tools::getShopDomain(true)._PS_IMG_.$params['image'].'/'.Image::getImgFolderStatic($row['id_image']).(int)$row['id_image'].'.'.$this->imageType;
  646. if ($path_to_image)
  647. $field_value = $path_to_image;
  648. }
  649. if (isset($params['callback']))
  650. {
  651. $callback_obj = (isset($params['callback_object'])) ? $params['callback_object'] : $this->context->controller;
  652. $field_value = call_user_func_array(array($callback_obj, $params['callback']), array($field_value, $row));
  653. }
  654. $content[$i][] = $field_value;
  655. }
  656. }
  657. $this->context->smarty->assign(array(
  658. 'export_precontent' => "\xEF\xBB\xBF",
  659. 'export_headers' => $headers,
  660. 'export_content' => $content,
  661. 'text_delimiter' => $text_delimiter
  662. )
  663. );
  664. $this->layout = 'layout-export.tpl';
  665. }
  666. /**
  667. * Object Delete
  668. */
  669. public function processDelete()
  670. {
  671. if (Validate::isLoadedObject($object = $this->loadObject()))
  672. {
  673. $res = true;
  674. // check if request at least one object with noZeroObject
  675. if (isset($object->noZeroObject) && count(call_user_func(array($this->className, $object->noZeroObject))) <= 1)
  676. {
  677. $this->errors[] = Tools::displayError('You need at least one object.').
  678. ' <b>'.$this->table.'</b><br />'.
  679. Tools::displayError('You cannot delete all of the items.');
  680. }
  681. elseif (array_key_exists('delete', $this->list_skip_actions) && in_array($object->id, $this->list_skip_actions['delete'])) //check if some ids are in list_skip_actions and forbid deletion
  682. $this->errors[] = Tools::displayError('You cannot delete this item.');
  683. else
  684. {
  685. if ($this->deleted)
  686. {
  687. if (!empty($this->fieldImageSettings))
  688. $res = $object->deleteImage();
  689. if (!$res)
  690. $this->errors[] = Tools::displayError('Unable to delete associated images.');
  691. $object->deleted = 1;
  692. if ($res = $object->update())
  693. $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token;
  694. }
  695. elseif ($res = $object->delete())
  696. $this->redirect_after = self::$currentIndex.'&conf=1&token='.$this->token;
  697. $this->errors[] = Tools::displayError('An error occurred during deletion.');
  698. if ($res)
  699. PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id);
  700. }
  701. }
  702. else
  703. {
  704. $this->errors[] = Tools::displayError('An error occurred while deleting the object.').
  705. ' <b>'.$this->table.'</b> '.
  706. Tools::displayError('(cannot load object)');
  707. }
  708. return $object;
  709. }
  710. /**
  711. * Call the right method for creating or updating object
  712. *
  713. * @return mixed
  714. */
  715. public function processSave()
  716. {
  717. if ($this->id_object)
  718. {
  719. $this->object = $this->loadObject();
  720. return $this->processUpdate();
  721. }
  722. else
  723. return $this->processAdd();
  724. }
  725. /**
  726. * Object creation
  727. */
  728. public function processAdd()
  729. {
  730. if (!isset($this->className) || empty($this->className))
  731. return false;
  732. $this->validateRules();
  733. if (count($this->errors) <= 0)
  734. {
  735. $this->object = new $this->className();
  736. $this->copyFromPost($this->object, $this->table);
  737. $this->beforeAdd($this->object);
  738. if (method_exists($this->object, 'add') && !$this->object->add())
  739. {
  740. $this->errors[] = Tools::displayError('An error occurred while creating an object.').
  741. ' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>';
  742. }
  743. /* voluntary do affectation here */
  744. elseif (($_POST[$this->identifier] = $this->object->id) && $this->postImage($this->object->id) && !count($this->errors) && $this->_redirect)
  745. {
  746. PrestaShopLogger::addLog(sprintf($this->l('%s addition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$this->object->id, true, (int)$this->context->employee->id);
  747. $parent_id = (int)Tools::getValue('id_parent', 1);
  748. $this->afterAdd($this->object);
  749. $this->updateAssoShop($this->object->id);
  750. // Save and stay on same form
  751. if (empty($this->redirect_after) && $this->redirect_after !== false && Tools::isSubmit('submitAdd'.$this->table.'AndStay'))
  752. $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$this->object->id.'&conf=3&update'.$this->table.'&token='.$this->token;
  753. // Save and back to parent
  754. if (empty($this->redirect_after) && $this->redirect_after !== false && Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent'))
  755. $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=3&token='.$this->token;
  756. // Default behavior (save and back)
  757. if (empty($this->redirect_after) && $this->redirect_after !== false)
  758. $this->redirect_after = self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$this->object->id : '').'&conf=3&token='.$this->token;
  759. }
  760. }
  761. $this->errors = array_unique($this->errors);
  762. if (!empty($this->errors))
  763. {
  764. // if we have errors, we stay on the form instead of going back to the list
  765. $this->display = 'edit';
  766. return false;
  767. }
  768. return $this->object;
  769. }
  770. /**
  771. * Object update
  772. */
  773. public function processUpdate()
  774. {
  775. /* Checking fields validity */
  776. $this->validateRules();
  777. if (empty($this->errors))
  778. {
  779. $id = (int)Tools::getValue($this->identifier);
  780. /* Object update */
  781. if (isset($id) && !empty($id))
  782. {
  783. $object = new $this->className($id);
  784. if (Validate::isLoadedObject($object))
  785. {
  786. /* Specific to objects which must not be deleted */
  787. if ($this->deleted && $this->beforeDelete($object))
  788. {
  789. // Create new one with old objet values
  790. $object_new = $object->duplicateObject();
  791. if (Validate::isLoadedObject($object_new))
  792. {
  793. // Update old object to deleted
  794. $object->deleted = 1;
  795. $object->update();
  796. // Update new object with post values
  797. $this->copyFromPost($object_new, $this->table);
  798. $result = $object_new->update();
  799. if (Validate::isLoadedObject($object_new))
  800. $this->afterDelete($object_new, $object->id);
  801. }
  802. }
  803. else
  804. {
  805. $this->copyFromPost($object, $this->table);
  806. $result = $object->update();
  807. $this->afterUpdate($object);
  808. }
  809. if ($object->id)
  810. $this->updateAssoShop($object->id);
  811. if (!$result)
  812. {
  813. $this->errors[] = Tools::displayError('An error occurred while updating an object.').
  814. ' <b>'.$this->table.'</b> ('.Db::getInstance()->getMsgError().')';
  815. }
  816. elseif ($this->postImage($object->id) && !count($this->errors) && $this->_redirect)
  817. {
  818. $parent_id = (int)Tools::getValue('id_parent', 1);
  819. // Specific back redirect
  820. if ($back = Tools::getValue('back'))
  821. $this->redirect_after = urldecode($back).'&conf=4';
  822. // Specific scene feature
  823. // @todo change stay_here submit name (not clear for redirect to scene ... )
  824. if (Tools::getValue('stay_here') == 'on' || Tools::getValue('stay_here') == 'true' || Tools::getValue('stay_here') == '1')
  825. $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&updatescene&token='.$this->token;
  826. // Save and stay on same form
  827. // @todo on the to following if, we may prefer to avoid override redirect_after previous value
  828. if (Tools::isSubmit('submitAdd'.$this->table.'AndStay'))
  829. $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&update'.$this->table.'&token='.$this->token;
  830. // Save and back to parent
  831. if (Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent'))
  832. $this->redirect_after = self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=4&token='.$this->token;
  833. // Default behavior (save and back)
  834. if (empty($this->redirect_after) && $this->redirect_after !== false)
  835. $this->redirect_after = self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$object->id : '').'&conf=4&token='.$this->token;
  836. }
  837. PrestaShopLogger::addLog(sprintf($this->l('%s edition', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int)$object->id, true, (int)$this->context->employee->id);
  838. }
  839. else
  840. $this->errors[] = Tools::displayError('An error occurred while updating an object.').
  841. ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)');
  842. }
  843. }
  844. $this->errors = array_unique($this->errors);
  845. if (!empty($this->errors))
  846. {
  847. // if we have errors, we stay on the form instead of going back to the list
  848. $this->display = 'edit';
  849. return false;
  850. }
  851. if (isset($object))
  852. return $object;
  853. return;
  854. }
  855. /**
  856. * Change object required fields
  857. */
  858. public function processUpdateFields()
  859. {
  860. if (!is_array($fields = Tools::getValue('fieldsBox')))
  861. $fields = array();
  862. $object = new $this->className();
  863. if (!$object->addFieldsRequiredDatabase($fields))
  864. $this->errors[] = Tools::displayError('An error occurred when attempting to update the required fields.');
  865. else
  866. $this->redirect_after = self::$currentIndex.'&conf=4&token='.$this->token;
  867. return $object;
  868. }
  869. /**
  870. * Change object status (active, inactive)
  871. */
  872. public function processStatus()
  873. {
  874. if (Validate::isLoadedObject($object = $this->loadObject()))
  875. {
  876. if ($object->toggleStatus())
  877. {
  878. $matches = array();
  879. if (preg_match('/[\?|&]controller=([^&]*)/', (string)$_SERVER['HTTP_REFERER'], $matches) !== FALSE
  880. && strtolower($matches[1]) != strtolower(preg_replace('/controller/i', '', get_class($this))))
  881. $this->redirect_after = preg_replace('/[\?|&]conf=([^&]*)/i', '', (string)$_SERVER['HTTP_REFERER']);
  882. else
  883. $this->redirect_after = self::$currentIndex.'&token='.$this->token;
  884. $id_category = (($id_category = (int)Tools::getValue('id_category')) && Tools::getValue('id_product')) ? '&id_category='.$id_category : '';
  885. $this->redirect_after .= '&conf=5'.$id_category;
  886. }
  887. else
  888. $this->errors[] = Tools::displayError('An error occurred while updating the status.');
  889. }
  890. else
  891. $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').
  892. ' <b>'.$this->table.'</b> '.
  893. Tools::displayError('(cannot load object)');
  894. return $object;
  895. }
  896. /**
  897. * Change object position
  898. */
  899. public function processPosition()
  900. {
  901. if (!Validate::isLoadedObject($object = $this->loadObject()))
  902. {
  903. $this->errors[] = Tools::displayError('An error occurred while updating the status for an object.').
  904. ' <b>'.$this->table.'</b> '.Tools::displayError('(cannot load object)');
  905. }
  906. elseif (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position')))
  907. $this->errors[] = Tools::displayError('Failed to update the position.');
  908. else
  909. {
  910. $id_identifier_str = ($id_identifier = (int)Tools::getValue($this->identifier)) ? '&'.$this->identifier.'='.$id_identifier : '';
  911. $redirect = self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.$id_identifier_str.'&token='.$this->token;
  912. $this->redirect_after = $redirect;
  913. }
  914. return $object;
  915. }
  916. /**
  917. * Cancel all filters for this tab
  918. */
  919. public function processResetFilters($list_id = null)
  920. {
  921. if ($list_id === null)
  922. $list_id = isset($this->list_id) ? $this->list_id : $this->table;
  923. $prefix = str_replace(array('admin', 'controller'), '', Tools::strtolower(get_class($this)));
  924. $filters = $this->context->cookie->getFamily($prefix.$list_id.'Filter_');
  925. foreach ($filters as $cookie_key => $filter)
  926. if (strncmp($cookie_key, $prefix.$list_id.'Filter_', 7 + Tools::strlen($prefix.$list_id)) == 0)
  927. {
  928. $key = substr($cookie_key, 7 + Tools::strlen($prefix.$list_id));
  929. if (is_array($this->fields_list) && array_key_exists($key, $this->fields_list))
  930. $this->context->cookie->$cookie_key = null;
  931. unset($this->context->cookie->$cookie_key);
  932. }
  933. if (isset($this->context->cookie->{'submitFilter'.$list_id}))
  934. unset($this->context->cookie->{'submitFilter'.$list_id});
  935. if (isset($this->context->cookie->{$prefix.$list_id.'Orderby'}))
  936. unset($this->context->cookie->{$prefix.$list_id.'Orderby'});
  937. if (isset($this->context->cookie->{$prefix.$list_id.'Orderway'}))
  938. unset($this->context->cookie->{$prefix.$list_id.'Orderway'});
  939. $_POST = array();
  940. $this->_filter = false;
  941. unset($this->_filterHaving);
  942. unset($this->_having);
  943. }
  944. /**
  945. * Update options and preferences
  946. */
  947. protected function processUpdateOptions()
  948. {
  949. $this->beforeUpdateOptions();
  950. $languages = Language::getLanguages(false);
  951. $hide_multishop_checkbox = (Shop::getTotalShops(false, null) < 2) ? true : false;
  952. foreach ($this->fields_options as $category_data)
  953. {
  954. if (!isset($category_data['fields']))
  955. continue;
  956. $fields = $category_data['fields'];
  957. foreach ($fields as $field => $values)
  958. {
  959. if (isset($values['type']) && $values['type'] == 'selectLang')
  960. {
  961. foreach ($languages as $lang)
  962. if (Tools::getValue($field.'_'.strtoupper($lang['iso_code'])))
  963. $fields[$field.'_'.strtoupper($lang['iso_code'])] = array(
  964. 'type' => 'select',
  965. 'cast' => 'strval',
  966. 'identifier' => 'mode',
  967. 'list' => $values['list']
  968. );
  969. }
  970. }
  971. // Validate fields
  972. foreach ($fields as $field => $values)
  973. {
  974. // We don't validate fields with no visibility
  975. if (!$hide_multishop_checkbox && Shop::isFeatureActive() && isset($values['visibility']) && $values['visibility'] > Shop::getContext())
  976. continue;
  977. // Check if field is required
  978. if ((!Shop::isFeatureActive() && isset($values['required']) && $values['required'])
  979. || (Shop::isFeatureActive() && isset($_POST['multishopOverrideOption'][$field]) && isset($values['required']) && $values['required']))
  980. if (isset($values['type']) && $values['type'] == 'textLang')
  981. {
  982. foreach ($languages as $language)
  983. if (($value = Tools::getValue($field.'_'.$language['id_lang'])) == false && (string)$value != '0')
  984. $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $values['title']);
  985. }
  986. elseif (($value = Tools::getValue($field)) == false && (string)$value != '0')
  987. $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $values['title']);
  988. // Check field validator
  989. if (isset($values['type']) && $values['type'] == 'textLang')
  990. {
  991. foreach ($languages as $language)
  992. if (Tools::getValue($field.'_'.$language['id_lang']) && isset($values['validation']))
  993. if (!Validate::$values['validation'](Tools::getValue($field.'_'.$language['id_lang'])))
  994. $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $values['title']);
  995. }
  996. elseif (Tools::getValue($field) && isset($values['validation']))
  997. if (!Validate::$values['validation'](Tools::getValue($field)))
  998. $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $values['title']);
  999. // Set default value
  1000. if (Tools::getValue($field) === false && isset($values['default']))
  1001. $_POST[$field] = $values['default'];
  1002. }
  1003. if (!count($this->errors))
  1004. {
  1005. foreach ($fields as $key => $options)
  1006. {
  1007. if (!$hide_multishop_checkbox && Shop::isFeatureActive() && isset($options['visibility']) && $options['visibility'] > Shop::getContext())
  1008. continue;
  1009. if (!$hide_multishop_checkbox && Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_ALL && empty($options['no_multishop_checkbox']) && empty($_POST['multishopOverrideOption'][$key]))
  1010. {
  1011. Configuration::deleteFromContext($key);
  1012. continue;
  1013. }
  1014. // check if a method updateOptionFieldName is available
  1015. $method_name = 'updateOption'.Tools::toCamelCase($key, true);
  1016. if (method_exists($this, $method_name))
  1017. $this->$method_name(Tools::getValue($key));
  1018. elseif (isset($options['type']) && in_array($options['type'], array('textLang', 'textareaLang')))
  1019. {
  1020. $list = array();
  1021. foreach ($languages as $language)
  1022. {
  1023. $key_lang = Tools::getValue($key.'_'.$language['id_lang']);
  1024. $val = (isset($options['cast']) ? $options['cast']($key_lang) : $key_lang);
  1025. if ($this->validateField($val, $options))
  1026. {
  1027. if (Validate::isCleanHtml($val))
  1028. $list[$language['id_lang']] = $val;
  1029. else
  1030. $this->errors[] = Tools::displayError('Can not add configuration '.$key.' for lang '.Language::getIsoById((int)$language['id_lang']));
  1031. }
  1032. }
  1033. Configuration::updateValue($key, $list);
  1034. }
  1035. else
  1036. {
  1037. $val = (isset($options['cast']) ? $options['cast'](Tools::getValue($key)) : Tools::getValue($key));
  1038. if ($this->validateField($val, $options))
  1039. {
  1040. if (Validate::isCleanHtml($val))
  1041. Configuration::updateValue($key, $val);
  1042. else
  1043. $this->errors[] = Tools::displayError('Can not add configuration '.$key);
  1044. }
  1045. }
  1046. }
  1047. }
  1048. }
  1049. $this->display = 'list';
  1050. if (empty($this->errors))
  1051. $this->confirmations[] = $this->_conf[6];
  1052. }
  1053. public function initPageHeaderToolbar()
  1054. {
  1055. if (empty($this->toolbar_title))
  1056. $this->initToolbarTitle();
  1057. if (!is_array($this->toolbar_title))
  1058. $this->toolbar_title = array($this->toolbar_title);
  1059. switch ($this->display)
  1060. {
  1061. case 'view':
  1062. // Default cancel button - like old back link
  1063. $back = Tools::safeOutput(Tools::getValue('back', ''));
  1064. if (empty($back))
  1065. $back = self::$currentIndex.'&token='.$this->token;
  1066. if (!Validate::isCleanHtml($back))
  1067. die(Tools::displayError());
  1068. if (!$this->lite_display)
  1069. $this->page_header_toolbar_btn['back'] = array(
  1070. 'href' => $back,
  1071. 'desc' => $this->l('Back to list')
  1072. );
  1073. $obj = $this->loadObject(true);
  1074. if (Validate::isLoadedObject($obj) && isset($obj->{$this->identifier_name}) && !empty($obj->{$this->identifier_name}))
  1075. {
  1076. array_pop($this->toolbar_title);
  1077. $this->toolbar_title[] = is_array($obj->{$this->identifier_name}) ? $obj->{$this->identifier_name}[$this->context->employee->id_lang] : $obj->{$this->identifier_name};
  1078. }
  1079. break;
  1080. case 'edit':
  1081. $obj = $this->loadObject(true);
  1082. if (Validate::isLoadedObject($obj) && isset($obj->{$this->identifier_name}) && !empty($obj->{$this->identifier_name}))
  1083. {
  1084. array_pop($this->toolbar_title);
  1085. $this->toolbar_title[] = sprintf($this->l('Edit: %s'),
  1086. is_array($obj->{$this->identifier_name}) ? $obj->{$this->identifier_name}[$this->context->employee->id_lang] : $obj->{$this->identifier_name});
  1087. }
  1088. break;
  1089. }
  1090. if (is_array($this->page_header_toolbar_btn)
  1091. && $this->page_header_toolbar_btn instanceof Traversable
  1092. || count($this->toolbar_title))
  1093. $this->show_page_header_toolbar = true;
  1094. if (empty($this->page_header_toolbar_title))
  1095. $this->page_header_toolbar_title = array_pop($this->toolbar_title);
  1096. $this->addPageHeaderToolBarModulesListButton();
  1097. $this->context->smarty->assign('help_link', 'http://help.prestashop.com/'.$this->context->language->iso_code.'/doc/'.Tools::getValue('controller').'?version='._PS_VERSION_.'&country='.$this->context->country->iso_code);
  1098. }
  1099. /**
  1100. * assign default action in toolbar_btn smarty var, if they are not set.
  1101. * uses override to specifically add, modify or remove items
  1102. *
  1103. */
  1104. public function initToolbar()
  1105. {
  1106. switch ($this->display)
  1107. {
  1108. case 'add':
  1109. case 'edit':
  1110. // Default save button - action dynamically handled in javascript
  1111. $this->toolbar_btn['save'] = array(
  1112. 'href' => '#',
  1113. 'desc' => $this->l('Save')
  1114. );
  1115. $back = Tools::safeOutput(Tools::getValue('back', ''));
  1116. if (empty($back))
  1117. $back = self::$currentIndex.'&token='.$this->token;
  1118. if (!Validate::isCleanHtml($back))
  1119. die(Tools::displayError());
  1120. if (!$this->lite_display)
  1121. $this->toolbar_btn['cancel'] = array(
  1122. 'href' => $back,
  1123. 'desc' => $this->l('Cancel')
  1124. );
  1125. break;
  1126. case 'view':
  1127. // Default cancel button - like old back link
  1128. $back = Tools::safeOutput(Tools::getValue('back', ''));
  1129. if (empty($back))
  1130. $back = self::$currentIndex.'&token='.$this->token;
  1131. if (!Validate::isCleanHtml($back))
  1132. die(Tools::displayError());
  1133. if (!$this->lite_display)
  1134. $this->toolbar_btn['back'] = array(
  1135. 'href' => $back,
  1136. 'desc' => $this->l('Back to list')
  1137. );
  1138. break;
  1139. case 'options':
  1140. $this->toolbar_btn['save'] = array(
  1141. 'href' => '#',
  1142. 'desc' => $this->l('Save')
  1143. );
  1144. break;
  1145. default: // list
  1146. $this->toolbar_btn['new'] = array(
  1147. 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token,
  1148. 'desc' => $this->l('Add new')
  1149. );
  1150. if ($this->allow_export)
  1151. $this->toolbar_btn['export'] = array(
  1152. 'href' => self::$currentIndex.'&export'.$this->table.'&token='.$this->token,
  1153. 'desc' => $this->l('Export')
  1154. );
  1155. }
  1156. $this->addToolBarModulesListButton();
  1157. }
  1158. /**
  1159. * Load class object using identifier in $_GET (if possible)
  1160. * otherwise return an empty object, or die
  1161. *
  1162. * @param boolean $opt Return an empty object if load fail
  1163. * @return object|boolean
  1164. */
  1165. protected function loadObject($opt = false)
  1166. {
  1167. if (!isset($this->className) || empty($this->className))
  1168. return true;
  1169. $id = (int)Tools::getValue($this->identifier);
  1170. if ($id && Validate::isUnsignedId($id))
  1171. {
  1172. if (!$this->object)
  1173. $this->object = new $this->className($id);
  1174. if (Validate::isLoadedObject($this->object))
  1175. return $this->object;
  1176. // throw exception
  1177. $this->errors[] = Tools::displayError('The object cannot be loaded (or found)');
  1178. return false;
  1179. }
  1180. elseif ($opt)
  1181. {
  1182. if (!$this->object)
  1183. $this->object = new $this->className();
  1184. return $this->object;
  1185. }
  1186. else
  1187. {
  1188. $this->errors[] = Tools::displayError('The object cannot be loaded (the identifier is missing or invalid)');
  1189. return false;
  1190. }
  1191. }
  1192. /**
  1193. * Check if the token is valid, else display a warning page
  1194. */
  1195. public function checkAccess()
  1196. {
  1197. if (!$this->checkToken())
  1198. {
  1199. // If this is an XSS attempt, then we should only display a simple, secure page
  1200. // ${1} in the replacement string of the regexp is required,
  1201. // because the token may begin with a number and mix up with it (e.g. $17)
  1202. $url = preg_replace('/([&?]token=)[^&]*(&.*)?$/', '${1}'.$this->token.'$2', $_SERVER['REQUEST_URI']);
  1203. if (false === strpos($url, '?token=') && false === strpos($url, '&token='))
  1204. $url .= '&token='.$this->token;
  1205. if (strpos($url, '?') === false)
  1206. $url = str_replace('&token', '?controller=AdminDashboard&token', $url);
  1207. $this->context->smarty->assign('url', htmlentities($url));
  1208. return false;
  1209. }
  1210. return true;
  1211. }
  1212. protected function filterToField($key, $filter)
  1213. {
  1214. if (!isset($this->fields_list))
  1215. return false;
  1216. foreach ($this->fields_list as $field)
  1217. if (array_key_exists('filter_key', $field) && $field['filter_key'] == $key)
  1218. return $field;
  1219. if (array_key_exists($filter, $this->fields_list))
  1220. return $this->fields_list[$filter];
  1221. return false;
  1222. }
  1223. public function displayNoSmarty()
  1224. {
  1225. }
  1226. public function displayAjax()
  1227. {
  1228. if ($this->json)
  1229. {
  1230. $this->context->smarty->assign(array(
  1231. 'json' => true,
  1232. 'status' => $this->status,
  1233. ));
  1234. }
  1235. $this->layout = 'layout-ajax.tpl';
  1236. $this->display_header = false;
  1237. $this->display_footer = false;
  1238. return $this->display();
  1239. }
  1240. protected function redirect()
  1241. {
  1242. header('Location: '.$this->redirect_after);
  1243. exit;
  1244. }
  1245. public function display()
  1246. {
  1247. $this->context->smarty->assign(array(
  1248. 'display_header' => $this->display_header,

Large files files are truncated, but you can click here to view the full file