PageRenderTime 57ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/classes/controller/AdminController.php

https://gitlab.com/mtellezgalindo/PrestaShop
PHP | 3971 lines | 2969 code | 494 blank | 508 comment | 783 complexity | 3b99df94b6eb36c743783b5b3652aa12 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-3.0

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

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