From 6191e868f1ee0ec902b9307a1e5ee53a29ff3d9b Mon Sep 17 00:00:00 2001 From: mMarinetti Date: Fri, 23 Sep 2011 15:01:49 +0000 Subject: [PATCH] [+] BO : New AdminController system, including smarty backoffice, thanks to Raphael and Thomas --- admin-dev/functions.php | 163 ++++++- admin-dev/header.inc.php | 26 +- admin-dev/index.php | 131 +---- admin-dev/init.php | 24 +- admin-dev/themes/template/header.tpl | 22 +- admin-dev/themes/template/index.tpl | 49 +- classes/AdminController.php | 82 +++- classes/AdminTab.php | 2 +- classes/Chart.php | 17 +- classes/Dispatcher.php | 63 ++- classes/Tab.php | 11 + controllers/admin/AdminHomeController.php | 459 ++++++++++++++++++ .../admin/AdminToolsController.php | 4 +- 13 files changed, 833 insertions(+), 220 deletions(-) create mode 100644 controllers/admin/AdminHomeController.php rename admin-dev/tabs/AdminTools.php => controllers/admin/AdminToolsController.php (93%) diff --git a/admin-dev/functions.php b/admin-dev/functions.php index bd1a320ef..85d5b82ae 100644 --- a/admin-dev/functions.php +++ b/admin-dev/functions.php @@ -224,14 +224,6 @@ function translate($string) return str_replace('"', '"', stripslashes($str)); } -function recursiveTab($id_tab, $tabs) -{ - $adminTab = Tab::getTab((int)Context::getContext()->language->id, $id_tab); - $tabs[]= $adminTab; - if ($adminTab['id_parent'] > 0) - $tabs = recursiveTab($adminTab['id_parent'], $tabs); - return $tabs; -} /** * Returns a new Tab object @@ -244,22 +236,21 @@ function checkingTab($tab) $tab = trim($tab); if (!Validate::isTabName($tab)) return false; - $row = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('SELECT id_tab, module FROM `'._DB_PREFIX_.'tab` WHERE class_name = \''.pSQL($tab).'\''); if (!$row['id_tab']) { if (isset(AdminTab::$tabParenting[$tab])) Tools::redirectAdmin('?tab='.AdminTab::$tabParenting[$tab].'&token='.Tools::getAdminTokenLite(AdminTab::$tabParenting[$tab])); - echo Tools::displayError('Tab cannot be found.'); + echo sprintf(Tools::displayError('Tab %s cannot be found.'),$tab); return false; } - if ($row['module'] AND file_exists(_PS_MODULE_DIR_.'/'.$row['module'].'/'.$tab.'.php')) - include_once(_PS_MODULE_DIR_.'/'.$row['module'].'/'.$tab.'.php'); - elseif (file_exists(_PS_ADMIN_DIR_.'/tabs/'.$tab.'.php')) - include_once(_PS_ADMIN_DIR_.'/tabs/'.$tab.'.php'); + if ($row['module'] AND file_exists(_PS_MODULE_DIR_.'/'.$row['module'].'/'.Dispatcher::$controllers[$tab].'.php')) + include_once(_PS_MODULE_DIR_.'/'.$row['module'].'/'.Dispatcher::$controllers[$tab].'.php'); + elseif (file_exists(_PS_ADMIN_DIR_.'/tabs/'.Dispatcher::$controllers[$tab].'.php')) + include_once(_PS_ADMIN_DIR_.'/tabs/'.Dispatcher::$controllers[$tab].'.php'); if (!class_exists($tab, false) OR !$row['id_tab']) { - echo Tools::displayError('Tab file cannot be found.'); + echo sprintf(Tools::displayError('Tab file %s cannot be found.'),$tab); return false; } $adminObj = new $tab; @@ -424,4 +415,144 @@ function generateShopList() $html .= ''; return $html; -} \ No newline at end of file +} + +/** + * for retrocompatibility with old AdminTab, old index.php + * + * @return void + */ +function runAdminTab() +{ + +require_once(_PS_ADMIN_DIR_.'/../config/config.inc.php'); +require_once(_PS_ADMIN_DIR_.'/functions.php'); +require_once(_PS_ADMIN_DIR_.'/init.php'); +if (empty($tab) and !sizeof($_POST)) +{ + $tab = 'AdminHome'; + $_POST['tab'] = 'AdminHome'; + $_POST['token'] = Tools::getAdminTokenLite($tab); +} +// $tab = $_REQUEST['tab']; +if ($adminObj = checkingTab($tab)) +{ + // init is different for new tabs (AdminController) and old tabs (AdminTab) + if ($adminObj instanceof AdminController) + { + $adminObj->path = dirname($_SERVER["PHP_SELF"]); + $adminObj->run(); + } + else + { + require_once(_PS_ADMIN_DIR_.'/header.inc.php'); + $isoUser = Context::getContext()->language->id; + $tabs = array(); + $tabs = Tab::recursiveTab($adminObj->id, $tabs); + $tabs = array_reverse($tabs); + $bread = ''; + foreach ($tabs AS $key => $item) + $bread .= ' > + '.((sizeof($tabs) - 1 > $key) + ? '' + : '').' + '.$item['name'].((sizeof($tabs) - 1 > $key) ? '' : ''); + + // @TODO : a way to desactivate this feature + echo''; + + echo '
+ + '.translate('Back Office').' + '.$bread; + echo ' +
'; + + + if (Shop::isMultiShopActivated() && Context::shop() != Shop::CONTEXT_ALL) + { + echo '
'; + if (Context::shop() == Shop::CONTEXT_GROUP) + printf(translate('You are configuring your store for group shop %s'), ''.Context::getContext()->shop->getGroup()->name.''); + elseif (Context::shop() == Shop::CONTEXT_SHOP) + printf(translate('You are configuring your store for shop %s'), ''.Context::getContext()->shop->name.''); + echo '
'; + } + + if (Validate::isLoadedObject($adminObj)) + { + if ($adminObj->checkToken()) + { + /* Filter memorization */ + if (isset($_POST) AND !empty($_POST) AND isset($adminObj->table)) + foreach ($_POST AS $key => $value) + if (is_array($adminObj->table)) + { + foreach ($adminObj->table AS $table) + if (strncmp($key, $table.'Filter_', 7) === 0 OR strncmp($key, 'submitFilter', 12) === 0) + $cookie->$key = !is_array($value) ? $value : serialize($value); + } + elseif (strncmp($key, $adminObj->table.'Filter_', 7) === 0 OR strncmp($key, 'submitFilter', 12) === 0) + $cookie->$key = !is_array($value) ? $value : serialize($value); + + if (isset($_GET) AND !empty($_GET) AND isset($adminObj->table)) + foreach ($_GET AS $key => $value) + if (is_array($adminObj->table)) + { + foreach ($adminObj->table AS $table) + if (strncmp($key, $table.'OrderBy', 7) === 0 OR strncmp($key, $table.'Orderway', 8) === 0) + $cookie->$key = $value; + } + elseif (strncmp($key, $adminObj->table.'OrderBy', 7) === 0 OR strncmp($key, $adminObj->table.'Orderway', 12) === 0) + $cookie->$key = $value; + $adminObj->displayConf(); + $adminObj->postProcess(); + $adminObj->displayErrors(); + $adminObj->display(); + } + else + { + // If this is an XSS attempt, then we should only display a simple, secure page + ob_clean(); + + // ${1} in the replacement string of the regexp is required, because the token may begin with a number and mix up with it (e.g. $17) + $url = preg_replace('/([&?]token=)[^&]*(&.*)?$/', '${1}'.$adminObj->token.'$2', $_SERVER['REQUEST_URI']); + if (false === strpos($url, '?token=') AND false === strpos($url, '&token=')) + $url .= '&token='.$adminObj->token; + + $message = translate('Invalid security token'); + echo ''.$message.' +
+ + '.$message.' +
'; + echo ' + + + + + + '; + die; + } + } + include(_PS_ADMIN_DIR_.'/footer.inc.php'); + } +} + + +} diff --git a/admin-dev/header.inc.php b/admin-dev/header.inc.php index 2fb4d5c7a..d87b1bef1 100644 --- a/admin-dev/header.inc.php +++ b/admin-dev/header.inc.php @@ -75,7 +75,7 @@ echo ' html = ""; nb_notifs = 0; $.each(json.order, function(property, value) { - html += "
  • '.translate('A new order has been made on your shop.').'
    '.translate('Order number : ').'#" + parseInt(value.id_order) + "
    '.translate('Total : ').'" + value.total_paid_real + "
    '.translate('From : ').'" + value.customer_name + "
    '.translate('Click here to see that order').'
  • "; + html += "
  • '.translate('A new order has been made on your shop.').'
    '.translate('Order number : ').'#" + parseInt(value.id_order) + "
    '.translate('Total : ').'" + value.total_paid_real + "
    '.translate('From : ').'" + value.customer_name + "
    '.translate('Click here to see that order').'
  • "; }); if (html != "") { @@ -94,7 +94,7 @@ echo ' html = ""; nb_notifs = 0; $.each(json.customer, function(property, value) { - html += "
  • '.translate('A new customer registered on your shop.').'
    '.translate('Customer name : ').'" + value.customer_name + "
    '.translate('Click here to see that customer').'
  • "; + html += "
  • '.translate('A new customer registered on your shop.').'
    '.translate('Customer name : ').'" + value.customer_name + "
    '.translate('Click here to see that customer').'
  • "; }); if (html != "") { @@ -113,7 +113,7 @@ echo ' html = ""; nb_notifs = 0; $.each(json.message, function(property, value) { - html += "
  • '.translate('A new message posted on your shop.').'
    '.translate('From : ').'" + value.customer_name + "
    '.translate('Excerpt : ').'" + value.message_customer + "
    '.translate('Click here to see that message').'
  • "; + html += "
  • '.translate('A new message posted on your shop.').'
    '.translate('From : ').'" + value.customer_name + "
    '.translate('Excerpt : ').'" + value.message_customer + "
    '.translate('Click here to see that message').'
  • "; }); if (html != "") { @@ -192,7 +192,7 @@ echo ' var html = "";

    '.translate('Last orders').'

    '.translate('No new orders has been made on your shop').'

    -

    '.translate('Show all orders').'

    +

    '.translate('Show all orders').'

    '; } @@ -203,7 +203,7 @@ echo ' var html = "";

    '.translate('Last customers').'

    '.translate('No new customers registered on your shop').'

    -

    '.translate('Show all customers').'

    +

    '.translate('Show all customers').'

    '; } @@ -214,7 +214,7 @@ echo ' var html = "";

    '.translate('Last messages').'

    '.translate('No new messages posted on your shop').'

    -

    '.translate('Show all messages').'

    +

    '.translate('Show all messages').'

    '; } @@ -223,10 +223,10 @@ echo ' var html = ""; [ '.translate('logout').' ]'; if (Context::getContext()->shop->getBaseURL()) echo '- '.translate('View my shop').''; - echo ' - '.translate('My preferences').' + echo ' - '.translate('My preferences').' {/if} @@ -125,7 +124,7 @@

    {l s='Last customers'}

    {l s='No new customers registered on your shop'}

    -

    {l s='Show all customers'}

    +

    {l s='Show all customers'}

    {/if} @@ -138,7 +137,7 @@

    {l s='Last messages'}

    {l s='No new messages posted on your shop'}

    -

    {l s='Show all messages'}

    +

    {l s='Show all messages'}

    {/if} @@ -151,10 +150,10 @@ {if {$base_url}} - {l s='View my shop'} {/if} - - {l s='My preferences'} + - {l s='My preferences'} + + +

    '; + + + $this->content .= ' +
    + + '; + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + SELECT SUM(o.`total_paid_real` / o.conversion_rate) as total_sales, COUNT(*) as total_orders + FROM `'._DB_PREFIX_.'orders` o + WHERE o.valid = 1 + AND o.`invoice_date` BETWEEN \''.date('Y-m').'-01 00:00:00\' AND \''.date('Y-m').'-31 23:59:59\' '); + $result2 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + SELECT COUNT(`id_customer`) AS total_registrations + FROM `'._DB_PREFIX_.'customer` c + WHERE c.`date_add` BETWEEN \''.date('Y-m').'-01 00:00:00\' AND \''.date('Y-m').'-31 23:59:59\''); + $result3 = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' + SELECT SUM(pv.`counter`) AS total_viewed + FROM `'._DB_PREFIX_.'page_viewed` pv + LEFT JOIN `'._DB_PREFIX_.'date_range` dr ON pv.`id_date_range` = dr.`id_date_range` + LEFT JOIN `'._DB_PREFIX_.'page` p ON pv.`id_page` = p.`id_page` + LEFT JOIN `'._DB_PREFIX_.'page_type` pt ON pt.`id_page_type` = p.`id_page_type` + WHERE pt.`name` = \'product.php\' + AND dr.`time_start` BETWEEN \''.date('Y-m').'-01 00:00:00\' AND \''.date('Y-m').'-31 23:59:59\' + AND dr.`time_end` BETWEEN \''.date('Y-m').'-01 00:00:00\' AND \''.date('Y-m').'-31 23:59:59\''); + $results = array_merge($result, array_merge($result2, $result3)); + $this->content .= ' +
    +
    '.$this->l('View more').' '.$this->l('Monthly Statistics').'
    + + + + + + + + + + + + + + + + + +
    + '.$this->l('Sales').' + + ' + .Tools::displayPrice($results['total_sales'], $currency) + .' +
    + '.$this->l('Total registrations').' + + '.(int)($results['total_registrations']).' +
    + '.$this->l('Total orders').' + + '.(int)($results['total_orders']).' +
    + '.$this->l('Product pages viewed').' + + '.(int)($results['total_viewed']).' +
    +
    + '; + $all = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_thread'); + $unread = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'customer_thread` WHERE `status` = "open"'); + $pending = (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'customer_thread` WHERE `status` LIKE "%pending%"'); + $close = $all - ($unread + $pending); + $this->content .= ' +
    +
    '.$this->l('View more').' '.$this->l('Customers service').'
    + + + + + + + + + + + + + + + + + +
    + '.$this->l('Thread unread').' + + '.$unread.' +
    + '.$this->l('Thread pending').' + + '.$pending.' +
    + '.$this->l('Thread closed').' + + '.$close.' +
    + '.$this->l('Total thread').' + + '.$all.' +
    +
    + +
    +
    '.$this->l('View more').' '.$this->l('Statistics').' / '.$this->l('Sales of the week').'
    +
    '; + + define('PS_BASE_URI', __PS_BASE_URI__); + $chart = new Chart(); + $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' + SELECT total_paid / conversion_rate as total_converted, invoice_date + FROM '._DB_PREFIX_.'orders o + WHERE valid = 1 + AND invoice_date BETWEEN \''.date('Y-m-d', strtotime('-7 DAYS', time())).' 00:00:00\' AND \''.date('Y-m-d H:i:s').'\''); + foreach ($result as $row) + $chart->getCurve(1)->setPoint(strtotime($row['invoice_date']), $row['total_converted']); + $chart->setSize(580, 170); + $chart->setTimeMode(strtotime('-7 DAYS', time()), time(), 'd'); + $chart->getCurve(1)->setLabel($this->l('Sales +Tx').' ('.strtoupper($currency->iso_code).')'); + $this->content .= $chart->fetch(); + $this->content .= '
    +
    + + + + + + + + + + + '; + + $orders = Order::getOrdersWithInformations(10); + $i = 0; + foreach ($orders AS $order) + { + $currency = Currency::getCurrency((int)$order['id_currency']); + $this->content .= ' + + + + + + + + '; + $i++; + } + + $this->content .= ' + +
    '.$this->l('ID').''.$this->l('Customer Name').''.$this->l('Status').''.$this->l('Total').''.$this->l('Action').'
    '.(int)$order['id_order'].''.Tools::htmlentitiesUTF8($order['firstname']).' '.Tools::htmlentitiesUTF8($order['lastname']).''.Tools::htmlentitiesUTF8($order['state_name']).''.Tools::displayPrice((float)$order['total_paid'], $currency).' + '.$this->l('See').' +
    +
    +
    + +
    +

    '.$this->l('Loading...').'

    +
    + '; + + if (Tools::isSubmit('hideOptimizationTips')) + Configuration::updateValue('PS_HIDE_OPTIMIZATION_TIPS', 1); + + $this->_displayOptimizationTips(); + + $this->content .= ' +
    +

    '.$this->l('Loading...').'

    +
    +
    +
    '; + + $this->content .= Module::hookExec('backOfficeHome'); + $this->context->smarty->assign('content', $this->content); + parent::display(); + } +} + + diff --git a/admin-dev/tabs/AdminTools.php b/controllers/admin/AdminToolsController.php similarity index 93% rename from admin-dev/tabs/AdminTools.php rename to controllers/admin/AdminToolsController.php index 9b1f78b31..c0ebd7e7a 100644 --- a/admin-dev/tabs/AdminTools.php +++ b/controllers/admin/AdminToolsController.php @@ -25,15 +25,13 @@ * International Registered Trademark & Property of PrestaShop SA */ -class AdminTools extends AdminController +class AdminToolsControllerCore extends AdminController { - public $template = 'adminTools.tpl'; public function __construct() { $this->className = 'AdminTools'; parent::__construct(); } - }