diff --git a/admin-dev/ajax.php b/admin-dev/ajax.php index ee25cf7b3..bc742000a 100644 --- a/admin-dev/ajax.php +++ b/admin-dev/ajax.php @@ -868,3 +868,35 @@ if (array_key_exists('ajaxGroupsAttributesPositions', $_POST)) } } } + +/* Modify feature position */ +if (array_key_exists('ajaxFeaturesPositions', $_POST)) +{ + $way = (int)(Tools::getValue('way')); + $id_feature = (int)(Tools::getValue('id_feature')); + $positions = Tools::getValue('feature'); + + $new_positions = array(); + foreach($positions as $k => $v) + if (!empty($v)) + $new_positions[] = $v; + + foreach ($new_positions AS $position => $value) + { + // pos[1] = id_feature, pos[2] = old position + $pos = explode('_', $value); + + if (isset($pos[1]) AND (int)$pos[1] === $id_feature) + { + if ($feature = new Feature((int)$pos[1])) + if (isset($position) && $feature->updatePosition($way, $position)) + echo "ok position $position for feature $pos[1]\r\n"; + else + echo '{"hasError" : true, "errors" : "Can not update feature '. $id_attribute_group . ' to position '.$position.' "}'; + else + echo '{"hasError" : true, "errors" : "This feature ('.$id_attribute_group.') can t be loaded"}'; + + break; + } + } +} diff --git a/admin-dev/tabs/AdminFeatures.php b/admin-dev/tabs/AdminFeatures.php index 9d6259542..b7bdd213a 100644 --- a/admin-dev/tabs/AdminFeatures.php +++ b/admin-dev/tabs/AdminFeatures.php @@ -40,7 +40,8 @@ class AdminFeatures extends AdminTab $this->fieldsDisplay = array( 'name' => array('title' => $this->l('Name'), 'width' => 128, 'filter_key' => 'b!name'), - 'value' => array('title' => $this->l('Values'), 'width' => 255, 'orderby' => false, 'search' => false)); + 'value' => array('title' => $this->l('Values'), 'width' => 255, 'orderby' => false, 'search' => false), + 'position' => array('title' => $this->l('Position'), 'width' => 40,'filter_key' => 'cp!position', 'align' => 'center', 'position' => 'position')); parent::__construct(); } @@ -76,12 +77,28 @@ class AdminFeatures extends AdminTab if (!sizeof($this->_list)) echo ''.$this->l('No features found.').''; - $irow = 0; + + echo ' + + + + '; + + $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]); echo ' - + '.$tr['name'].' @@ -118,6 +135,27 @@ class AdminFeatures 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 ' @@ -194,7 +232,9 @@ class AdminFeatures extends AdminTab return ; $this->adminFeaturesValues->tabAccess = Profile::getProfileAccess($this->context->employee->id_profile, $this->id); - $this->adminFeaturesValues->postProcess($this->token); + + if (Tools::isSubmit('submitAddfeature_value') || Tools::isSubmit('submitDelfeature_value')) + $this->adminFeaturesValues->postProcess($this->token); Module::hookExec('postProcessFeature', array('errors' => &$this->_errors)); // send _errors as reference to allow postProcessFeature to stop saving process @@ -216,6 +256,28 @@ class AdminFeatures extends AdminTab else $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); } + else if (Tools::isSubmit('submitAdd'.$this->table)) + { + if ($this->tabAccess['add'] === '1') + { + $id_feature = (int)Tools::getValue('id_feature'); + // Adding last position to the feature if not exist + if ($id_feature <= 0) + { + $sql = 'SELECT `position`+1 + FROM `'._DB_PREFIX_.'feature` + ORDER BY position DESC'; + // set the position of the new feature 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(); } diff --git a/admin-dev/tabs/AdminImport.php b/admin-dev/tabs/AdminImport.php index 51e11b0a7..a5237a28d 100644 --- a/admin-dev/tabs/AdminImport.php +++ b/admin-dev/tabs/AdminImport.php @@ -179,7 +179,8 @@ class AdminImport extends AdminTab 'label' => $this->l('Delete existing images (0 = no, 1 = yes)'), 'help' => $this->l('If you do not specify this column and you specify the column images, all images of the product will be replaced by those specified in the import file') ), - 'feature' => array('label' => $this->l('Feature')), + 'feature' => array('label' => $this->l('Feature(Name:Position)'), + 'help' => $this->l('Position of the feature.')), 'online_only' => array('label' => $this->l('Only available online')), 'condition' => array('label' => $this->l('Condition')), 'shop' => array( diff --git a/classes/AdminTab.php b/classes/AdminTab.php index e45ce74c8..1ce618ec9 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', 'id_attribute_group' => 'id_attribute_group'); + 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', 'id_feature' => 'id_feature'); /** @var bool Redirect or not ater a creation */ protected $_redirect = true; @@ -756,6 +756,7 @@ abstract class AdminTabCore { $object = new $this->className(); $this->copyFromPost($object, $this->table); +// d($object); if (!$object->add()) $this->_errors[] = Tools::displayError('An error occurred while creating object.').' '.$this->table.' ('.Db::getInstance()->getMsgError().')'; elseif (($_POST[$this->identifier] = $object->id /* voluntary */) AND $this->postImage($object->id) AND !sizeof($this->_errors) AND $this->_redirect) diff --git a/classes/Feature.php b/classes/Feature.php index cec22af96..cb3ae2d38 100644 --- a/classes/Feature.php +++ b/classes/Feature.php @@ -29,6 +29,7 @@ class FeatureCore extends ObjectModel { /** @var string Name */ public $name; + public $position; protected $fieldsRequiredLang = array('name'); protected $fieldsSizeLang = array('name' => 128); @@ -45,7 +46,7 @@ class FeatureCore extends ObjectModel public function getFields() { - return array('id_feature' => NULL); + return array('id_feature' => NULL, 'position' => (int)$this->position); } /** @@ -89,7 +90,7 @@ class FeatureCore extends ObjectModel SELECT * FROM `'._DB_PREFIX_.'feature` f LEFT JOIN `'._DB_PREFIX_.'feature_lang` fl ON (f.`id_feature` = fl.`id_feature` AND fl.`id_lang` = '.(int)($id_lang).') - ORDER BY fl.`name` ASC'); + ORDER BY f.`position` ASC'); } /** @@ -123,9 +124,14 @@ class FeatureCore extends ObjectModel Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'feature_value` WHERE `id_feature` = '.(int)($this->id)); /* Also delete related products */ Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'feature_product` WHERE `id_feature` = '.(int)($this->id)); + $return = parent::delete(); if($return) Module::hookExec('afterDeleteFeature', array('id_feature' => $this->id)); + + /* Reinitializing position */ + $this->cleanPositions(); + return $return; } @@ -225,5 +231,83 @@ class FeatureCore extends ObjectModel { return Configuration::get('PS_FEATURE_FEATURE_ACTIVE'); } + + /** + * Move a feature + * @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 `position`, `id_feature` + FROM `'._DB_PREFIX_.'feature` + WHERE `id_feature` = '.(int)Tools::getValue('id_feature', 1).' + ORDER BY `position` ASC' + )) + return false; + + foreach ($res AS $feature) + if ((int)$feature['id_feature'] == (int)$this->id) + $movedFeature = $feature; + + if (!isset($movedFeature) || !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_.'feature` + SET `position`= `position` '.($way ? '- 1' : '+ 1').' + WHERE `position` + '.($way + ? '> '.(int)$movedFeature['position'].' AND `position` <= '.(int)$position + : '< '.(int)$movedFeature['position'].' AND `position` >= '.(int)$position)) + AND Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'feature` + SET `position` = '.(int)$position.' + WHERE `id_feature`='.(int)$movedFeature['id_feature'])); + } + + /** + * Reorder feature position + * Call it after deleting a feature. + * + * @return bool $return + */ + public static function cleanPositions() + { + $return = true; + + $sql = ' + SELECT * + FROM `'._DB_PREFIX_.'feature` + ORDER BY `position`'; + $result = Db::getInstance()->ExecuteS($sql); + $sizeof = sizeof($result); + + for ($i = 0; $i < $sizeof; $i++) + $return = Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'feature` + SET `position` = '.(int)$i.' + WHERE `id_feature` = '.(int)$result[$i]['id_feature']); + return $return; + } + + /** + * getHigherPosition + * + * Get the higher feature position + * + * @return integer $position + */ + public static function getHigherPosition() + { + $sql = 'SELECT `position` + FROM `'._DB_PREFIX_.'feature` + 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 28da3c03a..c311aef49 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -2904,7 +2904,9 @@ class ProductCore extends ObjectModel FROM '._DB_PREFIX_.'feature_product pf LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fvl.id_feature_value = pf.id_feature_value AND fvl.id_lang = '.(int)$id_lang.') - WHERE pf.id_product = '.(int)$id_product); + LEFT JOIN '._DB_PREFIX_.'feature f ON (f.id_feature = pf.id_feature AND fl.id_lang = '.(int)$id_lang.') + WHERE pf.id_product = '.(int)$id_product.' + ORDER BY f.position ASC'); } return self::$_frontFeaturesCache[$id_product.'-'.$id_lang]; } diff --git a/install-dev/php/add_feature_position.php b/install-dev/php/add_feature_position.php new file mode 100644 index 000000000..824185943 --- /dev/null +++ b/install-dev/php/add_feature_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_feature_position() +{ + $features = Db::getInstance()->ExecuteS(' + SELECT `id_feature` + FROM `'._DB_PREFIX_.'feature`'); + $i = 0; + if (sizeof($features) && is_array($features)) + foreach ($features as $feature) + { + Db::getInstance()->Execute(' + UPDATE `'._DB_PREFIX_.'feature` + SET `position` = '.$i++.' + WHERE `id_feature` = '.(int)$feature['id_feature']); + } +} \ No newline at end of file diff --git a/install-dev/sql/db.sql b/install-dev/sql/db.sql index d67ec85c9..4840df4cd 100644 --- a/install-dev/sql/db.sql +++ b/install-dev/sql/db.sql @@ -641,6 +641,7 @@ CREATE TABLE `PREFIX_employee` ( CREATE TABLE `PREFIX_feature` ( `id_feature` int(10) unsigned NOT NULL auto_increment, + `position` int(10) unsigned NOT NULL default '0', PRIMARY KEY (`id_feature`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; diff --git a/install-dev/sql/db_settings_extends.sql b/install-dev/sql/db_settings_extends.sql index 2e8de2a5a..8d25424df 100644 --- a/install-dev/sql/db_settings_extends.sql +++ b/install-dev/sql/db_settings_extends.sql @@ -371,7 +371,7 @@ INSERT INTO `PREFIX_product_attribute_combination` (`id_attribute`, `id_product_ (4, 26),(5, 10),(5, 35),(5, 36),(6, 8),(6, 39),(6, 40),(7, 33),(7, 34),(8, 13),(8, 15),(9, 12),(9, 14),(10, 12),(10, 13),(11, 14),(11, 15),(14, 31),(14, 32),(15, 19), (15, 26),(15, 28),(15, 30),(15, 32),(15, 34),(15, 36),(15, 40),(15, 42),(16, 22),(16, 25),(16, 27),(16, 29),(16, 31),(16, 33),(16, 35),(16, 39),(16, 41),(17, 23),(18, 41),(18, 42),(19, 27),(19, 28); -INSERT INTO `PREFIX_feature` (`id_feature`) VALUES (1), (2), (3), (4), (5); +INSERT INTO `PREFIX_feature` (`id_feature`, `position`) VALUES (1, 0), (2, 1), (3, 2), (4, 3), (5, 4); INSERT INTO `PREFIX_feature_group_shop` (`id_feature`, `id_group_shop`) (SELECT `id_feature`, 1 FROM PREFIX_feature); diff --git a/install-dev/sql/upgrade/1.5.0.1.sql b/install-dev/sql/upgrade/1.5.0.1.sql index b13a1afb6..3074f795f 100644 --- a/install-dev/sql/upgrade/1.5.0.1.sql +++ b/install-dev/sql/upgrade/1.5.0.1.sql @@ -151,3 +151,7 @@ ALTER TABLE `PREFIX_product_download` ADD `is_shareable` TINYINT( 1 ) UNSIGNED N ALTER TABLE `PREFIX_attribute_group` ADD `position` INT( 10 ) UNSIGNED NOT NULL DEFAULT '0'; /* PHP:add_group_attribute_position(); */; + +ALTER TABLE `PREFIX_feature` ADD `position` INT( 10 ) UNSIGNED NOT NULL DEFAULT '0'; + +/* PHP:add_feature_position(); */; diff --git a/js/admin-dnd.js b/js/admin-dnd.js index db967d577..314ea79ac 100644 --- a/js/admin-dnd.js +++ b/js/admin-dnd.js @@ -110,6 +110,15 @@ $(document).ready(function() { } } + if (table.id == 'feature') { + params = { + ajaxFeaturesPositions: true, + id_feature : ids[1], + way: way, + token: token + } + } + $.ajax({ type: 'POST', async: false, @@ -147,7 +156,7 @@ $(document).ready(function() { } else { - if (table.id == 'product' || table.id.indexOf('attribute') != -1 || table.id == 'attribute_group') + if (table.id == 'product' || table.id.indexOf('attribute') != -1 || table.id == 'attribute_group' || table.id == 'feature') { var reg = /_[0-9][0-9]*$/g; } diff --git a/themes/prestashop/order-opc-new-account.tpl b/themes/prestashop/order-opc-new-account.tpl index 2170c75ff..5c77c9753 100644 --- a/themes/prestashop/order-opc-new-account.tpl +++ b/themes/prestashop/order-opc-new-account.tpl @@ -44,7 +44,7 @@ -
+

{l s='New Customer'}