PageRenderTime 49ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/controllers/admin/AdminCategoriesController.php

https://bitbucket.org/marcenuc/prestashop
PHP | 718 lines | 607 code | 63 blank | 48 comment | 146 complexity | 760c70dfe1fa67156ab309cb605ae2ff MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-3.0
  1. <?php
  2. /*
  3. * 2007-2012 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-2012 PrestaShop SA
  23. * @version Release: $Revision: 8971 $
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. * International Registered Trademark & Property of PrestaShop SA
  26. */
  27. class AdminCategoriesControllerCore extends AdminController
  28. {
  29. /**
  30. * @var object Category() instance for navigation
  31. */
  32. protected $_category = null;
  33. protected $position_identifier = 'id_category_to_move';
  34. /** @var boolean does the product have to be removed during the delete process */
  35. public $remove_products = true;
  36. /** @var boolean does the product have to be disable during the delete process */
  37. public $disable_products = false;
  38. public function __construct()
  39. {
  40. $this->table = 'category';
  41. $this->className = 'Category';
  42. $this->lang = true;
  43. $this->deleted = false;
  44. $this->explicitSelect = true;
  45. $this->context = Context::getContext();
  46. $this->fieldImageSettings = array(
  47. 'name' => 'image',
  48. 'dir' => 'c'
  49. );
  50. $this->fields_list = array(
  51. 'id_category' => array(
  52. 'title' => $this->l('ID'),
  53. 'align' => 'center',
  54. 'width' => 20
  55. ),
  56. 'name' => array(
  57. 'title' => $this->l('Name'),
  58. 'width' => 'auto'
  59. ),
  60. 'description' => array(
  61. 'title' => $this->l('Description'),
  62. 'width' => 500,
  63. 'maxlength' => 90,
  64. 'callback' => 'getDescriptionClean',
  65. 'orderby' => false
  66. ),
  67. 'position' => array(
  68. 'title' => $this->l('Position'),
  69. 'width' => 40,
  70. 'filter_key' => 'sa!position',
  71. 'align' => 'center',
  72. 'position' => 'position'
  73. ),
  74. 'active' => array(
  75. 'title' => $this->l('Displayed'),
  76. 'active' => 'status',
  77. 'align' => 'center',
  78. 'type' => 'bool',
  79. 'width' => 70,
  80. 'orderby' => false
  81. )
  82. );
  83. $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected')));
  84. $this->specificConfirmDelete = false;
  85. parent::__construct();
  86. }
  87. public function init()
  88. {
  89. parent::init();
  90. // context->shop is set in the init() function, so we move the _category instanciation after that
  91. if (($id_category = Tools::getvalue('id_category')) && $this->action != 'select_delete')
  92. $this->_category = new Category($id_category);
  93. else
  94. if (Shop::isFeatureActive() && Shop::getContext() == Shop::CONTEXT_SHOP)
  95. $this->_category = new Category($this->context->shop->id_category);
  96. else if (count(Category::getCategoriesWithoutParent()) > 1 && Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) != 1)
  97. $this->_category = Category::getTopCategory();
  98. else
  99. $this->_category = new Category(Configuration::get('PS_HOME_CATEGORY'));
  100. // if we are not in a shop context, we remove the position column
  101. if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP)
  102. unset($this->fields_list['position']);
  103. // shop restriction : if category is not available for current shop, we redirect to the list from default category
  104. if (!$this->_category->isAssociatedToShop() && Shop::getContext() == Shop::CONTEXT_SHOP)
  105. {
  106. $this->redirect_after = self::$currentIndex.'&id_category='.(int)$this->context->shop->getCategory().'&token='.$this->token;
  107. $this->redirect();
  108. }
  109. }
  110. public function initContent()
  111. {
  112. if ($this->action == 'select_delete')
  113. $this->context->smarty->assign(array(
  114. 'delete_form' => true,
  115. 'url_delete' => htmlentities($_SERVER['REQUEST_URI']),
  116. 'boxes' => $this->boxes,
  117. ));
  118. parent::initContent();
  119. }
  120. public function setMedia()
  121. {
  122. parent::setMedia();
  123. $this->addJqueryUi('ui.widget');
  124. $this->addJqueryPlugin('tagify');
  125. }
  126. public function renderList()
  127. {
  128. $this->addRowAction('edit');
  129. $this->addRowAction('delete');
  130. $this->addRowAction('add');
  131. $this->addRowAction('view');
  132. $count_categories_without_parent = count(Category::getCategoriesWithoutParent());
  133. $is_multishop = Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE');
  134. $top_category = Category::getTopCategory();
  135. if (Tools::isSubmit('id_category'))
  136. $id_parent = $this->_category->id;
  137. else if (!$is_multishop && $count_categories_without_parent > 1)
  138. $id_parent = $top_category->id;
  139. else if ($is_multishop && $count_categories_without_parent == 1)
  140. $id_parent = Configuration::get('PS_HOME_CATEGORY');
  141. else if ($is_multishop && $count_categories_without_parent > 1 && Shop::getContext() != Shop::CONTEXT_SHOP)
  142. if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && count(Shop::getShops(true, null, true)) == 1)
  143. $id_parent = $this->context->shop->id_category;
  144. else
  145. $id_parent = $top_category->id;
  146. else
  147. $id_parent = $this->context->shop->id_category;
  148. $this->_select = 'sa.position position';
  149. $this->_filter .= ' AND `id_parent` = '.(int)$id_parent.' ';
  150. if (Shop::getContext() == Shop::CONTEXT_SHOP)
  151. $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = '.(int)$this->context->shop->id.') ';
  152. else
  153. $this->_join .= ' LEFT JOIN `'._DB_PREFIX_.'category_shop` sa ON (a.`id_category` = sa.`id_category` AND sa.id_shop = a.id_shop_default) ';
  154. // we add restriction for shop
  155. if (Shop::getContext() == Shop::CONTEXT_SHOP && $is_multishop)
  156. $this->_where = ' AND sa.`id_shop` = '.(int)Context::getContext()->shop->id;
  157. $categories_tree = $this->_category->getParentsCategories();
  158. if (empty($categories_tree)
  159. && ($this->_category->id_category != 1 || Tools::isSubmit('id_category'))
  160. && (Shop::getContext() == Shop::CONTEXT_SHOP && !$is_multishop && $count_categories_without_parent > 1))
  161. $categories_tree = array(array('name' => $this->_category->name[$this->context->language->id]));
  162. asort($categories_tree);
  163. $this->tpl_list_vars['categories_tree'] = $categories_tree;
  164. if (Tools::isSubmit('submitBulkdelete'.$this->table) || Tools::isSubmit('delete'.$this->table))
  165. {
  166. $category = new Category(Tools::getValue('id_category'));
  167. if ($category->is_root_category)
  168. $this->tpl_list_vars['need_delete_mode'] = false;
  169. else
  170. $this->tpl_list_vars['need_delete_mode'] = true;
  171. $this->tpl_list_vars['delete_category'] = true;
  172. $this->tpl_list_vars['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
  173. $this->tpl_list_vars['POST'] = $_POST;
  174. }
  175. return parent::renderList();
  176. }
  177. public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
  178. {
  179. $alias = 'sa';
  180. parent::getList($id_lang, $alias.'.position', $order_way, $start, $limit, Context::getContext()->shop->id);
  181. // Check each row to see if there are combinations and get the correct action in consequence
  182. $nb_items = count($this->_list);
  183. for ($i = 0; $i < $nb_items; $i++)
  184. {
  185. $item = &$this->_list[$i];
  186. $category_tree = Category::getChildren((int)$item['id_category'], $this->context->language->id);
  187. if (!count($category_tree))
  188. $this->addRowActionSkipList('view', array($item['id_category']));
  189. }
  190. }
  191. public function renderView()
  192. {
  193. $this->initToolbar();
  194. return $this->renderList();
  195. }
  196. public function initToolbar()
  197. {
  198. if (empty($this->display))
  199. {
  200. if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE'))
  201. $this->toolbar_btn['new-url'] = array(
  202. 'href' => self::$currentIndex.'&amp;add'.$this->table.'root&amp;token='.$this->token,
  203. 'desc' => $this->l('Add new root category')
  204. );
  205. $this->toolbar_btn['new'] = array(
  206. 'href' => self::$currentIndex.'&amp;add'.$this->table.'&amp;token='.$this->token,
  207. 'desc' => $this->l('Add new')
  208. );
  209. }
  210. // be able to edit the Home category
  211. if (count(Category::getCategoriesWithoutParent()) == 1 && !Tools::isSubmit('id_category')
  212. && ($this->display == 'view' || empty($this->display)))
  213. $this->toolbar_btn['edit'] = array(
  214. 'href' => self::$currentIndex.'&amp;update'.$this->table.'&amp;id_category='.(int)$this->_category->id.'&amp;token='.$this->token,
  215. 'desc' => $this->l('Edit')
  216. );
  217. if (Tools::getValue('id_category') && !Tools::isSubmit('updatecategory'))
  218. {
  219. $this->toolbar_btn['edit'] = array(
  220. 'href' => self::$currentIndex.'&amp;update'.$this->table.'&amp;id_category='.(int)Tools::getValue('id_category').'&amp;token='.$this->token,
  221. 'desc' => $this->l('Edit')
  222. );
  223. }
  224. if ($this->display == 'view')
  225. $this->toolbar_btn['new'] = array(
  226. 'href' => self::$currentIndex.'&amp;add'.$this->table.'&amp;id_parent='.(int)Tools::getValue('id_category').'&amp;token='.$this->token,
  227. 'desc' => $this->l('Add new')
  228. );
  229. parent::initToolbar();
  230. if ($this->_category->id == Category::getTopCategory()->id && isset($this->toolbar_btn['new']))
  231. unset($this->toolbar_btn['new']);
  232. // after adding a category
  233. if (empty($this->display))
  234. {
  235. $id_category = (Tools::isSubmit('id_category')) ? '&amp;id_parent='.(int)Tools::getValue('id_category') : '';
  236. $this->toolbar_btn['new'] = array(
  237. 'href' => self::$currentIndex.'&amp;add'.$this->table.'&amp;token='.$this->token.$id_category,
  238. 'desc' => $this->l('Add new')
  239. );
  240. if (Tools::isSubmit('id_category'))
  241. {
  242. $back = Tools::safeOutput(Tools::getValue('back', ''));
  243. if (empty($back))
  244. $back = self::$currentIndex.'&token='.$this->token;
  245. $this->toolbar_btn['back'] = array(
  246. 'href' => $back,
  247. 'desc' => $this->l('Back to list')
  248. );
  249. }
  250. }
  251. }
  252. public function initProcess()
  253. {
  254. if (Tools::isSubmit('add'.$this->table.'root'))
  255. {
  256. if ($this->tabAccess['add'])
  257. {
  258. $this->action = 'add'.$this->table.'root';
  259. $this->display = 'edit';
  260. }
  261. else
  262. $this->errors[] = Tools::displayError('You do not have permission to edit here.');
  263. }
  264. parent::initProcess();
  265. if ($this->action == 'delete' || $this->action == 'bulkdelete')
  266. if (Tools::getIsset('cancel'))
  267. Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories'));
  268. elseif (Tools::getValue('deleteMode') == 'link' || Tools::getValue('deleteMode') == 'linkanddisable' || Tools::getValue('deleteMode') == 'delete')
  269. $this->delete_mode = Tools::getValue('deleteMode');
  270. else
  271. $this->action = 'select_delete';
  272. }
  273. public function renderForm()
  274. {
  275. $this->initToolbar();
  276. $obj = $this->loadObject(true);
  277. $id_shop = Context::getContext()->shop->id;
  278. $selected_cat = array((isset($obj->id_parent) && $obj->isParentCategoryAvailable($id_shop))? (int)$obj->id_parent : (int)Tools::getValue('id_parent', Category::getRootCategory()->id));
  279. $unidentified = new Group(Configuration::get('PS_UNIDENTIFIED_GROUP'));
  280. $guest = new Group(Configuration::get('PS_GUEST_GROUP'));
  281. $default = new Group(Configuration::get('PS_CUSTOMER_GROUP'));
  282. $unidentified_group_information = sprintf($this->l('%s - All people without a validated customer account.'), '<b>'.$unidentified->name[$this->context->language->id].'</b>');
  283. $guest_group_information = sprintf($this->l('%s - Customer who placed an order with the Guest Checkout.'), '<b>'.$guest->name[$this->context->language->id].'</b>');
  284. $default_group_information = sprintf($this->l('%s - All people who have created an account on this site.'), '<b>'.$default->name[$this->context->language->id].'</b>');
  285. $root_category = Category::getRootCategory();
  286. $root_category = array('id_category' => $root_category->id_category, 'name' => $root_category->name);
  287. $this->fields_form = array(
  288. 'tinymce' => true,
  289. 'legend' => array(
  290. 'title' => $this->l('Category'),
  291. 'image' => '../img/admin/tab-categories.gif'
  292. ),
  293. 'input' => array(
  294. array(
  295. 'type' => 'text',
  296. 'label' => $this->l('Name:'),
  297. 'name' => 'name',
  298. 'lang' => true,
  299. 'size' => 48,
  300. 'required' => true,
  301. 'class' => 'copy2friendlyUrl',
  302. 'hint' => $this->l('Invalid characters:').' <>;=#{}',
  303. ),
  304. array(
  305. 'type' => 'radio',
  306. 'label' => $this->l('Displayed:'),
  307. 'name' => 'active',
  308. 'required' => false,
  309. 'class' => 't',
  310. 'is_bool' => true,
  311. 'values' => array(
  312. array(
  313. 'id' => 'active_on',
  314. 'value' => 1,
  315. 'label' => $this->l('Enabled')
  316. ),
  317. array(
  318. 'id' => 'active_off',
  319. 'value' => 0,
  320. 'label' => $this->l('Disabled')
  321. )
  322. )
  323. ),
  324. array(
  325. 'type' => 'categories',
  326. 'label' => $this->l('Parent category:'),
  327. 'name' => 'id_parent',
  328. 'values' => array(
  329. 'trads' => array(
  330. 'Root' => $root_category,
  331. 'selected' => $this->l('selected'),
  332. 'Collapse All' => $this->l('Collapse All'),
  333. 'Expand All' => $this->l('Expand All')
  334. ),
  335. 'selected_cat' => $selected_cat,
  336. 'input_name' => 'id_parent',
  337. 'use_radio' => true,
  338. 'use_search' => false,
  339. 'disabled_categories' => array(4),
  340. 'top_category' => Category::getTopCategory(),
  341. 'use_context' => true,
  342. )
  343. ),
  344. array(
  345. 'type' => 'radio',
  346. 'label' => $this->l('Root Category:'),
  347. 'name' => 'is_root_category',
  348. 'required' => false,
  349. 'is_bool' => true,
  350. 'class' => 't',
  351. 'values' => array(
  352. array(
  353. 'id' => 'is_root_on',
  354. 'value' => 1,
  355. 'label' => $this->l('Yes')
  356. ),
  357. array(
  358. 'id' => 'is_root_off',
  359. 'value' => 0,
  360. 'label' => $this->l('No')
  361. )
  362. )
  363. ),
  364. array(
  365. 'type' => 'textarea',
  366. 'label' => $this->l('Description:'),
  367. 'name' => 'description',
  368. 'lang' => true,
  369. 'rows' => 10,
  370. 'cols' => 100,
  371. 'hint' => $this->l('Invalid characters:').' <>;=#{}'
  372. ),
  373. array(
  374. 'type' => 'file',
  375. 'label' => $this->l('Image:'),
  376. 'name' => 'image',
  377. 'display_image' => true,
  378. 'desc' => $this->l('Upload category logo from your computer')
  379. ),
  380. array(
  381. 'type' => 'text',
  382. 'label' => $this->l('Meta title:'),
  383. 'name' => 'meta_title',
  384. 'lang' => true,
  385. 'hint' => $this->l('Forbidden characters:').' <>;=#{}'
  386. ),
  387. array(
  388. 'type' => 'text',
  389. 'label' => $this->l('Meta description:'),
  390. 'name' => 'meta_description',
  391. 'lang' => true,
  392. 'hint' => $this->l('Forbidden characters:').' <>;=#{}'
  393. ),
  394. array(
  395. 'type' => 'tags',
  396. 'label' => $this->l('Meta keywords:'),
  397. 'name' => 'meta_keywords',
  398. 'lang' => true,
  399. 'hint' => $this->l('Forbidden characters:').' <>;=#{}',
  400. 'desc' => $this->l('To add "tags" click in the field, write something, then press "Enter"')
  401. ),
  402. array(
  403. 'type' => 'text',
  404. 'label' => $this->l('Friendly URL:'),
  405. 'name' => 'link_rewrite',
  406. 'lang' => true,
  407. 'required' => true,
  408. 'hint' => $this->l('Only letters and the minus (-) character are allowed')
  409. ),
  410. array(
  411. 'type' => 'group',
  412. 'label' => $this->l('Group access:'),
  413. 'name' => 'groupBox',
  414. 'values' => Group::getGroups(Context::getContext()->language->id),
  415. 'info_introduction' => $this->l('You now have three default customer groups.'),
  416. 'unidentified' => $unidentified_group_information,
  417. 'guest' => $guest_group_information,
  418. 'customer' => $default_group_information,
  419. 'desc' => $this->l('Mark all customer groups you want to give access to this category')
  420. )
  421. ),
  422. 'submit' => array(
  423. 'title' => $this->l('Save'),
  424. 'class' => 'button'
  425. )
  426. );
  427. $this->tpl_form_vars['shared_category'] = Validate::isLoadedObject($obj) && $obj->hasMultishopEntries();
  428. $this->tpl_form_vars['PS_ALLOW_ACCENTED_CHARS_URL'] = (int)Configuration::get('PS_ALLOW_ACCENTED_CHARS_URL');
  429. if (Shop::isFeatureActive())
  430. $this->fields_form['input'][] = array(
  431. 'type' => 'shop',
  432. 'label' => $this->l('Shop association:'),
  433. 'name' => 'checkBoxShopAsso',
  434. );
  435. // remove category tree and radio button "is_root_category" if this category has the root category as parent category to avoid any conflict
  436. if ($this->_category->id_parent == Category::getTopCategory()->id && Tools::isSubmit('updatecategory'))
  437. foreach ($this->fields_form['input'] as $k => $input)
  438. if (in_array($input['name'], array('id_parent', 'is_root_category')))
  439. unset($this->fields_form['input'][$k]);
  440. if (Tools::isSubmit('add'.$this->table.'root'))
  441. unset($this->fields_form['input'][2],$this->fields_form['input'][3]);
  442. if (!($obj = $this->loadObject(true)))
  443. return;
  444. $image = ImageManager::thumbnail(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg', $this->table.'_'.(int)$obj->id.'.'.$this->imageType, 350, $this->imageType, true);
  445. $this->fields_value = array(
  446. 'image' => $image ? $image : false,
  447. 'size' => $image ? filesize(_PS_CAT_IMG_DIR_.'/'.$obj->id.'.jpg') / 1000 : false
  448. );
  449. // Added values of object Group
  450. $category_groups_ids = $obj->getGroups();
  451. $groups = Group::getGroups($this->context->language->id);
  452. // if empty $carrier_groups_ids : object creation : we set the default groups
  453. if (empty($category_groups_ids))
  454. {
  455. $preselected = array(Configuration::get('PS_UNIDENTIFIED_GROUP'), Configuration::get('PS_GUEST_GROUP'), Configuration::get('PS_CUSTOMER_GROUP'));
  456. $category_groups_ids = array_merge($category_groups_ids, $preselected);
  457. }
  458. foreach ($groups as $group)
  459. $this->fields_value['groupBox_'.$group['id_group']] = Tools::getValue('groupBox_'.$group['id_group'], (in_array($group['id_group'], $category_groups_ids)));
  460. return parent::renderForm();
  461. }
  462. public function postProcess()
  463. {
  464. if (!in_array($this->display, array('edit', 'add')))
  465. $this->multishop_context_group = false;
  466. if (Tools::isSubmit('forcedeleteImage') || (isset($_FILES['image']) && $_FILES['image']['size'] > 0))
  467. {
  468. $this->processForceDeleteImage();
  469. if (Tools::isSubmit('forcedeleteImage'))
  470. Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=7');
  471. }
  472. return parent::postProcess();
  473. }
  474. public function processForceDeleteImage()
  475. {
  476. $category = $this->loadObject(true);
  477. if (Validate::isLoadedObject($category))
  478. $category->deleteImage(true);
  479. }
  480. public function processAdd()
  481. {
  482. $id_category = (int)Tools::getValue('id_category');
  483. $id_parent = (int)Tools::getValue('id_parent');
  484. // if true, we are in a root category creation
  485. if (!$id_parent && !Tools::isSubmit('is_root_category'))
  486. $_POST['is_root_category'] = $_POST['level_depth'] = $_POST['id_parent'] = $id_parent = 1;
  487. if ($id_category)
  488. {
  489. if ($id_category != $id_parent)
  490. {
  491. if (!Category::checkBeforeMove($id_category, $id_parent))
  492. $this->errors[] = Tools::displayError($this->l('Category cannot be moved here'));
  493. }
  494. else
  495. $this->errors[] = Tools::displayError($this->l('Category cannot be parent of itself.'));
  496. }
  497. $object = parent::processAdd();
  498. //if we create a you root category you have to associate to a shop before to add sub categories in. So we redirect to AdminCategories listing
  499. if ($object && Tools::getValue('is_root_category'))
  500. Tools::redirectAdmin(self::$currentIndex.'&token='.Tools::getAdminTokenLite('AdminCategories').'&conf=3');
  501. return $object;
  502. }
  503. protected function setDeleteMode()
  504. {
  505. if ($this->delete_mode == 'link' || $this->delete_mode == 'linkanddisable')
  506. {
  507. $this->remove_products = false;
  508. if ($this->delete_mode == 'linkanddisable')
  509. $this->disable_products = true;
  510. }
  511. else if ($this->delete_mode != 'delete')
  512. $this->errors[] = Tools::displayError('Unknown delete mode:'.' '.$this->deleted);
  513. }
  514. protected function processBulkDelete()
  515. {
  516. if ($this->tabAccess['delete'] === '1')
  517. {
  518. $cats_ids = array();
  519. foreach (Tools::getValue($this->table.'Box') as $id_category)
  520. {
  521. $category = new Category((int)$id_category);
  522. if (!$category->isRootCategoryForAShop())
  523. $cats_ids[$category->id] = $category->id_parent;
  524. }
  525. if (parent::processBulkDelete())
  526. {
  527. $this->setDeleteMode();
  528. foreach ($cats_ids as $id => $id_parent)
  529. $this->processFatherlessProducts((int)$id_parent);
  530. return true;
  531. }
  532. else
  533. return false;
  534. }
  535. else
  536. $this->errors[] = Tools::displayError('You do not have permission to delete here.');
  537. }
  538. public function processDelete()
  539. {
  540. $category = $this->loadObject();
  541. if ($this->tabAccess['delete'] === '1')
  542. {
  543. if ($category->isRootCategoryForAShop())
  544. $this->errors[] = Tools::displayError('You cannot remove this category because a shop uses this category as a root category.');
  545. else if (parent::processDelete())
  546. {
  547. $this->setDeleteMode();
  548. $this->processFatherlessProducts((int)$category->id_parent);
  549. return true;
  550. }
  551. else
  552. return false;
  553. }
  554. else
  555. $this->errors[] = Tools::displayError('You do not have permission to delete here.');
  556. }
  557. public function processFatherlessProducts($id_parent)
  558. {
  559. /* Delete or link products which were not in others categories */
  560. $fatherless_products = Db::getInstance()->executeS('
  561. SELECT p.`id_product` FROM `'._DB_PREFIX_.'product` p
  562. '.Shop::addSqlAssociation('product', 'p').'
  563. WHERE p.`id_product` NOT IN (SELECT DISTINCT(cp.`id_product`) FROM `'._DB_PREFIX_.'category_product` cp)');
  564. foreach ($fatherless_products as $id_poor_product)
  565. {
  566. $poor_product = new Product((int)$id_poor_product);
  567. if (Validate::isLoadedObject($poor_product))
  568. {
  569. if ($this->remove_products || $id_parent == 0)
  570. $poor_product->delete();
  571. else
  572. {
  573. if ($this->disable_products)
  574. $poor_product->active = 0;
  575. $poor_product->id_category_default = (int)$id_parent;
  576. $poor_product->addToCategories((int)$id_parent);
  577. $poor_product->save();
  578. }
  579. }
  580. }
  581. }
  582. public function processPosition()
  583. {
  584. if ($this->tabAccess['edit'] !== '1')
  585. $this->errors[] = Tools::displayError('You do not have permission to edit here.');
  586. else if (!Validate::isLoadedObject($object = new Category((int)Tools::getValue($this->identifier, Tools::getValue('id_category_to_move', 1)))))
  587. $this->errors[] = Tools::displayError('An error occurred while updating status for object.').' <b>'.
  588. $this->table.'</b> '.Tools::displayError('(cannot load object)');
  589. if (!$object->updatePosition((int)Tools::getValue('way'), (int)Tools::getValue('position')))
  590. $this->errors[] = Tools::displayError('Failed to update the position.');
  591. else
  592. {
  593. $object->regenerateEntireNtree();
  594. Tools::redirectAdmin(self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.(($id_category = (int)Tools::getValue($this->identifier, Tools::getValue('id_category_parent', 1))) ? ('&'.$this->identifier.'='.$id_category) : '').'&token='.Tools::getAdminTokenLite('AdminCategories'));
  595. }
  596. }
  597. protected function postImage($id)
  598. {
  599. $ret = parent::postImage($id);
  600. if (($id_category = (int)Tools::getValue('id_category')) &&
  601. isset($_FILES) && count($_FILES) && $_FILES['image']['name'] != null &&
  602. file_exists(_PS_CAT_IMG_DIR_.$id_category.'.jpg'))
  603. {
  604. $images_types = ImageType::getImagesTypes('categories');
  605. foreach ($images_types as $k => $image_type)
  606. {
  607. ImageManager::resize(
  608. _PS_CAT_IMG_DIR_.$id_category.'.jpg',
  609. _PS_CAT_IMG_DIR_.$id_category.'-'.stripslashes($image_type['name']).'.jpg',
  610. (int)$image_type['width'], (int)$image_type['height']
  611. );
  612. }
  613. }
  614. return $ret;
  615. }
  616. /**
  617. * Allows to display the category description without HTML tags and slashes
  618. *
  619. * @return string
  620. */
  621. public static function getDescriptionClean($description)
  622. {
  623. return strip_tags(stripslashes($description));
  624. }
  625. public function ajaxProcessUpdatePositions()
  626. {
  627. $id_category_to_move = (int)(Tools::getValue('id_category_to_move'));
  628. $id_category_parent = (int)(Tools::getValue('id_category_parent'));
  629. $way = (int)(Tools::getValue('way'));
  630. $positions = Tools::getValue('category');
  631. if (is_array($positions))
  632. foreach ($positions as $key => $value)
  633. {
  634. $pos = explode('_', $value);
  635. if ((isset($pos[1]) && isset($pos[2])) && ($pos[1] == $id_category_parent && $pos[2] == $id_category_to_move))
  636. {
  637. $position = $key + 1;
  638. break;
  639. }
  640. }
  641. $category = new Category($id_category_to_move);
  642. if (Validate::isLoadedObject($category))
  643. {
  644. if (isset($position) && $category->updatePosition($way, $position))
  645. {
  646. Hook::exec('actionCategoryUpdate');
  647. die(true);
  648. }
  649. else
  650. die('{"hasError" : true, errors : "Can not update categories position"}');
  651. }
  652. else
  653. die('{"hasError" : true, "errors" : "This category can not be loaded"}');
  654. }
  655. }