diff --git a/admin-dev/themes/template/address.tpl b/admin-dev/themes/template/address.tpl new file mode 100644 index 000000000..a2eadb41e --- /dev/null +++ b/admin-dev/themes/template/address.tpl @@ -0,0 +1,27 @@ +{* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 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/afl-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 +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{$list} \ No newline at end of file diff --git a/admin-dev/themes/template/content.tpl b/admin-dev/themes/template/content.tpl index d9f1e44a0..0c090e15d 100644 --- a/admin-dev/themes/template/content.tpl +++ b/admin-dev/themes/template/content.tpl @@ -1 +1,27 @@ +{* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 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/afl-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 +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + {$content} diff --git a/admin-dev/themes/template/list_content.tpl b/admin-dev/themes/template/list_content.tpl new file mode 100644 index 000000000..7cbb44717 --- /dev/null +++ b/admin-dev/themes/template/list_content.tpl @@ -0,0 +1,110 @@ +{* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 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/afl-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 +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{foreach $list AS $index => $tr} + + + {if $bulk_action} + + {/if} + + {foreach $fields_display AS $key => $params} + {if isset($params.prefix)}$params.prefix{/if} + {else} + > + {/if} + {if isset($params.active)} + {$tr.$key} + {elseif isset($params.activeVisu)} + {if $tr.$key}{l s='Enabled'}{else}{l s='Disabled'}{/if} + {elseif isset($params.position)} + {if $orderBy == 'position' && $orderWay != 'DESC'} + + {l s='Down'} + + + {l s='Up'}'; + {else} + {$tr.$key.position} + 1 + {/if} + {elseif isset($params.image)} + {$tr.$key} + {*{elseif (isset($params.icon) && (isset($params['icon'][$tr[$key]]) || isset($params['icon']['default'])))} + $tr.$key*} + {elseif isset($params.price)} + {$tr.$key} + {elseif isset($params.float)} + {$tr.$key} + {elseif isset($params.type) && $params.type == 'date'} + {$tr.$key} + {elseif isset($params.type) && $params.type == 'datetime'} + {$tr.$key} + {elseif isset($tr.$key)} + {$tr.$key} + {else} + -- + {/if} + {if isset($params.suffix)}$params.suffix{/if} + + {/foreach} + + {if $shop_link_type} + $tr.shop_short_name + {/if} + {if $has_actions} + + {if isset($tr.view)} + {$tr.view} + {/if} + {if isset($tr.edit)} + {$tr.edit} + {/if} + {if isset($tr.delete)} + {$tr.delete} + {/if} + {if isset($tr.duplicate)} + {$tr.duplicate} + {/if} + + {/if} + +{/foreach} \ No newline at end of file diff --git a/admin-dev/themes/template/list_footer.tpl b/admin-dev/themes/template/list_footer.tpl new file mode 100644 index 000000000..a96c1f34f --- /dev/null +++ b/admin-dev/themes/template/list_footer.tpl @@ -0,0 +1,41 @@ +{* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 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/afl-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 +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + +{* +if ($this->delete) +

+{/if} +*} + + + + + +{* +if (isset($this->_includeTab) AND sizeof($this->_includeTab)) + echo '

'; +*} \ No newline at end of file diff --git a/admin-dev/themes/template/list_header.tpl b/admin-dev/themes/template/list_header.tpl new file mode 100644 index 000000000..18f5242ce --- /dev/null +++ b/admin-dev/themes/template/list_header.tpl @@ -0,0 +1,170 @@ +{* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 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/afl-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 +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + + +{* Display column names and arrows for ordering (ASC, DESC) *} +{if $is_order_position} + + + +{/if} + + +  +
+ + + + + + +
+ + {if $page > 1} +   + + {/if} + {l s='Page '}{$page} / {$total_pages} + {if $page < $total_pages} +   + + {/if} + | {l s='Display'} + + / {$list_total} {l s='result(s)'} + + + + + + +
+ identifier,$this->identifiersDnd) ? ' id="'.(((int)(Tools::getValue($this->identifiersDnd[$this->identifier], 1))) ? substr($this->identifier,3,strlen($this->identifier)) : '').'"' : '' )*} + class="table" + {*(array_key_exists($this->identifier,$this->identifiersDnd) AND ($this->_orderBy != 'position 'AND $this->_orderWay != 'DESC')) ? ' tableDnD' : '' ).'"*} + cellpadding="0" cellspacing="0"> + + + + {foreach $fields_display AS $key => $params} + + {/foreach} + + {if $shop_link_type} + + {/if} + {if $has_actions} + + {/if} + + + + + {* Filters (input, select, date or bool) *} + {foreach $fields_display AS $key => $params} + + {/foreach} + + {if $shop_link_type} + + {/if} + {if $has_actions} + + {/if} + + diff --git a/classes/AdminController.php b/classes/AdminController.php index fb5aed6f1..d5898b1c5 100644 --- a/classes/AdminController.php +++ b/classes/AdminController.php @@ -3,6 +3,7 @@ class AdminControllerCore extends Controller { public $path; + public static $currentIndex; public $content; public $warnings; @@ -37,6 +38,50 @@ class AdminControllerCore extends Controller /** @var string Default ORDER BY clause when $_orderBy is not defined */ protected $_defaultOrderBy = false; + /** @var array Errors displayed after post processing */ + public $_errors = array(); + + protected $list_display; + + protected $shopLink; + + /** @var array Cache for query results */ + protected $_list = array(); + + /** @var integer Number of results in list */ + protected $_listTotal = 0; + + /** @var array WHERE clause determined by filter fields */ + protected $_filter; + + /** @var array Temporary SQL table WHERE clause determinated by filter fields */ + protected $_tmpTableFilter = ''; + + /** @var array Number of results in list per page (used in select field) */ + protected $_pagination = array(20, 50, 100, 300); + + /** @var string ORDER BY clause determined by field/arrows in list header */ + protected $_orderBy; + + /** @var string Order way (ASC, DESC) determined by arrows in list header */ + protected $_orderWay; + + protected $bulk_action; + + protected $is_cms = false; + + protected $is_dnd_identifier = false; + + 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 $view; + protected $edit; + protected $delete; + protected $duplicate; + protected $noLink; + protected $specificConfirmDelete; + protected $colorOnBackground; + + public function __construct() { parent::__construct(); @@ -50,7 +95,6 @@ class AdminControllerCore extends Controller $this->template = $tpl_name; } - $this->id = Tab::getIdFromClassName($this->className); $this->_conf = array( 1 => $this->l('Deletion successful'), 2 => $this->l('Selection successfully deleted'), 3 => $this->l('Creation successful'), 4 => $this->l('Update successful'), @@ -69,15 +113,16 @@ class AdminControllerCore extends Controller if (!$this->identifier) $this->identifier = 'id_'.$this->table; if (!$this->_defaultOrderBy) $this->_defaultOrderBy = $this->identifier; $className = get_class($this); - - if ($className == 'AdminCategories' OR $className == 'AdminProducts') - $className = 'AdminCatalog'; - // temporary fix for Token retrocompatibility // This has to be done when url is built instead of here) if(strpos($className,'Controller')) $className = substr($className,0,-10); + if ($className == 'AdminCategories' OR $className == 'AdminProducts') + $className = 'AdminCatalog'; + + $this->className = $className; + $this->id = Tab::getIdFromClassName($className); $this->token = Tools::getAdminToken($className.(int)$this->id.(int)$this->context->employee->id); // Fix for AdminHome @@ -137,6 +182,335 @@ class AdminControllerCore extends Controller } else { + if (!isset($this->table)) + return false; + // set token + $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; + + // Sub included tab postProcessing + $this->includeSubTab('postProcess', array('status', 'submitAdd1', 'submitDel', 'delete', 'submitFilter', 'submitReset')); + + /* Delete object image */ + if (isset($_GET['deleteImage'])) + { + if (Validate::isLoadedObject($object = $this->loadObject())) + if (($object->deleteImage())) + Tools::redirectAdmin(self::$currentIndex.'&add'.$this->table.'&'.$this->identifier.'='.Tools::getValue($this->identifier).'&conf=7&token='.$token); + $this->_errors[] = Tools::displayError('An error occurred during image deletion (cannot load object).'); + } + + /* Delete object */ + elseif (isset($_GET['delete'.$this->table])) + { + if ($this->tabAccess['delete'] === '1') + { + if (Validate::isLoadedObject($object = $this->loadObject()) AND isset($this->fieldImageSettings)) + { + // check if request at least one object with noZeroObject + if (isset($object->noZeroObject) AND sizeof(call_user_func(array($this->className, $object->noZeroObject))) <= 1) + $this->_errors[] = Tools::displayError('You need at least one object.').' '.$this->table.'
'.Tools::displayError('You cannot delete all of the items.'); + else + { + if ($this->deleted) + { + $object->deleteImage(); + $object->deleted = 1; + if ($object->update()) + 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.'); + } + } + else + $this->_errors[] = Tools::displayError('An error occurred while deleting object.').' '.$this->table.' '.Tools::displayError('(cannot load object)'); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); + } + + /* Change object statuts (active, inactive) */ + elseif ((isset($_GET['status'.$this->table]) OR isset($_GET['status'])) AND Tools::getValue($this->identifier)) + { + if ($this->tabAccess['edit'] === '1') + { + if (Validate::isLoadedObject($object = $this->loadObject())) + { + if ($object->toggleStatus()) + Tools::redirectAdmin(self::$currentIndex.'&conf=5'.((($id_category = (int)(Tools::getValue('id_category'))) AND Tools::getValue('id_product')) ? '&id_category='.$id_category : '').'&token='.$token); + else + $this->_errors[] = Tools::displayError('An error occurred while updating status.'); + } + else + $this->_errors[] = Tools::displayError('An error occurred while updating status for object.').' '.$this->table.' '.Tools::displayError('(cannot load object)'); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); + } + /* Move an object */ + elseif (isset($_GET['position'])) + { + if ($this->tabAccess['edit'] !== '1') + $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); + elseif (!Validate::isLoadedObject($object = $this->loadObject())) + $this->_errors[] = Tools::displayError('An error occurred while updating status for object.').' '.$this->table.' '.Tools::displayError('(cannot load object)'); + elseif (!$object->updatePosition((int)(Tools::getValue('way')), (int)(Tools::getValue('position')))) + $this->_errors[] = Tools::displayError('Failed to update the position.'); + else + Tools::redirectAdmin(self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.(($id_category = (int)(Tools::getValue($this->identifier))) ? ('&'.$this->identifier.'='.$id_category) : '').'&token='.$token); + Tools::redirectAdmin(self::$currentIndex.'&'.$this->table.'Orderby=position&'.$this->table.'Orderway=asc&conf=5'.((($id_category = (int)(Tools::getValue('id_category'))) AND Tools::getValue('id_product')) ? '&id_category='.$id_category : '').'&token='.$token); + } + /* Delete multiple objects */ + elseif (Tools::getValue('submitDel'.$this->table)) + { + if ($this->tabAccess['delete'] === '1') + { + if (isset($_POST[$this->table.'Box'])) + { + $object = new $this->className(); + if (isset($object->noZeroObject) AND + // Check if all object will be deleted + (sizeof(call_user_func(array($this->className, $object->noZeroObject))) <= 1 OR sizeof($_POST[$this->table.'Box']) == sizeof(call_user_func(array($this->className, $object->noZeroObject))))) + $this->_errors[] = Tools::displayError('You need at least one object.').' '.$this->table.'
'.Tools::displayError('You cannot delete all of the items.'); + else + { + $result = true; + if ($this->deleted) + { + foreach(Tools::getValue($this->table.'Box') as $id) + { + $toDelete = new $this->className($id); + $toDelete->deleted = 1; + $result = $result AND $toDelete->update(); + } + } + else + $result = $object->deleteSelection(Tools::getValue($this->table.'Box')); + + if ($result) + Tools::redirectAdmin(self::$currentIndex.'&conf=2&token='.$token); + $this->_errors[] = Tools::displayError('An error occurred while deleting selection.'); + } + } + else + $this->_errors[] = Tools::displayError('You must select at least one element to delete.'); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); + } + + /* Create or update an object */ + elseif (Tools::getValue('submitAdd'.$this->table)) + { + /* Checking fields validity */ + $this->validateRules(); + if (!sizeof($this->_errors)) + { + $id = (int)(Tools::getValue($this->identifier)); + + /* Object update */ + if (isset($id) AND !empty($id)) + { + if ($this->tabAccess['edit'] === '1' OR ($this->table == 'employee' AND $this->context->employee->id == Tools::getValue('id_employee') AND Tools::isSubmit('updateemployee'))) + { + $object = new $this->className($id); + if (Validate::isLoadedObject($object)) + { + /* Specific to objects which must not be deleted */ + if ($this->deleted AND $this->beforeDelete($object)) + { + // Create new one with old objet values + $objectNew = new $this->className($object->id); + $objectNew->id = NULL; + $objectNew->date_add = ''; + $objectNew->date_upd = ''; + + // Update old object to deleted + $object->deleted = 1; + $object->update(); + + // Update new object with post values + $this->copyFromPost($objectNew, $this->table); + $result = $objectNew->add(); + if (Validate::isLoadedObject($objectNew)) + $this->afterDelete($objectNew, $object->id); + } + else + { + $this->copyFromPost($object, $this->table); + $result = $object->update(); + $this->afterUpdate($object); + } + + if ($object->id) + $this->updateAssoShop($object->id); + + if (!$result) + $this->_errors[] = Tools::displayError('An error occurred while updating object.').' '.$this->table.' ('.Db::getInstance()->getMsgError().')'; + elseif ($this->postImage($object->id) AND !sizeof($this->_errors)) + { + $parent_id = (int)(Tools::getValue('id_parent', 1)); + // Specific back redirect + if ($back = Tools::getValue('back')) + Tools::redirectAdmin(urldecode($back).'&conf=4'); + // Specific scene feature + if (Tools::getValue('stay_here') == 'on' || Tools::getValue('stay_here') == 'true' || Tools::getValue('stay_here') == '1') + Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&updatescene&token='.$token); + // Save and stay on same form + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) + Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=4&update'.$this->table.'&token='.$token); + // Save and back to parent + if (Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) + Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=4&token='.$token); + // Default behavior (save and back) + Tools::redirectAdmin(self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$object->id : '').'&conf=4&token='.$token); + } + } + else + $this->_errors[] = Tools::displayError('An error occurred while updating object.').' '.$this->table.' '.Tools::displayError('(cannot load object)'); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); + } + + /* Object creation */ + else + { + if ($this->tabAccess['add'] === '1') + { + $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) + { + $parent_id = (int)(Tools::getValue('id_parent', 1)); + $this->afterAdd($object); + $this->updateAssoShop($object->id); + // Save and stay on same form + if (Tools::isSubmit('submitAdd'.$this->table.'AndStay')) + Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$object->id.'&conf=3&update'.$this->table.'&token='.$token); + // Save and back to parent + if (Tools::isSubmit('submitAdd'.$this->table.'AndBackToParent')) + Tools::redirectAdmin(self::$currentIndex.'&'.$this->identifier.'='.$parent_id.'&conf=3&token='.$token); + // Default behavior (save and back) + Tools::redirectAdmin(self::$currentIndex.($parent_id ? '&'.$this->identifier.'='.$object->id : '').'&conf=3&token='.$token); + } + } + else + $this->_errors[] = Tools::displayError('You do not have permission to add here.'); + } + } + $this->_errors = array_unique($this->_errors); + } + + /* Cancel all filters for this tab */ + elseif (isset($_POST['submitReset'.$this->table])) + { + $filters = $this->context->cookie->getFamily($this->table.'Filter_'); + foreach ($filters AS $cookieKey => $filter) + if (strncmp($cookieKey, $this->table.'Filter_', 7 + Tools::strlen($this->table)) == 0) + { + $key = substr($cookieKey, 7 + Tools::strlen($this->table)); + /* Table alias could be specified using a ! eg. alias!field */ + $tmpTab = explode('!', $key); + $key = (count($tmpTab) > 1 ? $tmpTab[1] : $tmpTab[0]); + if (array_key_exists($key, $this->fieldsDisplay)) + unset($this->context->cookie->$cookieKey); + } + if (isset($this->context->cookie->{'submitFilter'.$this->table})) + unset($this->context->cookie->{'submitFilter'.$this->table}); + if (isset($this->context->cookie->{$this->table.'Orderby'})) + unset($this->context->cookie->{$this->table.'Orderby'}); + if (isset($this->context->cookie->{$this->table.'Orderway'})) + unset($this->context->cookie->{$this->table.'Orderway'}); + unset($_POST); + } + + /* Submit options list */ + elseif (Tools::getValue('submitOptions'.$this->table)) + { + $this->updateOptions($token); + } + + /* Manage list filtering */ + elseif (Tools::isSubmit('submitFilter'.$this->table) OR $this->context->cookie->{'submitFilter'.$this->table} !== false) + { + $_POST = array_merge($this->context->cookie->getFamily($this->table.'Filter_'), (isset($_POST) ? $_POST : array())); + foreach ($_POST AS $key => $value) + { + /* Extracting filters from $_POST on key filter_ */ + if ($value != NULL AND !strncmp($key, $this->table.'Filter_', 7 + Tools::strlen($this->table))) + { + $key = Tools::substr($key, 7 + Tools::strlen($this->table)); + /* Table alias could be specified using a ! eg. alias!field */ + $tmpTab = explode('!', $key); + $filter = count($tmpTab) > 1 ? $tmpTab[1] : $tmpTab[0]; + if ($field = $this->filterToField($key, $filter)) + { + $type = (array_key_exists('filter_type', $field) ? $field['filter_type'] : (array_key_exists('type', $field) ? $field['type'] : false)); + if (($type == 'date' OR $type == 'datetime') AND is_string($value)) + $value = unserialize($value); + $key = isset($tmpTab[1]) ? $tmpTab[0].'.`'.$tmpTab[1].'`' : '`'.$tmpTab[0].'`'; + if (array_key_exists('tmpTableFilter', $field)) + $sqlFilter = & $this->_tmpTableFilter; + elseif (array_key_exists('havingFilter', $field)) + $sqlFilter = & $this->_filterHaving; + else + $sqlFilter = & $this->_filter; + + /* Only for date filtering (from, to) */ + if (is_array($value)) + { + if (isset($value[0]) AND !empty($value[0])) + { + if (!Validate::isDate($value[0])) + $this->_errors[] = Tools::displayError('\'from:\' date format is invalid (YYYY-MM-DD)'); + else + $sqlFilter .= ' AND `'.bqSQL($key).'` >= \''.pSQL(Tools::dateFrom($value[0])).'\''; + } + + if (isset($value[1]) AND !empty($value[1])) + { + if (!Validate::isDate($value[1])) + $this->_errors[] = Tools::displayError('\'to:\' date format is invalid (YYYY-MM-DD)'); + else + $sqlFilter .= ' AND `'.bqSQL($key).'` <= \''.pSQL(Tools::dateTo($value[1])).'\''; + } + } + else + { + $sqlFilter .= ' AND '; + if ($type == 'int' OR $type == 'bool') + $sqlFilter .= (($key == $this->identifier OR $key == '`'.$this->identifier.'`' OR $key == '`active`') ? 'a.' : '').pSQL($key).' = '.(int)($value).' '; + elseif ($type == 'decimal') + $sqlFilter .= (($key == $this->identifier OR $key == '`'.$this->identifier.'`') ? 'a.' : '').pSQL($key).' = '.(float)($value).' '; + elseif ($type == 'select') + $sqlFilter .= (($key == $this->identifier OR $key == '`'.$this->identifier.'`') ? 'a.' : '').pSQL($key).' = \''.pSQL($value).'\' '; + else + $sqlFilter .= (($key == $this->identifier OR $key == '`'.$this->identifier.'`') ? 'a.' : '').pSQL($key).' LIKE \'%'.pSQL($value).'%\' '; + } + } + } + } + } + elseif(Tools::isSubmit('submitFields') AND $this->requiredDatabase AND $this->tabAccess['add'] === '1' AND $this->tabAccess['delete'] === '1') + { + if (!is_array($fields = Tools::getValue('fieldsBox'))) + $fields = array(); + + $object = new $this->className(); + if (!$object->addFieldsRequiredDatabase($fields)) + $this->_errors[] = Tools::displayError('Error in updating required fields'); + else + Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$token); + } } } @@ -160,6 +534,22 @@ class AdminControllerCore extends Controller } } + /** + * @TODO + */ + public function includeSubTab($methodname, $actions = array()) + { + } + + protected function filterToField($key, $filter) + { + foreach ($this->fieldsDisplay AS $field) + if (array_key_exists('filter_key', $field) AND $field['filter_key'] == $key) + return $field; + if (array_key_exists($filter, $this->fieldsDisplay)) + return $this->fieldsDisplay[$filter]; + return false; + } public function displayNoSmarty() { @@ -464,11 +854,11 @@ class AdminControllerCore extends Controller Tools::redirectAdmin('login.php?redirect='.$_SERVER['REQUEST_URI']); // Set current index - $currentIndex = $_SERVER['SCRIPT_NAME'].(($tab = Tools::getValue('tab')) ? '?tab='.$tab : ''); + $currentIndex = $_SERVER['SCRIPT_NAME'].(($controller = Tools::getValue('controller')) ? '?controller='.$controller : ''); + if ($back = Tools::getValue('back')) $currentIndex .= '&back='.urlencode($back); - AdminTab::$currentIndex = $currentIndex; - + self::$currentIndex = $currentIndex; $iso = $this->context->language->iso_code; include(_PS_TRANSLATIONS_DIR_.$iso.'/errors.php'); include(_PS_TRANSLATIONS_DIR_.$iso.'/fields.php'); @@ -482,23 +872,6 @@ class AdminControllerCore extends Controller //define('_PS_BASE_URL_', Tools::getShopDomain(true)); //define('_PS_BASE_URL_SSL_', Tools::getShopDomainSsl(true)); - /*$path = _PS_ADMIN_DIR_.'/themes/'; - if (empty($this->context->employee->bo_theme) OR !file_exists($path.$this->context->employee->bo_theme.'/admin.css')) - { - if (file_exists($path.'oldschool/admin.css')) - $this->context->employee->bo_theme = 'oldschool'; - elseif (file_exists($path.'origins/admin.css')) - $this->context->employee->bo_theme = 'origins'; - else - foreach (scandir($path) as $theme) - if ($theme[0] != '.' AND file_exists($path.$theme.'/admin.css')) - { - $employee->bo_theme = $theme; - break; - } - $this->context->employee->update(); - }*/ - // Change shop context ? if (Shop::isMultiShopActivated() && Tools::getValue('setShopContext') !== false) { @@ -547,4 +920,109 @@ class AdminControllerCore extends Controller { p($this->_errors); } + + /** + * Get the current objects' list form the database + * + * @param integer $id_lang Language used for display + * @param string $orderBy ORDER BY clause + * @param string $_orderWay Order way (ASC, DESC) + * @param integer $start Offset in LIMIT clause + * @param integer $limit Row count in LIMIT clause + */ + public function getList($id_lang, $orderBy = NULL, $orderWay = NULL, $start = 0, $limit = NULL, $id_lang_shop = false) + { + /* Manage default params values */ + if (empty($limit)) + $limit = ((!isset($this->context->cookie->{$this->table.'_pagination'})) ? $this->_pagination[1] : $limit = $this->context->cookie->{$this->table.'_pagination'}); + + if (!Validate::isTableOrIdentifier($this->table)) + die (Tools::displayError('Table name is invalid:').' "'.$this->table.'"'); + + if (empty($orderBy)) + $orderBy = $this->context->cookie->__get($this->table.'Orderby') ? $this->context->cookie->__get($this->table.'Orderby') : $this->_defaultOrderBy; + if (empty($orderWay)) + $orderWay = $this->context->cookie->__get($this->table.'Orderway') ? $this->context->cookie->__get($this->table.'Orderway') : 'ASC'; + + $limit = (int)(Tools::getValue('pagination', $limit)); + $this->context->cookie->{$this->table.'_pagination'} = $limit; + + + /* Check params validity */ + if (!Validate::isOrderBy($orderBy) OR !Validate::isOrderWay($orderWay) + OR !is_numeric($start) OR !is_numeric($limit) + OR !Validate::isUnsignedId($id_lang)) + die(Tools::displayError('get list params is not valid')); + + /* Determine offset from current page */ + if ((isset($_POST['submitFilter'.$this->table]) OR + isset($_POST['submitFilter'.$this->table.'_x']) OR + isset($_POST['submitFilter'.$this->table.'_y'])) AND + !empty($_POST['submitFilter'.$this->table]) AND + is_numeric($_POST['submitFilter'.$this->table])) + $start = (int)($_POST['submitFilter'.$this->table] - 1) * $limit; + + /* Cache */ + $this->_lang = (int)($id_lang); + $this->_orderBy = $orderBy; + $this->_orderWay = Tools::strtoupper($orderWay); + + /* SQL table : orders, but class name is Order */ + $sqlTable = $this->table == 'order' ? 'orders' : $this->table; + + // Add SQL shop restriction + $selectShop = $joinShop = $whereShop = ''; + if ($this->shopLinkType) + { + $selectShop = ', shop.name as shop_name '; + $joinShop = ' LEFT JOIN '._DB_PREFIX_.$this->shopLinkType.' shop + ON a.id_'.$this->shopLinkType.' = shop.id_'.$this->shopLinkType; + $whereShop = $this->context->shop->sqlRestriction($this->shopShareDatas, 'a', $this->shopLinkType); + } + $assos = Shop::getAssoTables(); + if (isset($assos[$this->table]) && $assos[$this->table]['type'] == 'shop') + { + $filterKey = $assos[$this->table]['type']; + $idenfierShop = $this->context->shop->getListOfID(); + } + else if (Context::shop() == Shop::CONTEXT_GROUP) + { + $assos = GroupShop::getAssoTables(); + if (isset($assos[$this->table]) AND $assos[$this->table]['type'] == 'group_shop') + { + $filterKey = $assos[$this->table]['type']; + $idenfierShop = array($this->context->shop->getGroupID()); + } + } + + $filterShop = ''; + if (isset($filterKey)) + { + if (!$this->_group) + $this->_group = 'GROUP BY a.'.pSQL($this->identifier); + else if (!preg_match('#(\s|,)\s*a\.`?'.pSQL($this->identifier).'`?(\s|,|$)#', $this->_group)) + $this->_group .= ', a.'.pSQL($this->identifier); + + if (Shop::isMultiShopActivated() && Context::shop() != Shop::CONTEXT_ALL && !preg_match('#`?'.preg_quote(_DB_PREFIX_.$this->table.'_'.$filterKey).'`? *sa#', $this->_join)) + $filterShop = 'JOIN `'._DB_PREFIX_.$this->table.'_'.$filterKey.'` sa ON (sa.'.$this->identifier.' = a.'.$this->identifier.' AND sa.id_'.$filterKey.' IN ('.implode(', ', $idenfierShop).'))'; + } + + /* Query in order to get results with all fields */ + $sql = 'SELECT SQL_CALC_FOUND_ROWS + '.($this->_tmpTableFilter ? ' * FROM (SELECT ' : '').' + '.($this->lang ? 'b.*, ' : '').'a.*'.(isset($this->_select) ? ', '.$this->_select.' ' : '').$selectShop.' + FROM `'._DB_PREFIX_.$sqlTable.'` a + '.$filterShop.' + '.($this->lang ? 'LEFT JOIN `'._DB_PREFIX_.$this->table.'_lang` b ON (b.`'.$this->identifier.'` = a.`'.$this->identifier.'` AND b.`id_lang` = '.(int)$id_lang.($id_lang_shop ? ' AND b.`id_shop`='.(int)$id_lang_shop : '').')' : '').' + '.(isset($this->_join) ? $this->_join.' ' : '').' + '.$joinShop.' + WHERE 1 '.(isset($this->_where) ? $this->_where.' ' : '').($this->deleted ? 'AND a.`deleted` = 0 ' : '').(isset($this->_filter) ? $this->_filter : '').$whereShop.' + '.(isset($this->_group) ? $this->_group.' ' : '').' + '.((isset($this->_filterHaving) || isset($this->_having)) ? 'HAVING ' : '').(isset($this->_filterHaving) ? ltrim($this->_filterHaving, ' AND ') : '').(isset($this->_having) ? $this->_having.' ' : '').' + ORDER BY '.(($orderBy == $this->identifier) ? 'a.' : '').'`'.pSQL($orderBy).'` '.pSQL($orderWay). + ($this->_tmpTableFilter ? ') tmpTable WHERE 1'.$this->_tmpTableFilter : '').' + LIMIT '.(int)$start.','.(int)$limit; + $this->_list = Db::getInstance()->ExecuteS($sql); + $this->_listTotal = Db::getInstance()->getValue('SELECT FOUND_ROWS() AS `'._DB_PREFIX_.$this->table.'`'); + } } diff --git a/classes/HelperList.php b/classes/HelperList.php new file mode 100644 index 000000000..f19bcb1ef --- /dev/null +++ b/classes/HelperList.php @@ -0,0 +1,445 @@ + 'id_product', 'id_category' => 'id_category_to_move','id_cms_category' => 'id_cms_category_to_move', 'id_cms' => 'id_cms', 'id_attribute' => 'id_attribute'); + + public function __construct() + { + $this->context = Context::getContext(); + } + + /** + * Return an html list given the data to fill it up + * + * @param array $list entries to display (rows) + * @param array $fieldsDisplay fields (cols) + * @return string html + */ + public function generateList($list, $fieldsDisplay) + { + /*if ($this->edit AND (!isset($this->noAdd) OR !$this->noAdd)) + $this->displayAddButton();*/ + + /* Append when we get a syntax error in SQL query */ + if ($list === false) + { + $this->displayWarning($this->l('Bad SQL query')); + return false; + } + + $this->_list = $list; + $this->fieldsDisplay = $fieldsDisplay; + + /* Display list header (filtering, pagination and column names) */ + $list_display = $this->displayListHeader(); + if (!sizeof($this->_list)) + $list_display .= ''; + + /* Show the content of the table */ + $list_display .= $this->displayListContent(); + + /* Close list table and submit button */ + $list_display .= $this->displayListFooter(); + + return $list_display; + } + + /** + * @TODO refactor + * + * @param unknown_type $token + * @param unknown_type $id + * @param unknown_type $value + * @param unknown_type $active + * @param unknown_type $id_category + * @param unknown_type $id_product + */ + protected function _displayEnableLink($token, $id, $value, $active, $id_category = NULL, $id_product = NULL) + { + return ' + '.($value ? $this->l('Enabled') : $this->l('Disabled')).''; + } + + public function displayListContent($token = NULL) + { + if (!$this->_list) + return; + + if ($this->is_dnd_identifier) + $id_category = (int)(Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category', '1')); + else + $id_category = 1; // default categ + + if (isset($this->fieldsDisplay['position'])) + { + $positions = array_map(create_function('$elem', 'return (int)($elem[\'position\']);'), $this->_list); + sort($positions); + } + + $key_to_get = 'id_'.($this->is_cms ? 'cms_' : '').'category'.(in_array($this->identifier, array('id_category', 'id_cms_category')) ? '_parent' : ''); + + $fields = array(); + + foreach ($this->_list AS $index => $tr) + { + $id = $tr[$this->identifier]; + + if ($this->shopLinkType) + $this->_list[$index]['short_shop_name'] = (Tools::strlen($tr['shop_name']) > 15) ? Tools::substr($tr['shop_name'], 0, 15).'...' : $tr['shop_name']; + + $has_actions = ($this->edit OR $this->delete OR ($this->view AND $this->view !== 'noActionColumn')) ? true : false; + + if ($has_actions) + { + if ($this->view) + $this->_list[$index]['view'] = $this->_displayViewLink($token, $id); + if ($this->edit) + $this->_list[$index]['edit'] = $this->_displayEditLink($token, $id); + if ($this->delete AND (!isset($this->_listSkipDelete) OR !in_array($id, $this->_listSkipDelete))) + $this->_list[$index]['delete'] = $this->_displayDeleteLink($token, $id); + if ($this->duplicate) + $this->_list[$index]['duplicate'] = $this->_displayDuplicate($token, $id); + } + + foreach ($this->fieldsDisplay AS $key => $params) + { + $tmp = explode('!', $key); + $key = isset($tmp[1]) ? $tmp[1] : $tmp[0]; + + if (isset($params['active'])) + $this->_list[$index][$key] = $this->_displayEnableLink($this->token, $tr['identifier'], $tr[$key], $params['active'], Tools::getValue('id_category'), Tools::getValue('id_product')); + elseif (isset($params['activeVisu'])) + $this->_list[$index][$key] = (bool)$tr[$key]; + elseif (isset($params['position'])) + { + $this->_list[$index][$key] = array( + 'position' => $tr[$key], + 'position_url_down' => self::$currentIndex. + '&'.$key_to_get.'='.(int)($id_category).'&'.$this->identifiersDnd[$this->identifier].'='.$id. + '&way=1&position='.(int)($tr['position'] + 1).'&token='.$this->token, + 'position_url_up' => self::$currentIndex. + '&'.$key_to_get.'='.(int)($id_category).'&'.$this->identifiersDnd[$this->identifier].'='.$id. + '&way=0&position='.(int)($tr['position'] - 1).'&token='.$this->token + ); + } + elseif (isset($params['image'])) + { + // item_id is the product id in a product image context, else it is the image id. + $item_id = isset($params['image_id']) ? $tr[$params['image_id']] : $id; + // If it's a product image + if (isset($tr['id_image'])) + { + $image = new Image((int)$tr['id_image']); + $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.$image->getExistingImgPath().'.'.$this->imageType; + }else + $path_to_image = _PS_IMG_DIR_.$params['image'].'/'.$item_id.(isset($tr['id_image']) ? '-'.(int)($tr['id_image']) : '').'.'.$this->imageType; + + $this->_list[$index][$key] = cacheImage($path_to_image, $this->table.'_mini_'.$item_id.'.'.$this->imageType, 45, $this->imageType); + } + elseif (isset($params['icon']) AND (isset($params['icon'][$tr[$key]]) OR isset($params['icon']['default']))) + $this->_list[$index][$key] = isset($params['icon'][$tr[$key]]) ? $params['icon'][$tr[$key]] : $params['icon']['default']; + elseif (isset($params['price'])) + $this->_list[$index][$key] = Tools::displayPrice($tr[$key], (isset($params['currency']) ? Currency::getCurrencyInstance($tr['id_currency']) : $this->context->currency), false); + elseif (isset($params['float'])) + $this->_list[$index][$key] = rtrim(rtrim($tr[$key], '0'), '.'); + elseif (isset($params['type']) AND $params['type'] == 'date') + $this->_list[$index][$key] = Tools::displayDate($tr[$key], $this->context->language->id); + elseif (isset($params['type']) AND $params['type'] == 'datetime') + $this->_list[$index][$key] = Tools::displayDate($tr[$key], $this->context->language->id, true); + elseif (isset($tr[$key])) + { + if ($key == 'price') + $echo = round($tr[$key], 2); + else if (isset($params['maxlength']) && Tools::strlen($tr[$key]) > $params['maxlength']) + $echo = ''.Tools::substr($tr[$key], 0, $params['maxlength']).'...'; + else + $echo = $tr[$key]; + + $this->_list[$index][$key] = isset($params['callback']) ? call_user_func_array(array((isset($params['callback_object'])) ? $params['callback_object'] : $this->className, $params['callback']), array($echo, $tr)) : $echo; + } + } + } + + $this->context->smarty->assign(array( + 'is_dnd_identifier' => $this->is_dnd_identifier, + 'color_on_bg' => $this->colorOnBackground, + 'id_category' => $id_category, + 'bulk_action' => $this->bulk_action, + 'key_to_get' => $key_to_get, + 'positions' => isset($positions) ? $positions : NULL, + 'is_cms' => $this->is_cms, + 'fields_display' => $this->fieldsDisplay, + 'list' => $this->_list, + 'no_link' => $this->noLink, + 'bulk_action' => $this->bulk_action, + 'current_index' => self::$currentIndex, + 'view' => $this->view, + 'edit' => $this->edit, + 'has_actions' => $has_actions, + + )); + return $this->context->smarty->fetch(_PS_ADMIN_DIR_.'/themes/template/list_content.tpl'); + } + + protected function displayAddButton() + { + echo '
'.$this->l('Add new').'

'; + } + + protected function _displayDuplicate($token = NULL, $id) + { + $_cacheLang['Duplicate'] = $this->l('Duplicate'); + $_cacheLang['Copy images too?'] = $this->l('Copy images too?', __CLASS__, TRUE, FALSE); + + $duplicate = self::$currentIndex.'&'.$this->identifier.'='.$id.'&duplicate'.$this->table; + + return ' + + '.$_cacheLang['Duplicate'].''; + } + + protected function _displayViewLink($token = NULL, $id) + { + $_cacheLang['View'] = $this->l('View'); + + return ' + + '.$_cacheLang['View'].''; + } + + protected function _displayEditLink($token = NULL, $id) + { + $_cacheLang['Edit'] = $this->l('Edit'); + + return ' + + '; + } + + protected function _displayDeleteLink($token = NULL, $id) + { + $_cacheLang['Delete'] = $this->l('Delete'); + $_cacheLang['DeleteItem'] = $this->l('Delete item #', __CLASS__, TRUE, FALSE); + + return ' + + '.$_cacheLang['Delete'].''; + } + + /** + * Display list header (filtering, pagination and column names) + */ + public function displayListHeader($token = NULL) + { + $id_cat = Tools::getValue('id_'.($this->is_cms ? 'cms_' : '').'category'); + + if (!isset($token) OR empty($token)) + $token = $this->token; + + /* Determine total page number */ + $total_pages = ceil($this->_listTotal / Tools::getValue('pagination', (isset($this->context->cookie->{$this->table.'_pagination'}) ? $this->context->cookie->{$this->table.'_pagination'} : $this->_pagination[0]))); + if (!$total_pages) $total_pages = 1; + + $action = self::$currentIndex + .(Tools::getIsset($this->identifier) ? '&'.$this->identifier.'='.(int)(Tools::getValue($this->identifier)) : '') + .'&token='.$token + .(Tools::getIsset($this->table.'Orderby') ? '&'.$this->table.'Orderby='.urlencode($this->_orderBy).'&'.$this->table.'Orderway='.urlencode(strtolower($this->_orderWay)) : '') + .'#'.$this->table; + + /* Determine current page number */ + $page = (int)(Tools::getValue('submitFilter'.$this->table)); + if (!$page) $page = 1; + + /* Choose number of results per page */ + $selected_pagination = Tools::getValue('pagination', (isset($this->context->cookie->{$this->table.'_pagination'}) ? $this->context->cookie->{$this->table.'_pagination'} : NULL)); + + /*$is_dnd_identifier = array_key_exists($this->identifier,$this->identifiersDnd); + + if ($is_dnd_identifier) + { + ' id="'. + if(((int)(Tools::getValue($this->identifiersDnd[$this->identifier], 1))) + substr($this->identifier,3,strlen($this->identifier))) + } + .' class="table'.( + if ($is_dnd_identifier AND ($this->_orderBy != 'position 'AND $this->_orderWay != 'DESC')) + ' tableDnD' + .'" cellpadding="0" cellspacing="0">*/ + + // Cleaning links + if (Tools::getValue($this->table.'Orderby') && Tools::getValue($this->table.'Orderway')) + self::$currentIndex = preg_replace('/&'.$this->table.'Orderby=([a-z _]*)&'.$this->table.'Orderway=([a-z]*)/i', '', self::$currentIndex); + + // Check if object can be modified, deleted or detailed + $has_actions = ($this->edit OR $this->delete OR ($this->view AND $this->view !== 'noActionColumn')) ? true : false; + + foreach ($this->fieldsDisplay as $key => $params) + { + if (!isset($params['type'])) + $params['type'] = 'text'; + + $value = Tools::getValue($this->table.'Filter_'.(array_key_exists('filter_key', $params) ? $params['filter_key'] : $key)); + + switch ($params['type']) + { + case 'bool': + break; + case 'date': + case 'datetime': + if (is_string($value)) + $value = unserialize($value); + if (!Validate::isCleanHtml($value[0]) OR !Validate::isCleanHtml($value[1])) + $value = ''; + //$name = $this->table.'Filter_'.(isset($params['filter_key']) ? $params['filter_key'] : $key); + //$nameId = str_replace('!', '__', $name); + //includeDatepicker(array($nameId.'_0', $nameId.'_1')); + break; + case 'select': + foreach ($params['select'] AS $option_value => $option_display) + { + if (isset($_POST[$this->table.'Filter_'.$params['filter_key']]) + && Tools::getValue($this->table.'Filter_'.$params['filter_key']) == $option_value + && Tools::getValue($this->table.'Filter_'.$params['filter_key']) != '') + $this->fieldsDisplay[$key]['select'][$option_value]['selected'] = 'selected'; + } + break; + case 'text': + if (!Validate::isCleanHtml($value)) + $value = ''; + + } + $params['value'] = $value; + $this->fieldsDisplay[$key] = $params; + } + + $this->context->smarty->assign(array( + 'table' => $this->table, + 'currentIndex' => self::$currentIndex, + 'action' => $action, + 'page' => $page, + 'total_pages' => $total_pages, + 'selected_pagination' => $selected_pagination, + 'pagination' => $this->_pagination, + 'list_total' => $this->_listTotal, + 'is_order_position' => array_key_exists($this->identifier, $this->identifiersDnd) && $this->_orderBy == 'position', + 'order_way' => $this->_orderWay, + 'token' => $this->token, + 'fields_display' => $this->fieldsDisplay, + 'delete' => $this->delete, + 'identifier' => $this->identifier, + 'id_cat' => $id_cat, + 'shop_link_type' => $this->shopLinkType, + 'has_actions' => $has_actions, + + )); + + return $this->context->smarty->fetch(_PS_ADMIN_DIR_.'/themes/template/list_header.tpl'); + } + + /** + * Close list table and submit button + */ + public function displayListFooter($token = NULL) + { + $this->context->smarty->assign(array( + 'token' => $this->token, + )); + return $this->context->smarty->fetch(_PS_ADMIN_DIR_.'/themes/template/list_footer.tpl'); + } + + /** + * use translations files to replace english expression. + * + * @param mixed $string term or expression in english + * @param string $class + * @param boolan $addslashes if set to true, the return value will pass through addslashes(). Otherwise, stripslashes(). + * @param boolean $htmlentities if set to true(default), the return value will pass through htmlentities($string, ENT_QUOTES, 'utf-8') + * @return string the translation if available, or the english default text. + */ + protected function l($string, $class = 'AdminTab', $addslashes = FALSE, $htmlentities = TRUE) + { + // if the class is extended by a module, use modules/[module_name]/xx.php lang file + $currentClass = get_class($this); + if(Module::getModuleNameFromClass($currentClass)) + { + $string = str_replace('\'', '\\\'', $string); + return Module::findTranslation(Module::$classInModule[$currentClass], $string, $currentClass); + } + global $_LANGADM; + + if ($class == __CLASS__) + $class = 'AdminTab'; + + $key = md5(str_replace('\'', '\\\'', $string)); + $str = (key_exists(get_class($this).$key, $_LANGADM)) ? $_LANGADM[get_class($this).$key] : ((key_exists($class.$key, $_LANGADM)) ? $_LANGADM[$class.$key] : $string); + $str = $htmlentities ? htmlentities($str, ENT_QUOTES, 'utf-8') : $str; + return str_replace('"', '"', ($addslashes ? addslashes($str) : stripslashes($str))); + } +} \ No newline at end of file diff --git a/classes/Tab.php b/classes/Tab.php index ebbde154b..0ce092855 100644 --- a/classes/Tab.php +++ b/classes/Tab.php @@ -126,7 +126,7 @@ class TabCore extends ObjectModel */ public static function getCurrentParentId() { - if ($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('SELECT `id_parent` FROM `'._DB_PREFIX_.'tab` WHERE LOWER(class_name) = \''.pSQL(Tools::strtolower(Tools::getValue('tab'))).'\'')) + if ($result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('SELECT `id_parent` FROM `'._DB_PREFIX_.'tab` WHERE LOWER(class_name) = \''.pSQL(Tools::strtolower(Tools::getValue('controller'))).'\'')) return $result['id_parent']; return -1; } diff --git a/controllers/admin/AdminAddressesController.php b/controllers/admin/AdminAddressesController.php new file mode 100644 index 000000000..2e8f80a5d --- /dev/null +++ b/controllers/admin/AdminAddressesController.php @@ -0,0 +1,523 @@ + +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision$ +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ +//include_once(_PS_ADMIN_DIR_.'/../classes/AdminTab.php'); +if(Configuration::get('VATNUMBER_MANAGEMENT') AND file_exists(_PS_MODULE_DIR_.'vatnumber/vatnumber.php')) + include_once(_PS_MODULE_DIR_.'vatnumber/vatnumber.php'); + +class AdminAddressesControllerCore extends AdminController +{ + /** @var array countries list */ + private $countriesArray = array(); + + public function __construct() + { + $this->table = 'address'; + $this->className = 'Address'; + $this->lang = false; + $this->edit = true; + $this->delete = true; + $this->requiredDatabase = true; + $this->addressType = 'customer'; + $this->context = Context::getContext(); + + if (!Tools::getValue('realedit')) + $this->deleted = true; + $this->_select = 'cl.`name` as country'; + $this->_join = 'LEFT JOIN `'._DB_PREFIX_.'country_lang` cl ON + (cl.`id_country` = a.`id_country` AND cl.`id_lang` = '.(int)$this->context->language->id.')'; + + $countries = Country::getCountries($this->context->language->id); + foreach ($countries AS $country) + $this->countriesArray[$country['id_country']] = $country['name']; + + $this->fieldsDisplay = array( + 'id_address' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25), + 'firstname' => array('title' => $this->l('First name'), 'width' => 80, 'filter_key' => 'a!firstname'), + 'lastname' => array('title' => $this->l('Last name'), 'width' => 100, 'filter_key' => 'a!lastname'), + 'address1' => array('title' => $this->l('Address'), 'width' => 200), + 'postcode' => array('title' => $this->l('Postcode/ Zip Code'), 'align' => 'right', 'width' => 50), + 'city' => array('title' => $this->l('City'), 'width' => 150), + 'country' => array('title' => $this->l('Country'), 'width' => 100, 'type' => 'select', 'select' => $this->countriesArray, 'filter_key' => 'cl!id_country')); + + $this->template = 'address.tpl'; + + parent::__construct(); + } + + public function postProcess() + { + if (isset($_POST['submitAdd'.$this->table])) + { + // Transform e-mail in id_customer for parent processing + if ($this->addressType == 'customer') + { + if (Validate::isEmail(Tools::getValue('email'))) + { + $customer = new Customer(Tools::getValue('id_customer')); + if (Validate::isLoadedObject($customer)) + $_POST['id_customer'] = $customer->id; + else + $this->_errors[] = Tools::displayError('This e-mail address is not registered.'); + } + elseif ($id_customer = Tools::getValue('id_customer')) + { + $customer = new Customer((int)($id_customer)); + if (Validate::isLoadedObject($customer)) + $_POST['id_customer'] = $customer->id; + else + $this->_errors[] = Tools::displayError('Unknown customer'); + } + else + $this->_errors[] = Tools::displayError('Unknown customer'); + if (Country::isNeedDniByCountryId(Tools::getValue('id_country')) AND !Tools::getValue('dni')) + $this->_errors[] = Tools::displayError('Identification number is incorrect or has already been used.'); + } + + // Check manufacturer selected + if ($this->addressType == 'manufacturer') + { + $manufacturer = new Manufacturer((int)(Tools::getValue('id_manufacturer'))); + if (!Validate::isLoadedObject($manufacturer)) + $this->_errors[] = Tools::displayError('Manufacturer selected is not valid.'); + } + + /* If the selected country does not contain states */ + $id_state = (int)(Tools::getValue('id_state')); + if ($id_country = Tools::getValue('id_country') AND $country = new Country((int)($id_country)) AND !(int)($country->contains_states) AND $id_state) + $this->_errors[] = Tools::displayError('You have selected a state for a country that does not contain states.'); + + /* If the selected country contains states, then a state have to be selected */ + if ((int)($country->contains_states) AND !$id_state) + $this->_errors[] = Tools::displayError('An address located in a country containing states must have a state selected.'); + + /* Check zip code */ + if ($country->need_zip_code) + { + $zip_code_format = $country->zip_code_format; + if (($postcode = Tools::getValue('postcode')) AND $zip_code_format) + { + $zip_regexp = '/^'.$zip_code_format.'$/ui'; + $zip_regexp = str_replace(' ', '( |)', $zip_regexp); + $zip_regexp = str_replace('-', '(-|)', $zip_regexp); + $zip_regexp = str_replace('N', '[0-9]', $zip_regexp); + $zip_regexp = str_replace('L', '[a-zA-Z]', $zip_regexp); + $zip_regexp = str_replace('C', $country->iso_code, $zip_regexp); + if (!preg_match($zip_regexp, $postcode)) + $this->_errors[] = Tools::displayError('Your zip/postal code is incorrect.').'
'.Tools::displayError('Must be typed as follows:').' '.str_replace('C', $country->iso_code, str_replace('N', '0', str_replace('L', 'A', $zip_code_format))); + } + elseif ($zip_code_format) + $this->_errors[] = Tools::displayError('Postcode required.'); + elseif ($postcode AND !preg_match('/^[0-9a-zA-Z -]{4,9}$/ui', $postcode)) + $this->_errors[] = Tools::displayError('Your zip/postal code is incorrect.'); + } + + + /* If this address come from order's edition and is the same as the other one (invoice or delivery one) + ** we delete its id_address to force the creation of a new one */ + if ((int)(Tools::getValue('id_order'))) + { + $this->_redirect = false; + if (isset($_POST['address_type'])) + $_POST['id_address'] = ''; + } + } + if (!sizeof($this->_errors)) + parent::postProcess(); + + /* Reassignation of the order's new (invoice or delivery) address */ + $address_type = ((int)(Tools::getValue('address_type')) == 2 ? 'invoice' : ((int)(Tools::getValue('address_type')) == 1 ? 'delivery' : '')); + if (isset($_POST['submitAdd'.$this->table]) AND ($id_order = (int)(Tools::getValue('id_order'))) AND !sizeof($this->_errors) AND !empty($address_type)) + { + if(!Db::getInstance()->Execute('UPDATE '._DB_PREFIX_.'orders SET `id_address_'.$address_type.'` = '.Db::getInstance()->Insert_ID().' WHERE `id_order` = '.$id_order)) + $this->_errors[] = Tools::displayError('An error occurred while linking this address to its order.'); + else + Tools::redirectAdmin(Tools::getValue('back').'&conf=4'); + } + } + + public function getList($id_lang, $orderBy = NULL, $orderWay = NULL, $start = 0, $limit = NULL, $id_lang_shop = NULL) + { + parent::getList($id_lang, $orderBy, $orderWay, $start, $limit); + /* Manage default params values */ + if (empty($limit)) + $limit = ((!isset($this->context->cookie->{$this->table.'_pagination'})) ? $this->_pagination[0] : $limit = $this->context->cookie->{$this->table.'_pagination'}); + + if (!Validate::isTableOrIdentifier($this->table)) + die('filter is corrupted'); + if (empty($orderBy)) + $orderBy = Tools::getValue($this->table.'Orderby', 'id_'.$this->table); + if (empty($orderWay)) + $orderWay = Tools::getValue($this->table.'Orderway', 'ASC'); + $limit = (int)(Tools::getValue('pagination', $limit)); + $this->context->cookie->{$this->table.'_pagination'} = $limit; + + /* Check params validity */ + if (!Validate::isOrderBy($orderBy) OR !Validate::isOrderWay($orderWay) + OR !is_numeric($start) OR !is_numeric($limit) + OR !Validate::isUnsignedId($id_lang)) + die(Tools::displayError('get list params is not valid')); + + /* Determine offset from current page */ + if ((isset($_POST['submitFilter'.$this->table]) OR + isset($_POST['submitFilter'.$this->table.'_x']) OR + isset($_POST['submitFilter'.$this->table.'_y'])) AND + !empty($_POST['submitFilter'.$this->table]) AND + is_numeric($_POST['submitFilter'.$this->table])) + $start = (int)($_POST['submitFilter'.$this->table] - 1) * $limit; + + /* Cache */ + $this->_lang = (int)($id_lang); + $this->_orderBy = $orderBy; + $this->_orderWay = Tools::strtoupper($orderWay); + + /* SQL table : orders, but class name is Order */ + $sqlTable = $this->table == 'order' ? 'orders' : $this->table; + + /* Query in order to get results number */ + $queryTotal = Db::getInstance()->getRow(' + SELECT COUNT(a.`id_'.$this->table.'`) AS total + FROM `'._DB_PREFIX_.$sqlTable.'` a + '.($this->lang ? 'LEFT JOIN `'._DB_PREFIX_.$this->table.'_lang` b ON (b.`id_'.$this->table.'` = a.`id_'.$this->table.'` AND b.`id_lang` = '.(int)($id_lang).')' : '').' + '.(isset($this->_join) ? $this->_join.' ' : '').' + WHERE 1 '.(isset($this->_where) ? $this->_where.' ' : '').(($this->deleted OR $this->table == 'currency') ? 'AND a.`deleted` = 0 ' : '').$this->_filter.' + '.(isset($this->_group) ? $this->_group.' ' : '').' + '.(isset($this->addressType) ? 'AND a.id_'.strval($this->addressType).' != 0' : '')); + $this->_listTotal = (int)($queryTotal['total']); + + /* Query in order to get results with all fields */ + $this->_list = Db::getInstance()->ExecuteS(' + SELECT a.*'.($this->lang ? ', b.*' : '').(isset($this->_select) ? ', '.$this->_select.' ' : '').' + FROM `'._DB_PREFIX_.$sqlTable.'` a + '.($this->lang ? 'LEFT JOIN `'._DB_PREFIX_.$this->table.'_lang` b ON (b.`id_'.$this->table.'` = a.`id_'.$this->table.'` AND b.`id_lang` = '.(int)($id_lang).')' : '').' + '.(isset($this->_join) ? $this->_join.' ' : '').' + WHERE 1 '.(isset($this->_where) ? $this->_where.' ' : '').(($this->deleted OR $this->table == 'currency') ? 'AND a.`deleted` = 0 ' : '').$this->_filter.' + '.(isset($this->_group) ? $this->_group.' ' : '').' + '.(isset($this->addressType) ? 'AND a.id_'.strval($this->addressType).' != 0' : '').' + ORDER BY '.(($orderBy == 'id_'.$this->table) ? 'a.' : '').'`'.pSQL($orderBy).'` '.pSQL($orderWay).' + LIMIT '.(int)($start).','.(int)($limit)); + } + + public function displayForm($isMainTab = true) + { + parent::displayForm(); + if (!($obj = $this->loadObject(true))) + return; + + echo ' + + '.((int)($obj->id) ? '' : '').' + '.(($id_order = (int)(Tools::getValue('id_order'))) ? '' : '').' + '.(($address_type = (int)(Tools::getValue('address_type'))) ? '' : '').' + '.(Tools::getValue('realedit') ? '' : '').' +
+ '.$this->l('Addresses').''; + switch ($this->addressType) + { + case 'manufacturer': + echo ' +
'; + $manufacturers = Manufacturer::getManufacturers(); + echo ''; + echo '
'; + echo ''; + break; + case 'customer': + default: + if ($obj->id) + { + $customer = new Customer($obj->id_customer); + $tokenCustomer = Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)$this->context->employee->id); + echo ' + + + + '; + } + else + { + echo + ' +
+ * +
'; + } + echo ' + +
+ +

'.$this->l('DNI / NIF / NIE').'

+
'; + + echo ' +
+ * + '.$this->l('Invalid characters:').' <>;=#{}  +
'; + break; + } + + $addresses_fields = $this->processAddressFormat(); + $addresses_fields = $addresses_fields["dlv_all_fields"]; // we use delivery address + + + + foreach($addresses_fields as $addr_field_item) + { + if ($addr_field_item == 'company') + { + if ($this->addressType != 'manufacturer') + { + echo ' +
+ + '.$this->l('Invalid characters:').' <>;=#{}  +
'; + + if ((Configuration::get('VATNUMBER_MANAGEMENT') AND file_exists(_PS_MODULE_DIR_.'vatnumber/vatnumber.php')) && VatNumber::isApplicable(Configuration::get('PS_COUNTRY_DEFAULT'))) + echo '
'; + else if(Configuration::get('VATNUMBER_MANAGEMENT')) + echo '
'; + else + echo'
'; + + echo ' +
+ +
+
'; + } + } + elseif ($addr_field_item == 'lastname') + { + echo ' + +
+ * + '.$this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:  +
'; + } + elseif ($addr_field_item == 'firstname') + { + + echo ' + +
+ * + '.$this->l('Invalid characters:').' 0-9!<>,;?=+()@#"�{}_$%:  +
'; + } + elseif ($addr_field_item == 'address1') + { + + echo ' + +
+ * +
'; + } + elseif ($addr_field_item == 'address2') + { + + echo ' + +
+ +
'; + } + elseif ($addr_field_item == 'postcode') + { + + echo ' + +
+ +
'; + } + elseif ($addr_field_item == 'city') + { + + echo ' + +
+ * +
'; + } + elseif ($addr_field_item == 'country' || $addr_field_item == 'Country:name') + { + + echo ' + +
+ * +
'; + + + echo ' +
+ +
+ + * +
+
'; + + + $id_country_ajax = (int)$this->getFieldValue($obj, 'id_country'); + + echo ' + '; + } + + } // End foreach + echo ' + +
+ +
'; + + echo ' + +
+ +
'; + + + echo ' + +
+ + '.$this->l('Forbidden characters:').' <>;=#{}  +
'; + + echo ' +
+ +
+
* '.$this->l('Required field').'
+
'; + echo ' + '; + } + + protected function processAddressFormat() + { + $tmp_addr = new Address((int)Tools::getValue("id_address")); + + $selectedCountry = ($tmp_addr && $tmp_addr->id_country) ? $tmp_addr->id_country : + (int)(Configuration::get('PS_COUNTRY_DEFAULT')); + + $inv_adr_fields = AddressFormat::getOrderedAddressFields($selectedCountry, false, true); + $dlv_adr_fields = AddressFormat::getOrderedAddressFields($selectedCountry, false, true); + + $inv_all_fields = array(); + $dlv_all_fields = array(); + + $out = array(); + + foreach (array('inv','dlv') as $adr_type) + { + foreach (${$adr_type.'_adr_fields'} as $fields_line) + foreach(explode(' ',$fields_line) as $field_item) + ${$adr_type.'_all_fields'}[] = trim($field_item); + + + $out[$adr_type.'_adr_fields'] = ${$adr_type.'_adr_fields'}; + $out[$adr_type.'_all_fields'] = ${$adr_type.'_all_fields'}; + } + + return $out; + } + + public function display() + { + $this->getList($this->context->language->id); + + $helper = new HelperList(); + $helper->edit = $this->edit; + $helper->delete = $this->delete; + $helper::$currentIndex = self::$currentIndex; + $helper->table = $this->table; + $helper->shopLink = $this->shopLink; + $helper->shopLinkType = $this->shopLinkType; + $helper->identifier = $this->identifier; + $helper->token = $this->token; + $this->context->smarty->assign(array('list' => $helper->generateList($this->_list, $this->fieldsDisplay))); + + parent::display(); + } +} + + diff --git a/controllers/admin/AdminToolsController.php b/controllers/admin/AdminToolsController.php index c0ebd7e7a..67fa60368 100644 --- a/controllers/admin/AdminToolsController.php +++ b/controllers/admin/AdminToolsController.php @@ -27,11 +27,5 @@ class AdminToolsControllerCore extends AdminController { - public function __construct() - { - $this->className = 'AdminTools'; - parent::__construct(); - } - }
+ {if $delete} + + {/if} + {$params.title} + {if !isset($params.orderby) || $params.orderby} +
+ + + + + + + {/if} +
+ {if $shop_link_type == 'shop'} + {l s='shop'} + {else} + {l s='Group shop'} + {/if} + {l s='Actions'}
+ {if $delete} + -- + {/if} + + {if isset($params.search) && !$params.search} + -- + {else} + {if $params.type == 'bool'} + + {elseif $params.type == 'date' || $params.type == 'datetime'} + {* + {l s='From'}
+ {l s='To'} + *} + {elseif $params.type == 'select'} + {if isset($params.filter_key)} + + {/if} + {else} + + {/if} + {/if} +
----
'.$this->l('No items found').'