[*] BO : Features are now sortable.

git-svn-id: http://dev.prestashop.com/svn/v1/branches/1.5.x@8751 b9a71923-0436-4b27-9f14-aed3839534dd
This commit is contained in:
vChabot
2011-09-23 15:45:40 +00:00
parent 4f5b1dd933
commit 83fc0977c9
12 changed files with 250 additions and 12 deletions
+32
View File
@@ -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;
}
}
}
+66 -4
View File
@@ -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 '<tr><td class="center" colspan="'.sizeof($this->_list).'">'.$this->l('No features found.').'</td></tr>';
$irow = 0;
echo '
<script type="text/javascript" src="../js/jquery/jquery.tablednd_0_5.js"></script>
<script type="text/javascript">
var token = \''.$this->token.'\';
var come_from = \''.$this->table.'\';
var alternate = \''.($this->_orderWay == 'DESC' ? '1' : '0' ).'\';
</script>
<script type="text/javascript" src="../js/admin-dnd.js"></script>
';
$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'.($irow++ % 2 ? ' class="alt_row"' : '').'>
<tr'.($irow++ % 2 ? ' class="alt_row"' : '').' id="tr_'.$tr['id_feature'].'_'.$tr['position'].'">
<td style="vertical-align: top; padding: 4px 0 4px 0" class="center"><input type="checkbox" name="'.$this->table.'Box[]" value="'.$id.'" class="noborder" /></td>
<td style="width: 140px; vertical-align: top; padding: 4px 0 4px 0; cursor: pointer" onclick="$(\'#features_values_'.$id.'\').slideToggle();">'.$tr['name'].'</td>
<td style="vertical-align: top; padding: 4px 0 4px 0; width: 340px">
@@ -118,6 +135,27 @@ class AdminFeatures extends AdminTab
</div>
</td>';
echo '
<td style="width: 140px; vertical-align: top; padding: 4px 0 4px 0; cursor: pointer" class="dragHandle">';
if ($this->_orderBy == 'position' AND $this->_orderWay != 'DESC')
{
echo '<a'.(!($tr['position'] != $positions[sizeof($positions) - 1]) ? ' style="display: none;"' : '').' href="'.self::$currentIndex.
'&'.$this->identifiersDnd[$this->identifier].'='.$id.'
&way=1&position='.((int)$tr['position'] + 1).'&token='.$this->token.'">
<img src="../img/admin/'.($this->_orderWay == 'ASC' ? 'down' : 'up').'.gif"
alt="'.$this->l('Down').'" title="'.$this->l('Down').'" /></a>';
echo '<a'.(!($tr['position'] != $positions[0]) ? ' style="display: none;"' : '').' href="'.self::$currentIndex.
'&'.$this->identifiersDnd[$this->identifier].'='.$id.'
&way=0&position='.((int)$tr['position'] - 1).'&token='.$this->token.'">
<img src="../img/admin/'.($this->_orderWay == 'ASC' ? 'up' : 'down').'.gif"
alt="'.$this->l('Up').'" title="'.$this->l('Up').'" /></a>';
}
else
echo (int)($tr['position'] + 1);
echo '
<td style="vertical-align: top; padding: 4px 0 4px 0" class="center">
<a href="'.self::$currentIndex.'&id_'.$this->table.'='.$id.'&update'.$this->table.'&token='.$this->token.'">
@@ -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();
}
+2 -1
View File
@@ -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(
+2 -1
View File
@@ -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.').' <b>'.$this->table.' ('.Db::getInstance()->getMsgError().')</b>';
elseif (($_POST[$this->identifier] = $object->id /* voluntary */) AND $this->postImage($object->id) AND !sizeof($this->_errors) AND $this->_redirect)
+86 -2
View File
@@ -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;
}
}
+3 -1
View File
@@ -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];
}
+42
View File
@@ -0,0 +1,42 @@
<?php
/*
* 2007-2011 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @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']);
}
}
+1
View File
@@ -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;
+1 -1
View File
@@ -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);
+4
View File
@@ -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(); */;
+10 -1
View File
@@ -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;
}
+1 -1
View File
@@ -44,7 +44,7 @@
</div>
</fieldset>
</form>
<form action="#" method="post" id="new_account_form" class="std">
<form action="#" method="post" id="new_account_form" class="std" autocomplete="on" autofill="on">
<fieldset>
<h3 id="new_account_title">{l s='New Customer'}</h3>
<div id="opc_account_choice">