diff --git a/admin-dev/ajax.php b/admin-dev/ajax.php index 40992b77f..fecfe8600 100644 --- a/admin-dev/ajax.php +++ b/admin-dev/ajax.php @@ -823,3 +823,35 @@ if (array_key_exists('ajaxAttributesPositions', $_POST)) } } } + +/* Modify group attribute position */ +if (array_key_exists('ajaxGroupsAttributesPositions', $_POST)) +{ + $way = (int)(Tools::getValue('way')); + $id_attribute_group = (int)(Tools::getValue('id_attribute_group')); + $positions = Tools::getValue('attribute_group'); + + $new_positions = array(); + foreach($positions as $k => $v) + if (count(explode('_', $v)) == 3) + $new_positions[] = $v; + + foreach ($new_positions AS $position => $value) + { + // pos[1] = id_attribute_group, pos[2] = old position + $pos = explode('_', $value); + + if (isset($pos[1]) AND (int)$pos[1] === $id_attribute_group) + { + if ($group_attribute = new AttributeGroup((int)$pos[1])) + if (isset($position) && $group_attribute->updatePosition($way, $position)) + echo "ok position $position for group attribute $pos[1]\r\n"; + else + echo '{"hasError" : true, "errors" : "Can not update group attribute '. $id_attribute_group . ' to position '.$position.' "}'; + else + echo '{"hasError" : true, "errors" : "This group attribute ('.$id_attribute_group.') can t be loaded"}'; + + break; + } + } +} diff --git a/admin-dev/tabs/AdminAttributes.php b/admin-dev/tabs/AdminAttributes.php index e034a3f2b..9734395a2 100644 --- a/admin-dev/tabs/AdminAttributes.php +++ b/admin-dev/tabs/AdminAttributes.php @@ -153,7 +153,7 @@ class AdminAttributes extends AdminTab else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); } - elseif (Tools::isSubmit('submitAddattribute')) + elseif (Tools::isSubmit('submitAdd'.$this->table)) { $id_attribute = (int)Tools::getValue('id_attribute'); // Adding last position to the attribute if not exist diff --git a/admin-dev/tabs/AdminAttributesGroups.php b/admin-dev/tabs/AdminAttributesGroups.php index 2541fc414..a79e39559 100644 --- a/admin-dev/tabs/AdminAttributesGroups.php +++ b/admin-dev/tabs/AdminAttributesGroups.php @@ -44,7 +44,8 @@ class AdminAttributesGroups extends AdminTab $this->fieldsDisplay = array( 'name' => array('title' => $this->l('Name'), 'width' => 140, 'filter_key' => 'b!name'), - 'attribute' => array('title' => $this->l('Attributes'), 'width' => 240, 'orderby' => false, 'search' => false)); + 'attribute' => array('title' => $this->l('Attributes'), 'width' => 240, 'orderby' => false, 'search' => false), + 'position' => array('title' => $this->l('Position'), 'width' => 40,'filter_key' => 'cp!position', 'align' => 'center', 'position' => 'position')); parent::__construct(); } @@ -71,7 +72,8 @@ class AdminAttributesGroups extends AdminTab return; $this->adminAttributes->tabAccess = Profile::getProfileAccess(Context::getContext()->employee->id_profile, $this->id); - $this->adminAttributes->postProcess($this->token); + if (Tools::isSubmit('submitAddattribute') || Tools::isSubmit('submitDelattribute')) + $this->adminAttributes->postProcess($this->token); if(Tools::getValue('submitDel'.$this->table)) { @@ -89,6 +91,26 @@ class AdminAttributesGroups extends AdminTab } else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); + // clean position after delete + AttributeGroup::cleanPositions(); + } + else if (Tools::isSubmit('submitAdd'.$this->table)) + { + $id_attribute_group = (int)Tools::getValue('id_attribute_group'); + // Adding last position to the attribute if not exist + if ($id_attribute_group <= 0) + { + $sql = 'SELECT `position`+1 + FROM `'._DB_PREFIX_.'attribute_group` + ORDER BY position DESC'; + // set the position of the new group attribute in $_POST for postProcess() method + $_POST['position'] = DB::getInstance()->getValue($sql); + } + // clean \n\r characters + foreach ($_POST as $key => $value) + if (preg_match('/^name_/Ui', $key)) + $_POST[$key] = str_replace ('\n', '', str_replace('\r', '', $value)); + parent::postProcess(); } else parent::postProcess(); @@ -129,11 +151,16 @@ class AdminAttributesGroups extends AdminTab '; $irow = 0; + if ($this->_list AND isset($this->fieldsDisplay['position'])) + { + $positions = array_map(create_function('$elem', 'return (int)$elem[\'position\'];'), $this->_list); + sort($positions); + } foreach ($this->_list AS $tr) { - $id = (int)($tr['id_'.$this->table]); + $id = (int)$tr['id_'.$this->table]; echo ' - + '.$tr['name'].' '; @@ -142,6 +169,27 @@ class AdminAttributesGroups extends AdminTab '; echo ' + '; + + if ($this->_orderBy == 'position' AND $this->_orderWay != 'DESC') + { + echo ' + '.$this->l('Down').''; + + echo ' + '.$this->l('Up').''; + } + else + echo (int)($tr['position'] + 1); + + echo ' + '.$this->l('Edit').'  diff --git a/classes/AdminTab.php b/classes/AdminTab.php index a8e218017..265f99396 100644 --- a/classes/AdminTab.php +++ b/classes/AdminTab.php @@ -149,7 +149,7 @@ abstract class AdminTabCore public $smarty; - protected $identifiersDnd = array('id_product' => 'id_product', 'id_category' => 'id_category_to_move','id_cms_category' => 'id_cms_category_to_move', 'id_cms' => 'id_cms', 'id_attribute' => 'id_attribute'); + protected $identifiersDnd = array('id_product' => 'id_product', 'id_category' => 'id_category_to_move','id_cms_category' => 'id_cms_category_to_move', 'id_cms' => 'id_cms', 'id_attribute' => 'id_attribute', 'id_attribute_group' => 'id_attribute_group'); /** @var bool Redirect or not ater a creation */ protected $_redirect = true; @@ -590,7 +590,11 @@ abstract class AdminTabCore Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.$token); } elseif ($object->delete()) + { + if(method_exists($object, 'cleanPositions')) + $object->cleanPositions(); Tools::redirectAdmin(self::$currentIndex.'&conf=1&token='.$token); + } $this->_errors[] = Tools::displayError('An error occurred during deletion.'); } } @@ -1601,7 +1605,7 @@ abstract class AdminTabCore $irow = 0; if ($this->_list AND isset($this->fieldsDisplay['position'])) { - $positions = array_map(create_function('$elem', 'return (int)($elem[\'position\']);'), $this->_list); + $positions = array_map(create_function('$elem', 'return (int)$elem[\'position\'];'), $this->_list); sort($positions); } if ($this->_list) diff --git a/classes/AttributeGroup.php b/classes/AttributeGroup.php index cc8769cda..5fd9ef768 100644 --- a/classes/AttributeGroup.php +++ b/classes/AttributeGroup.php @@ -30,6 +30,7 @@ class AttributeGroupCore extends ObjectModel /** @var string Name */ public $name; public $is_color_group; + public $position; /** @var string Public Name */ public $public_name; @@ -38,7 +39,7 @@ class AttributeGroupCore extends ObjectModel protected $fieldsValidate = array('is_color_group' => 'isBool'); protected $fieldsRequiredLang = array('name', 'public_name'); protected $fieldsSizeLang = array('name' => 64, 'public_name' => 64); - protected $fieldsValidateLang = array('name' => 'isGenericName', 'public_name' => 'isGenericName'); + protected $fieldsValidateLang = array('name' => 'isGenericName', 'public_name' => 'isGenericName', 'position' => 'isInt'); protected $table = 'attribute_group'; protected $identifier = 'id_attribute_group'; @@ -61,6 +62,7 @@ class AttributeGroupCore extends ObjectModel $this->validateFields(); $fields['is_color_group'] = (int)($this->is_color_group); + $fields['position'] = (int)($this->position); return $fields; } @@ -208,5 +210,83 @@ class AttributeGroupCore extends ObjectModel $result = Db::getInstance()->executeS('SELECT id_attribute AS id from `'._DB_PREFIX_.'attribute` WHERE id_attribute_group = '.(int)$this->id); return $result; } + + /** + * Move a group attribute + * @param boolean $way Up (1) or Down (0) + * @param integer $position + * @return boolean Update result + */ + public function updatePosition($way, $position) + { + if (!$res = Db::getInstance()->ExecuteS(' + SELECT ag.`position`, ag.`id_attribute_group` + FROM `'._DB_PREFIX_.'attribute_group` ag + WHERE ag.`id_attribute_group` = '.(int)Tools::getValue('id_attribute_group', 1).' + ORDER BY ag.`position` ASC' + )) + return false; + + foreach ($res AS $group_attribute) + if ((int)$group_attribute['id_attribute_group'] == (int)$this->id) + $movedGroupAttribute = $group_attribute; + + if (!isset($movedGroupAttribute) || !isset($position)) + return false; + + // < and > statements rather than BETWEEN operator + // since BETWEEN is treated differently according to databases + return (Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'attribute_group` + SET `position`= `position` '.($way ? '- 1' : '+ 1').' + WHERE `position` + '.($way + ? '> '.(int)$movedGroupAttribute['position'].' AND `position` <= '.(int)$position + : '< '.(int)$movedGroupAttribute['position'].' AND `position` >= '.(int)$position)) + AND Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'attribute_group` + SET `position` = '.(int)$position.' + WHERE `id_attribute_group`='.(int)$movedGroupAttribute['id_attribute_group'])); + } + + /** + * Reorder group attribute position + * Call it after deleting a group attribute. + * + * @return bool $return + */ + public static function cleanPositions() + { + $return = true; + + $sql = ' + SELECT * + FROM `'._DB_PREFIX_.'attribute_group` + ORDER BY `position`'; + $result = Db::getInstance()->ExecuteS($sql); + $sizeof = sizeof($result); + + for ($i = 0; $i < $sizeof; $i++) + $return = Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'attribute_group` + SET `position` = '.(int)$i.' + WHERE `id_attribute_group` = '.(int)$result[$i]['id_attribute_group']); + return $return; + } + + /** + * getHigherPosition + * + * Get the higher group attribute position + * + * @return integer $position + */ + public static function getHigherPosition() + { + $sql = 'SELECT `position` + FROM `'._DB_PREFIX_.'attribute_group` + ORDER BY position DESC'; + return ((DB::getInstance()->getValue($sql)!==false)) ? DB::getInstance()->getValue($sql) : -1; + } } diff --git a/classes/Product.php b/classes/Product.php index 88fb2ff12..b2c0b10ac 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -2328,7 +2328,7 @@ class ProductCore extends ObjectModel WHERE pa.`id_product` = '.(int)($this->id).' AND al.`id_lang` = '.(int)($id_lang).' AND agl.`id_lang` = '.(int)($id_lang).' - ORDER BY agl.`public_name`, a.`position` ASC'; + ORDER BY ag.`position` ASC, a.`position` ASC'; return Db::getInstance()->ExecuteS($sql); } diff --git a/install-dev/php/add_group_attribute_position.php b/install-dev/php/add_group_attribute_position.php new file mode 100644 index 000000000..585967736 --- /dev/null +++ b/install-dev/php/add_group_attribute_position.php @@ -0,0 +1,42 @@ + +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision: 6844 $ +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +function add_group_attribute_position() +{ + $groups = Db::getInstance()->ExecuteS(' + SELECT * + FROM `'._DB_PREFIX_.'attribute_group`'); + $i = 0; + if (sizeof($groups) && is_array($groups)) + foreach ($groups as $group) + { + Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'attribute_group` + SET `position` = '.$i++.' + WHERE `id_attribute_group` = '.(int)$group['id_attribute_group']); + } +} \ No newline at end of file diff --git a/install-dev/sql/db.sql b/install-dev/sql/db.sql index 6a6ae5904..9940968f5 100644 --- a/install-dev/sql/db.sql +++ b/install-dev/sql/db.sql @@ -91,6 +91,7 @@ CREATE TABLE `PREFIX_attribute` ( CREATE TABLE `PREFIX_attribute_group` ( `id_attribute_group` int(10) unsigned NOT NULL auto_increment, `is_color_group` tinyint(1) NOT NULL default '0', + `position` int(10) unsigned NOT NULL default '0', PRIMARY KEY (`id_attribute_group`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; diff --git a/install-dev/sql/upgrade/1.5.0.1.sql b/install-dev/sql/upgrade/1.5.0.1.sql index 0b8b97cdd..1060fa0b8 100644 --- a/install-dev/sql/upgrade/1.5.0.1.sql +++ b/install-dev/sql/upgrade/1.5.0.1.sql @@ -146,4 +146,6 @@ ALTER TABLE `PREFIX_attribute` ADD `position` INT( 10 ) UNSIGNED NOT NULL DEFAUL ALTER TABLE `PREFIX_product_download` CHANGE `date_deposit` `date_add` DATETIME NOT NULL ; ALTER TABLE `PREFIX_product_download` CHANGE `physically_filename` `filename` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL; ALTER TABLE `PREFIX_product_download` ADD `id_product_attribute` INT( 10 ) UNSIGNED NOT NULL AFTER `id_product` , ADD INDEX ( `id_product_attribute` ); -ALTER TABLE `PREFIX_product_download` ADD `is_shareable` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `active` \ No newline at end of file +ALTER TABLE `PREFIX_product_download` ADD `is_shareable` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0' AFTER `active`; + +ALTER TABLE `PREFIX_attribute_group` ADD `position` INT( 10 ) UNSIGNED NOT NULL DEFAULT '0'; diff --git a/js/admin-dnd.js b/js/admin-dnd.js index 6d21b7454..db967d577 100644 --- a/js/admin-dnd.js +++ b/js/admin-dnd.js @@ -91,7 +91,7 @@ $(document).ready(function() { token: token }; } - if (table.id.indexOf('attribute') != -1) { + if (table.id.indexOf('attribute') != -1 && table.id != 'attribute_group') { params = { ajaxAttributesPositions: true, id_attribute_group: ids[1], @@ -101,6 +101,14 @@ $(document).ready(function() { }; } + if (table.id == 'attribute_group') { + params = { + ajaxGroupsAttributesPositions: true, + id_attribute_group: ids[1], + way: way, + token: token + } + } $.ajax({ type: 'POST', @@ -139,7 +147,7 @@ $(document).ready(function() { } else { - if (table.id == 'product' || table.id.indexOf('attribute') != -1) + if (table.id == 'product' || table.id.indexOf('attribute') != -1 || table.id == 'attribute_group') { var reg = /_[0-9][0-9]*$/g; } @@ -149,30 +157,27 @@ $(document).ready(function() { } var up_reg = new RegExp('position=[-]?[0-9]+&'); - - tableDrag.find('tbody tr').each(function(i) { + tableDrag.children('tbody').children('tr').each(function(i) { $(this).attr('id', $(this).attr('id').replace(reg, '_' + i)); - - // Update link position + // Update link position // Up links - $(this).find('td.dragHandle a:odd').attr('href', $(this).find('td.dragHandle a:odd').attr('href').replace(up_reg, 'position='+ (i - 1) +'&')); + $(this).children('td.dragHandle a:odd').attr('href', $(this).children('td.dragHandle a:odd').attr('href').replace(up_reg, 'position='+ (i - 1) +'&')); // Down links - $(this).find('td.dragHandle a:even').attr('href', $(this).find('td.dragHandle a:even').attr('href').replace(up_reg, 'position='+ (i + 1) +'&')); + $(this).children('td.dragHandle a:even').attr('href', $(this).children('td.dragHandle a:even').attr('href').replace(up_reg, 'position='+ (i + 1) +'&')); }); - tableDrag.find('tr').not('.nodrag').removeClass('alt_row').removeClass('not_alt_row'); - tableDrag.find('tr:not(".nodrag"):odd').addClass('alt_row'); - tableDrag.find('tr:not(".nodrag"):even').addClass('not_alt_row'); - tableDrag.find('tr td.dragHandle a:hidden').show(); - + tableDrag.children('tbody').children('tr').not('.nodrag').removeClass('alt_row').removeClass('not_alt_row'); + tableDrag.children('tbody').children('tr:not(".nodrag"):odd').addClass('alt_row'); + tableDrag.children('tbody').children('tr:not(".nodrag"):even').addClass('not_alt_row'); + tableDrag.children('tbody').children('tr').children('td.dragHandle').children('a:hidden').show(); if (alternate) { - tableDrag.find('tr td.dragHandle:first a:odd').hide(); - tableDrag.find('tr td.dragHandle:last a:even').hide(); + tableDrag.children('tbody').children('tr').children('td.dragHandle:first').children('a:odd').hide(); + tableDrag.children('tbody').children('tr').children('td.dragHandle:last').children('a:even').hide(); } else { - tableDrag.find('tr td.dragHandle:first a:even').hide(); - tableDrag.find('tr td.dragHandle:last a:odd').hide(); + tableDrag.children('tbody').children('tr').children('td.dragHandle:first').children('a:even').hide(); + tableDrag.children('tbody').children('tr').children('td.dragHandle:last').children('a:odd').hide(); } } }