From e0ceb7634dafd175a5b7465d5e4fadcc5577014e Mon Sep 17 00:00:00 2001 From: fSerny Date: Thu, 17 Nov 2011 00:43:30 +0000 Subject: [PATCH] [+] BO : New module tab interface - #PSFV-94 --- admin-dev/themes/default/modules.css | 243 ++++++ admin-dev/themes/template/modules/content.tpl | 33 + admin-dev/themes/template/modules/js.tpl | 107 +++ admin-dev/themes/template/modules/list.tpl | 228 +++++ controllers/admin/AdminModulesController.php | 799 ++++++++++++++++++ 5 files changed, 1410 insertions(+) create mode 100644 admin-dev/themes/default/modules.css create mode 100644 admin-dev/themes/template/modules/content.tpl create mode 100644 admin-dev/themes/template/modules/js.tpl create mode 100644 admin-dev/themes/template/modules/list.tpl create mode 100644 controllers/admin/AdminModulesController.php diff --git a/admin-dev/themes/default/modules.css b/admin-dev/themes/default/modules.css new file mode 100644 index 000000000..58b83f019 --- /dev/null +++ b/admin-dev/themes/default/modules.css @@ -0,0 +1,243 @@ +body {font-family: Arial, Helvetica, sans-serif;} + + +h1, h2, h3, h4 { font-family: Arial, Helvetica, sans-serif; margin-bottom:.5em; line-height:1.4em; } +h2 { font-size:1.7em; } +h3 { font-size:1.25em; } +h4 { font-size:1.05em; } +h6 { font-size:1em; } + + +/*LIST*/ +ul,ol {list-style:none; margin: 0; padding: 0;} + +/*FORM*/ +label {color:#585a69;text-shadow:0 1px 0#fff;} +fieldset{background-color:#EBEDF4; border:1px solid #CCCED7;font-size:1.1em;margin:0;padding:1em} +legend{background:#EBEDF4;border:1px solid #CCCED7;font-weight:700;margin:0;padding:.2em .5em;text-align:left} +input[type="text"],input[type="password"],input[type="file"],textarea {border:1px solid #ccc;} +select { border:1px solid #ccc;} +select[disabled="disabled"], input[disabled="disabled"],textarea[disabled="disabled"] {border: 1px solid #CCCCCC;color: #AAAAAA} +.header_module{background:url(header_module.png);padding-left: 0.5em;padding-top: 0.8em;height:20px;color: #812143;border:solid 1px #CCC;} + +/*BUTTON*/ +.button{background: -moz-linear-gradient(center top , #F9F9F9, #E3E3E3) repeat scroll 0 0 transparent; + background: -webkit-gradient(linear, center top ,center bottom, from(#F9F9F9), to(#E3E3E3)) repeat scroll 0 0 transparent; + border-color: #CCCCCC #BBBBBB #A0A0A0;border-left: 1px solid #BBBBBB;border-radius: 3px 3px 3px 3px;border-right: 1px solid #BBBBBB;border-style: solid;border-width: 1px;color: #000000;margin: 0; outline: medium none;padding: 3px 8px;text-align: center;vertical-align: middle;white-space: nowrap;} +.button[disabled=disabled]{color:#8C8C8C} +input.button[disabled=disabled]:hover{background-color:#FFF6D3} +.button:hover{border:1px solid #939393;} +.button:active{border:1px solid #939393;} + +#top_container{margin:0;padding:0} + +/*HEADER*/ +#header { background-color: #394049; height:114px; } +#header #header_infos{ position:relative; margin: 0; padding:0; height:84px; } +#header #header_shopname {float: left; margin:15px 20px 0 20px;} +#header #employee_links {float: right; display:block; margin:15px 15px 0 15px; } +#header #employee_links a{ float:left; color:#fff; text-transform:capitalize;} +#header #employee_links .employee_name { float:left; color:#fff;} +#header .separator { background: transparent url(separator.png) no-repeat scroll center top; display: block;float: left;height: 19px; width: 16px;} +#header #header_infos #header_shopname span{display:block; font-size:24px; height:28px; overflow:hidden;margin:0; color:#fff; text-shadow: 0 1px 0 #000000;} +#header #header_infos #header_logout { background: transparent url(logout.png) no-repeat scroll left top; float:left; padding-left:20px; color:#fff !important; } +#header #header_infos #header_logout a { color:#fff !important;} +#header #header_infos #header_logout a span {color:#fff;} +#header #header_infos #header_foaccess{ text-decoration:none; color:#fff;} +#header #header_infos #header_foaccess a {color:#fff !important;} +#header #header_search{ float:left; margin-top:15px; } +#header #header_search #bo_query{float:left;background: none repeat scroll 0 0 #fff; border-color: #666666 #CCCCCC #CCCCCC; + border-style:solid dotted solid solid; + border-width: 1px; color: #333; font: 13px Arial,sans-serif; padding: 4px 1px 4px 4px; width: 180px; + box-shadow: 0 1px 0 #444444;} +#header #header_search #bo_search_type{float:left; margin:0; padding:3px 0 4px; vertical-align:middle;width:auto; border-color: #666666 #CCCCCC #CCCCCC; + border-style:solid solid solid none; height:25px; + border-width: 1px;} +#header #header_search #bo_search_submit { border-color: #CCCCCC #BBBBBB; float:left; font-weight:normal; margin:0; padding: 4px 8px 3px; cursor:pointer; text-shadow: 0 1px 0 #fff; border-bottom-left-radius: 0; border-left: 0 none; border-top-left-radius: 0; } +#header #header_quick{float:right; display:block; margin-top:15px;} +#header #header_quick #quick_select{margin:0; padding:3px 0 4px; vertical-align:middle;width:140px; height:25px;} +#header #header_shoplist{ background-image:none; clear:both; float: right; color:#fff; margin-top:10px; margin-right:15px;} +#header #header_shoplist span { float:left; padding:3px;} +#header #header_myaccount{background:url(bg-lang.png) no-repeat;display:block;float:right;height:16px;margin:8px 1px 0 0;width:16px} + + +.path_bar {display:none;} +#notifs_icon_wrapper {float: left;position: relative;margin:15px 10px 0; width:90px;} +.notifs { float: left;position: relative;cursor: pointer;margin:0; padding:5px; width: 18px;height: 16px;} +#orders_notif {background: url("notif_order.png") no-repeat center top;} +#customers_notif {background: url("notif_customer.png") no-repeat center top;} +#messages_notif {background: url("notif_message.png") no-repeat center top;} +#orders_notif.open_notifs, +#customers_notif.open_notifs, +#messages_notif.open_notifs { background-color: #FFFFFF;border: 1px solid #000000; position: relative; display: block; background-position:center bottom; } + + +.number_wrapper {color: white;display: none;font-size: 13px;font-weight: bold;position: absolute; right: -8px;top: -10px;z-index: 101;padding: 2px 5px;} +.number_wrapper span {background-color: #F03D25;display: block;padding: 0 2px;border-color: -moz-use-text-color #DD3822 #DD3822;border-radius: 2px 2px 2px 2px;border-right: 1px solid #DD3822;border-style: none solid solid;border-width: 0 0px;} +.notifs_wrapper {background: none repeat scroll 0 0 #FFFFFF; border: 1px solid #000; border-top:none;display: none; cursor:auto; position: absolute; top: 25px; left: -1px; width:300px; padding: 10px;color: black; z-index:9999;} +.notifs_wrapper h3 {font-size: 14px;padding-bottom:8px;margin:0;border-bottom: 1px solid #E5E5E5;} +.notifs_wrapper ul {padding:6px 0;margin:0;} +.notifs_wrapper ul li {text-decoration: none;list-style: none;font-size:12px;padding:5px 0;} +#header_infos .notifs_wrapper a {font-weight: bold; font-size:11px; color: black; float:right;} +.notifs_wrapper p {font-size: 12px;padding-top:8px;margin:0;border-top: 1px solid #E5E5E5;} +.notifs_wrapper p.no_notifs {border: none;} + + +/*MENU*/ +#header #menu{ background-color: #f8f8f8; border-bottom:1px solid #e5e5e5; float:left;line-height:normal;margin:0;padding:0;width:100%;} +#header #menu li.maintab{float:left;height:29px;list-style:none;margin:0 1px 0 0;list-style:none;display:block; border-left:1px solid #fff; border-right:1px solid #ccc;} +#header #menu li#maintab1 { margin-left:20px;} +#header #menu li.submenu_size .title{color:#000;display:block; padding:8px 6px 4px 0;font-weight:normal;font-size:12px;} +#header #menu li.submenu_size .title{_display:inline;_padding:6px 5px 4px 0} +#header #menu li{_height:32px;_padding-top:3px} +#header #menu img{display:inline;padding:0 3px 0 6px; margin-top:-4px; vertical-align:middle;width:16px;height:16px} +#header #menu li.active, #header #menu li:hover{background-position:0 -38px;white-space:nowrap;} +#header #menu li.active a{} +#header #menu li:hover, #header #menu li.active {background-color:#49B2FF; } +#header #menu li.active span.title, #header #menu li:hover span.title {color:#fff; text-shadow: -1px -1px 0 #3293D6;} +#header #menu .withLeftBorder{background:transparent url(separator_subnav.png) no-repeat 0 5px} +#header #menu .submenu{background:#f8f8f8;clear:both;margin:0;padding:0;border:1px solid #d9d9d9;z-index:9999; box-shadow: 1px 5px 10px #CCCCCC; -moz-box-shadow:1px 5px 10px #CCCCCC; -webkit-box-shadow:1px 5px 10px #CCCCCC;} +#header #menu .submenu li{list-style:none;margin:0;padding:0;display:block;} +#header #menu .submenu li a{ font-size:12px;display:block;padding: 5px 15px 5px 10px; color:#666666;border-top:1px solid #fff; border-bottom:1px solid #ccc;} +#header #menu .submenu li a:hover { background-color:#eee; text-shadow:0 1px 0 #fff;} + +/*SEPARATION*/ +.separation { background-color:#ccc;border-bottom:1px solid #fff; width:100%; height:1px; margin:10px 0;} + +/*TABLE*/ +.table_grid {width:100%;} +.table{ background-color:#fff;border:1px solid #ccc;padding:0: border-radius:3px; -moz-border-radius:3px;-webkit-border-radius:3px;} +.filter {background-color:#f1f9ff;} +.table th a{text-decoration:underline} +.table a:hover{text-decoration:none} +.table tr th{ background-color: #F1F1F1; text-shadow:0 1px 0 #fff; padding:4px 6px; + background-image: -moz-linear-gradient(center top , #F9F9F9, #ECECEC); + background: -webkit-gradient(linear, center top ,center bottom, from(#F9F9F9), to(#ECECEC)) repeat scroll 0 0 transparent;} +.table tr td{border-bottom:1px solid #ccc;color:#333;font-size:11px;padding: 2px 4px 2px 6px} +.table tr.action_details td{background:#FAFAFA;} +.table tr.alt_row.action_details td{background:#E8E8E8;} +.table tr td.empty{border-bottom:none;background:white!important} +.table tr td.first{border-left:1px solid #DEDEDE} +.table tr td.last{border-right:1px solid #DEDEDE} +.table tr.small td{height:15px} +.table tr.last td{border-bottom:none} +td.col-left {vertical-align:top; padding-right:10px;} +td.col-left label { display:block; width:100%; text-align:right;} +.alt_row{background-color:#f8f8f8} +.path_bar{background-color:#E2EBEE;border:1px solid #999999;font-family:Trebuchet,Arial,Helvetica,sans-serif;font-size:13px;margin-bottom:20px;padding:5px} +.path_bar a{font-weight:700} +.cat_bar{background-color:#F4E8CD;border:1px solid #999999;font-family:Trebuchet,Arial,Helvetica,sans-serif;font-size:12px;font-weight:700;margin-bottom:20px;padding:5px} +.cat_bar a{font-weight:700} + +a.action_module{color: #268CCD;text-decoration: underline;} +a.header_module_toggle{font-weight: bold;color: #268CCD;display:block;} +a.module_toggle_all{color: #268CCD;} +.nbr_module{float:right;margin-right:10px;font-style:italic;font-size:12px;color: #268CCD;} + +.autoupgradeSteps div { line-height: 30px; } +.upgradestep { margin-right: 5px;padding-left: 10px; padding-right: 5px;} +#upgradeNow.stepok, .autoupgradeSteps a.stepok { background-image: url("../img/admin/enabled.gif");background-position: left center;background-repeat: no-repeat;padding-left: 15px;} +#upgradeNow {-moz-border-bottom-colors: none;-moz-border-image: none;-moz-border-left-colors: none;-moz-border-right-colors: none;-moz-border-top-colors: none;border-color: #FFF6D3 #DFD5AF #DFD5AF #FFF6D3;border-right: 1px solid #DFD5AF;border-style: solid;border-width: 1px;color: #268CCD;font-size: medium;padding: 5px;} +.button-autoupgrade {-moz-border-bottom-colors: none;-moz-border-image: none;-moz-border-left-colors: none;-moz-border-right-colors: none;-moz-border-top-colors: none;border-color: #FFF6D3 #DFD5AF #DFD5AF #FFF6D3;border-right: 1px solid #DFD5AF;border-style: solid;border-width: 1px;color: #268CCD;font-size: medium;padding: 5px;} +.processing {overflow: auto;} + +/*TABLE STATUS COMMANDE*/ +.table td span.color_field { font-size:11px; padding:2px 5px; border-radius:3px; text-transform:uppercase; text-shadow:0 1px 0 #fff; color:#fff; border-radius:3px; -moz-border-radius:3px; -webkit-border-radius:3px;} + +/*toolbarBox*/ +.toolbarBox { background-color: #F8F8F8; border: 1px solid #CCCCCC; margin-bottom:10px; padding: 10px 0; border-radius:3px; -moz-border-radius:3px; -webkit-border-radius:3px;} +.toolbarBox .pageTitle { margin-left:10px; line-height:48px} +.toolbarBox .pageTitle h3 {font-size: 2em; font-weight: bold; line-height: 48px; margin: 0; padding: 0;} +.toolbarBox ul.cc_button {float:right;margin:0;padding:0;} +.toolbarBox ul.cc_button li {color: #666666; float: left; height: 48px; list-style: none outside none; padding: 1px 1px 3px 4px; text-align: center;} +.toolbarBox a.toolbar_btn { border-width: 1px;font-size:11px;cursor: pointer; display: block; float: left; padding: 1px 5px; white-space: nowrap; text-shadow: 0 1px 0 #ffffff;;} +.toolbarBox a.toolbar_btn:hover {} +.toolbarBox .toolbar_btn span{ display: block;float: none;height: 32px;margin: 0 auto;width: 32px;} +.toolbarBox .process-icon-delete { background-image: url(process-icon-delete.png);} +.toolbarBox .process-icon-duplicate { background-image: url(process-icon-duplicate.png);} +.toolbarBox .process-icon-preview { background-image: url(process-icon-preview.png);} +.toolbarBox .process-icon-stats { background-image: url(process-icon-stats.png);} +.toolbarBox .process-icon-cancel { background-image: url(process-icon-cancel.png);} +.toolbarBox .process-icon-new, .toolbarBox .process-icon-newAttributes{ background-image: url(process-icon-new.png);} +.toolbarBox .process-icon-save, .toolbarBox .process-icon-save-settings { background-image: url(process-icon-save.png);} +.toolbarBox .process-icon-save-and-stay { background-image: url(process-icon-save-and-stay.png);} +.toolbarBox .process-icon-edit { background-image: url(process-icon-edit.png);} +.toolbarBox .process-icon-back { background-image: url(process-icon-back.png);} +.toolbarBox .process-icon-refresh-index { background-image: url(process-icon-refresh-index.png);} +.toolbarBox .process-icon-refresh-cache { background-image: url(process-icon-refresh-cache.png);} +.toolbarBox .process-icon-save-calendar { background-image: url(process-icon-save-calendar.png);} +.toolbarBox .process-icon-new-module { background-image: url(process-icon-new-module.png);} +.toolbarBox .process-icon-new-module-addon { background-image: url(process-icon-new-module-addon.png);} + +div.fix-toolbar {border-bottom: 1px solid #E0E0E0;position:fixed;top:0;opacity:0.9;z-index:1;} + +/*button upload files*/ +.qq-upload-button {background: -moz-linear-gradient(center top , #F9F9F9, #E3E3E3) repeat scroll 0 0 transparent; + background: -webkit-gradient(linear, center top ,center bottom, from(#F9F9F9), to(#E3E3E3)) repeat scroll 0 0 transparent; + border-color: #CCCCCC #BBBBBB #A0A0A0;border-left: 1px solid #BBBBBB;border-radius: 3px 3px 3px 3px;border-right: 1px solid #BBBBBB;border-style: solid;border-width: 1px;color: #000000;} +.qq-upload-button:hover { border:1px solid #939393;} +/*leadin*/ +.leadin { padding:10px;} + +/*productBox*/ +#productBox { position:relative; width:100%; float:left;} + +/*tab-pane*/ +form#product, form#access_form{ background-color:#ebedf4; border:1px solid #ccced7; min-height:300px; padding: 5px 10px 10px; margin-left:140px;} +/*form.defaultForm{ background-color:#ebedf4; border:1px solid #ccced7; min-height:300px; padding: 5px 10px 10px;}*/ +.tab-row {} +.tab-row .tab {background:#EFEFEF;width:100px;} +.tab-row .tab-page.selected {} +.tab-row .tab-page {} +.productTabs{ background-color:#fafafa; border:1px solid #ccced7; border-right:none; float:left; width:140px;} +.productTabs ul{padding:0;margin:0;} +.productTabs ul li.tab-row { border:none; } +.productTabs ul li.tab-row:first-child a {border-top:none;} +.productTabs ul li.tab-row a { display:block; font-weight:normal; color:#666;padding: 7px 10px; border-top:1px solid #CCCED7; border-right:1px solid #CCCED7;} +.productTabs ul li.tab-row a.selected { background-color:#EBEDF4;font-weight:bold;color:#000; border-right:none;} +.product-tab-content h4.tab { display:none;} + + +/*FILTER MODULE*/ +.filter-module { background-color:#ebedf4; border:1px solid #c2c4d9; padding:10px; display:block; min-height:35px;} +.filter-module #filternameForm {float:left; margin-right:30px;} +.filter-module label {width:auto;} +.filter-module .select-filter { float:left;} +.filter-module .button-filter { float:right;} + +/*SIDEBAR*/ +.sidebar { position:relative; float:left; width:220px; display:inline;} +.sidebar h3 { background-color:#ebedf4; font-weight:bold; display:block; padding:5px;} +.sidebar .subHeadline { font-weight:bold; float:right; margin-top:-28px; margin-right:5px;} +.sidebar ul.categorieList {} +.sidebar ul.categorieList li { border-top:1px solid #ccc; position:relative; line-height:20px;} +.sidebar ul.categorieList li:first-child { border-top:none;} +.sidebar ul.categorieList li a {color:#3a6ea7;} +.sidebar ul.categorieList li div.categorieWidth { width:180px; margin-left:5px; overflow:hidden;} +.sidebar ul.categorieList li div.count{ position:absolute; top:0; right:5px;} + +/*MODULECONTAINER*/ +#moduleContainer { margin-left:220px; padding:13px 0 0 20px;} +#moduleContainer .table tr th { height:40px;} +#moduleContainer .table tr td { vertical-align:top; padding: 5px 7px 0; border-top:1px dotted #ccc; border-bottom:none;} +#moduleContainer .table tr:first-child {border-top:1px solid #ccc} +#moduleContainer .moduleDesc { font-size:12px; position:relative; margin-bottom:10px;} +#moduleContainer .moduleDesc h3 { color:#3A6EA7; margin:0;} +#moduleContainer .moduleDesc .metadata { float:left; display:block; margin:5px 0;} +#moduleContainer .moduleDesc .metadata dl { float:left; margin:0; padding-right:10px;} +#moduleContainer .moduleDesc .metadata dl dt, .moduleDesc .metadata dl dd { float:left; margin:0; padding:0;} +#moduleContainer .moduleDesc .metadata dl dd { padding-right:10px;} +#moduleContainer .moduleDesc .metadata dl dt { font-weight:bold; padding-right:5px;} +#moduleContainer .moduleDesc p.desc { color:#666; font-size:12px; display:block; clear:both;} +#moduleContainer .setup {background-color:#6db300; font-size:10px; color:#fff; text-transform:uppercase; position:relative; left:10px; padding:0px 4px; display: inline-block; border-radius:3px;} +#moduleContainer .setup.non-install { background-color:#ec7000;} +#moduleContainer .setup.off{ background-color:#ccc;} +#moduleContainer .row-actions-module span { padding-right:5px;} +#moduleContainer .row-actions-module span a { font-size:12px;} +#moduleContainer .button.uninstalled, +#moduleContainer .button.installed { float:right; clear:both; margin-top:15px; font-size:12px;} + + +/*FOOTER*/ +#footer {height:40px; font-size:12px;clear:both;font-size:0.9em;color:#666666} +#footer .footer_link, #footer .footer_link:hover {color:#D41958;} diff --git a/admin-dev/themes/template/modules/content.tpl b/admin-dev/themes/template/modules/content.tpl new file mode 100644 index 000000000..1b857ca8d --- /dev/null +++ b/admin-dev/themes/template/modules/content.tpl @@ -0,0 +1,33 @@ +{* +* 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: 9771 $ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + +{if isset($module_content)} + {$module_content} +{else} + {include file='themes/template/modules/js.tpl'} + {include file='themes/template/modules/list.tpl'} +{/if} \ No newline at end of file diff --git a/admin-dev/themes/template/modules/js.tpl b/admin-dev/themes/template/modules/js.tpl new file mode 100644 index 000000000..6d2259b27 --- /dev/null +++ b/admin-dev/themes/template/modules/js.tpl @@ -0,0 +1,107 @@ +{* +* 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: 9771 $ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + + + + + + + \ No newline at end of file diff --git a/admin-dev/themes/template/modules/list.tpl b/admin-dev/themes/template/modules/list.tpl new file mode 100644 index 000000000..096c5c855 --- /dev/null +++ b/admin-dev/themes/template/modules/list.tpl @@ -0,0 +1,228 @@ +{* +* 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: 9771 $ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +
+
+
+ + + +
+

Module : Liste de modules

+
+ +
+
+ {l s='Add a new module'} {l s='Add a new module'} +

{'The module must be either a zip file or a tarball.'}

+
+
+
+ +
+ +

{l s='Upload the module from your computer.'}

+
+
+ +
+
+
+
+
+
+ +
+
+ + +
+
+ + +
+ +
+ +
+ + + +   + +   + +   + + +
+ +
+ + +
+ +
+ +
+ + +
+ + + +
+ + + + + + + + + + + + + + + {foreach from=$modules item=module} + + + + + + + {/foreach} + +
+
+ +
{l s='Module name'}
+
+

{$module->displayName}{if isset($module->id) && $module->id gt 0}{l s='Installed'}{else}{l s='Not installed'}{/if}

+ +

{l s='Description'} : {$module->description}

+ {if isset($module->message)}
{$module->message}
{/if} +
+ {$module->optionsHtml} +
+
+
{if isset($module->id) && $module->id gt 0}{l s='Uninstall'}{else}{l s='Install'}{/if}
+
+
+
\ No newline at end of file diff --git a/controllers/admin/AdminModulesController.php b/controllers/admin/AdminModulesController.php new file mode 100644 index 000000000..994d1b304 --- /dev/null +++ b/controllers/admin/AdminModulesController.php @@ -0,0 +1,799 @@ + +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision: 9790 $ +* @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_.'/../tools/tar/Archive_Tar.php'); + +class AdminModulesControllerCore extends AdminController +{ + /** @var array map with $_GET keywords and their callback */ + private $map = array( + 'install' => 'install', + 'uninstall' => 'uninstall', + 'configure' => 'getContent', + 'delete' => 'delete' + ); + + private $list_modules_categories = array(); + private $list_partners_modules = array(); + private $list_natives_modules = array(); + private $cache_file_modules_list = '/config/modules_list.xml'; + private $xml_modules_list = 'http://www.prestashop.com/xml/modules_list.xml'; + + private $nb_modules_total = 0; + private $nb_modules_installed = 0; + private $nb_modules_activated = 0; + + private $serial_modules = ''; + private $modules_authors = array(); + + public function __construct() + { + parent::__construct(); + + // Set the modules categories + $this->list_modules_categories['administration']['name'] = $this->l('Administration'); + $this->list_modules_categories['advertising_marketing']['name'] = $this->l('Advertising & Marketing'); + $this->list_modules_categories['analytics_stats']['name'] = $this->l('Analytics & Stats'); + $this->list_modules_categories['billing_invoicing']['name'] = $this->l('Billing & Invoicing'); + $this->list_modules_categories['checkout']['name'] = $this->l('Checkout'); + $this->list_modules_categories['content_management']['name'] = $this->l('Content Management'); + $this->list_modules_categories['export']['name'] = $this->l('Export'); + $this->list_modules_categories['front_office_features']['name'] = $this->l('Front Office Features'); + $this->list_modules_categories['i18n_localization']['name'] = $this->l('I18n & Localization'); + $this->list_modules_categories['merchandizing']['name'] = $this->l('Merchandizing'); + $this->list_modules_categories['migration_tools']['name'] = $this->l('Migration Tools'); + $this->list_modules_categories['payments_gateways']['name'] = $this->l('Payments & Gateways'); + $this->list_modules_categories['payment_security']['name'] = $this->l('Payment Security'); + $this->list_modules_categories['pricing_promotion']['name'] = $this->l('Pricing & Promotion'); + $this->list_modules_categories['quick_bulk_update']['name'] = $this->l('Quick / Bulk update'); + $this->list_modules_categories['search_filter']['name'] = $this->l('Search & Filter'); + $this->list_modules_categories['seo']['name'] = $this->l('SEO'); + $this->list_modules_categories['shipping_logistics']['name'] = $this->l('Shipping & Logistics'); + $this->list_modules_categories['slideshows']['name'] = $this->l('Slideshows'); + $this->list_modules_categories['smart_shopping']['name'] = $this->l('Smart Shopping'); + $this->list_modules_categories['market_place']['name'] = $this->l('Market Place'); + $this->list_modules_categories['social_networks']['name'] = $this->l('Social Networks'); + $this->list_modules_categories['others']['name'] = $this->l('Other Modules'); + + // Load cache file modules list (natives and partners modules) + if (file_exists(_PS_ROOT_DIR_.$this->cache_file_modules_list)) + $xmlModules = @simplexml_load_file(_PS_ROOT_DIR_.$this->cache_file_modules_list); + else + $xmlModules = false; + if ($xmlModules) + { + foreach($xmlModules->children() as $xmlModule) + { + if ($xmlModule->attributes() == 'native') + foreach($xmlModule->children() as $module) + foreach($module->attributes() as $key => $value) + if ($key == 'name') + $this->list_natives_modules[] = (string)$value; + + if ($xmlModule->attributes() == 'partner') + foreach ($xmlModule->children() as $module) + foreach ($module->attributes() as $key => $value) + if ($key == 'name') + $this->list_partners_modules[] = (string)$value; + } + } + } + + /** if modules_list.xml is outdated, + * this function will re-upload it from prestashop.com + * + * @return null + */ + public function ajaxProcessRefreshModuleList() + { + //refresh modules_list.xml every week + if (!$this->isFresh()) + { + if ($this->refresh()) + $this->status = 'refresh'; + else + $this->status = 'error'; + } + else + $this->status = 'cache'; + } + + + public function isFresh($timeout = 604800000) + { + if (file_exists(_PS_ROOT_DIR_ . $this->_moduleCacheFile)) + return ((time() - filemtime(_PS_ROOT_DIR_ . $this->_moduleCacheFile)) < $timeout); + else + return false; + } + + public function refresh() + { + return file_put_contents(_PS_ROOT_DIR_.$this->_moduleCacheFile, Tools::file_get_contents($this->xml_modules_list)); + } + + public function displayAjaxRefreshModuleList() + { + echo Tools::jsonEncode(array('status' => $this->status)); + } + + private function setFilterModules($module_type, $country_module_value, $module_install, $module_status) + { + $this->context = Context::getContext(); + Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)$this->context->employee->id, $module_type); + Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)$this->context->employee->id, $country_module_value); + Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)$this->context->employee->id, $module_install); + Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)$this->context->employee->id, $module_status); + } + + private function resetFilterModules() + { + $this->context = Context::getContext(); + Configuration::updateValue('PS_SHOW_TYPE_MODULES_'.(int)$this->context->employee->id, 'allModules'); + Configuration::updateValue('PS_SHOW_COUNTRY_MODULES_'.(int)$this->context->employee->id, 0); + Configuration::updateValue('PS_SHOW_INSTALLED_MODULES_'.(int)$this->context->employee->id, 'installedUninstalled'); + Configuration::updateValue('PS_SHOW_ENABLED_MODULES_'.(int)$this->context->employee->id, 'enabledDisabled'); + } + + /** + * Get current URL + * + * @param array $remove List of keys to remove from URL + * @return string + */ + protected function getCurrentUrl($remove = array()) + { + $url = $_SERVER['REQUEST_URI']; + if (!$remove) + return $url; + + if (!is_array($remove)) + $remove = array($remove); + + $url = preg_replace('#(?<=&|\?)(' . implode('|', $remove) . ')=.*?(&|$)#i', '', $url); + $len = strlen($url); + if ($url[$len - 1] == '&') + $url = substr($url, 0, $len - 1); + return $url; + } + + private function _getSubmitedModuleAuthor($value) + { + $value = str_replace('authorModules[', '', $value); + $value = str_replace("\'", "'", $value); + + $value = substr($value, 0, -1); + return $value; + } + + public function postProcess() + { + $id_employee = (int)$this->context->employee->id; + $filter_conf = Configuration::getMultiple(array( + 'PS_SHOW_TYPE_MODULES_'.$id_employee, + 'PS_SHOW_COUNTRY_MODULES_'.$id_employee, + 'PS_SHOW_INSTALLED_MODULES_'.$id_employee, + 'PS_SHOW_ENABLED_MODULES_'.$id_employee + )); + + if (Tools::isSubmit('desactive') && isset($filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee] != 'enabledDisabled') + $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee], 'disabled'); + + if (Tools::isSubmit('active') && isset($filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee] != 'enabledDisabled') + $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee], 'enabled'); + + if (Tools::isSubmit('uninstall') && isset($filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee] != 'installedUninstalled') + $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], 'unistalled', $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]); + + if (Tools::isSubmit('install') && isset($filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee]) && $filter_conf['PS_SHOW_INSTALLED_MODULES_'.$id_employee] != 'installedUninstalled') + $this->setFilterModules($filter_conf['PS_SHOW_TYPE_MODULES_'.$id_employee], $filter_conf['PS_SHOW_COUNTRY_MODULES_'.$id_employee], 'installed', $filter_conf['PS_SHOW_ENABLED_MODULES_'.$id_employee]); + + if (Tools::getValue('filterCategory') != '') + { + $newFilterCategory = Tools::getValue('filterCategory'); + $filterCategories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->context->employee->id)); + + // Check if category is not already filtered + foreach ($filterCategories as $fc) + if ($fc == $newFilterCategory) + $newFilterCategory = ''; + + // Add the new filter + if ($newFilterCategory != '') + $filterCategories[] = $newFilterCategory; + $filterCategories = implode('|', $filterCategories); + + Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->context->employee->id, $filterCategories); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + if (Tools::getValue('unfilterCategory') != '') + { + $unfilterCategory = Tools::getValue('unfilterCategory'); + $filterCategories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->context->employee->id)); + + // Remove the category + foreach ($filterCategories as $k => $fc) + if ($fc == $unfilterCategory) + unset($filterCategories[$k]); + + $filterCategories = implode('|', $filterCategories); + Configuration::updateValue('PS_SHOW_CAT_MODULES_'.(int)$this->context->employee->id, $filterCategories); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + if (Tools::isSubmit('filterModules')) + { + $this->setFilterModules(Tools::getValue('module_type'), Tools::getValue('country_module_value'), Tools::getValue('module_install'), Tools::getValue('module_status')); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + elseif (Tools::isSubmit('resetFilterModules')) + { + $this->resetFilterModules(); + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token); + } + + if (Tools::isSubmit('active')) + { + if ($this->tabAccess['edit'] === '1') + { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) + { + if (!$module->getPermission('configure')) + $this->_errors[] = Tools::displayError('You do not have the permission to use this module'); + else + { + $module->enable(); + Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); + } + } + else + $this->_errors[] = Tools::displayError('Cannot load module object'); + } else + $this->_errors[] = Tools::displayError('You do not have permission to add here.'); + } + elseif (Tools::isSubmit('desactive')) + { + if ($this->tabAccess['edit'] === '1') + { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) + { + if (!$module->getPermission('configure')) + $this->_errors[] = Tools::displayError('You do not have the permission to use this module'); + else + { + $module->disable(); + Tools::redirectAdmin(self::$currentIndex.'&conf=5&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); + } + } + else + $this->_errors[] = Tools::displayError('Cannot load module object'); + } else + $this->_errors[] = Tools::displayError('You do not have permission to add here.'); + } + elseif (Tools::isSubmit('reset')) + { + if ($this->tabAccess['edit'] === '1') + { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) + { + if (!$module->getPermission('configure')) + $this->_errors[] = Tools::displayError('You do not have the permission to use this module'); + else + { + if ($module->uninstall()) + if ($module->install()) + Tools::redirectAdmin(self::$currentIndex.'&conf=21'.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); + else + $this->_errors[] = Tools::displayError('Cannot install module'); + else + $this->_errors[] = Tools::displayError('Cannot uninstall module'); + } + } + else + $this->_errors[] = Tools::displayError('Cannot load module object'); + } else + $this->_errors[] = Tools::displayError('You do not have permission to add here.'); + + } + /* Automatically copy a module from external URL and unarchive it in the appropriated directory */ + if (Tools::isSubmit('submitDownload2')) + { + /* PrestaShop demo mode */ + if (_PS_MODE_DEMO_) + { + $this->_errors[] = Tools::displayError('This functionnality has been disabled.'); + return; + } + /* PrestaShop demo mode*/ + if ($this->tabAccess['add'] === '1') + { + if (!isset($_FILES['file']['tmp_name']) OR empty($_FILES['file']['tmp_name'])) + $this->_errors[] = $this->l('no file selected'); + elseif (substr($_FILES['file']['name'], -4) != '.tar' AND substr($_FILES['file']['name'], -4) != '.zip' AND substr($_FILES['file']['name'], -4) != '.tgz' AND substr($_FILES['file']['name'], -7) != '.tar.gz') + $this->_errors[] = Tools::displayError('Unknown archive type'); + elseif (!@copy($_FILES['file']['tmp_name'], _PS_MODULE_DIR_.$_FILES['file']['name'])) + $this->_errors[] = Tools::displayError('An error occurred while copying archive to module directory.'); + else + $this->extractArchive(_PS_MODULE_DIR_.$_FILES['file']['name']); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to add here.'); + } + + // Enable / disable module + if (Tools::getValue('enable') !== false) + { + if ($this->tabAccess['edit'] === '1') + { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module)) + { + if (!$module->getPermission('configure')) + $this->_errors[] = Tools::displayError('You do not have the permission to use this module'); + else + { + if (Tools::getValue('enable')) + $module->enable(); + else + $module->disable(); + Tools::redirectAdmin($this->getCurrentUrl('enable')); + } + } + else + $this->_errors[] = Tools::displayError('Cannot load module object'); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to add here.'); + } + + if (Tools::isSubmit('deleteModule')) + { + if ($this->tabAccess['delete'] === '1') + { + if (Tools::getValue('module_name') != '') + { + $module = Module::getInstanceByName(Tools::getValue('module_name')); + if (Validate::isLoadedObject($module) AND !$module->getPermission('configure')) + $this->_errors[] = Tools::displayError('You do not have the permission to use this module'); + else + { + $moduleDir = _PS_MODULE_DIR_.str_replace(array('.', '/', '\\'), array('', '', ''), Tools::getValue('module_name')); + $this->recursiveDeleteOnDisk($moduleDir); + Tools::redirectAdmin(self::$currentIndex.'&conf=22&token='.$this->token.'&tab_module='.Tools::getValue('tab_module').'&module_name='.Tools::getValue('module_name')); + } + } + } + else + $this->_errors[] = Tools::displayError('You do not have permission to delete here.'); + } + + /* Call appropriate module callback */ + else + { + $return = false; + foreach ($this->map as $key => $method) + { + $modules = Tools::getValue($key); + if (strpos($modules, '|')) + $modules = explode('|', $modules); + else + $modules = empty($modules) ? false : array($modules); + $module_errors = array(); + if ($modules) + foreach ($modules AS $name) + { + if (!($module = Module::getInstanceByName(urldecode($name)))) + $this->_errors[] = $this->l('module not found'); + elseif ($key == 'install' AND $this->tabAccess['add'] !== '1') + $this->_errors[] = Tools::displayError('You do not have permission to install a module.'); + elseif ($key == 'uninstall' AND ($this->tabAccess['delete'] !== '1' OR !$module->getPermission('configure'))) + $this->_errors[] = Tools::displayError('You do not have permission to delete this module.'); + elseif ($key == 'configure' AND ($this->tabAccess['edit'] !== '1' OR !$module->getPermission('configure'))) + $this->_errors[] = Tools::displayError('You do not have permission to configure this module.'); + elseif ($key == 'install' AND Module::isInstalled($module->name)) + $this->_errors[] = Tools::displayError('This module is already installed:').' '.$module->name; + elseif ($key == 'uninstall' AND !Module::isInstalled($module->name)) + $this->_errors[] = Tools::displayError('This module is already uninstalled:').' '.$module->name; + else + { + // If we install a module, force temporary global context for multishop + if (Shop::isFeatureActive() && Context::shop() != Shop::CONTEXT_ALL) + { + Context::getContext()->tmpOldShop = clone(Context::getContext()->shop); + Context::getContext()->shop = new Shop(); + Configuration::updateValue('RSS_FEED_TITLE', 'lol'); + } + + if (((method_exists($module, $method) && ($echo = $module->{$method}())) || ($echo = ' ')) AND $key == 'configure' AND Module::isInstalled($module->name)) + { + $backlink = self::$currentIndex.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name; + $hooklink = 'index.php?tab=AdminModulesPositions&token='.Tools::getAdminTokenLite('AdminModulesPositions').'&show_modules='.(int)$module->id; + $tradlink = 'index.php?tab=AdminTranslations&token='.Tools::getAdminTokenLite('AdminTranslations').'&type=modules&lang='; + + $toolbar = ' + + + + + + + '; + + // Display checkbox in toolbar if multishop + if (Shop::isFeatureActive()) + { + $activateOnclick = 'onclick="location.href = \''.$this->getCurrentUrl('enable').'&enable=\'+(($(this).attr(\'checked\')) ? 1 : 0)"'; + $toolbar .= ' + + '; + } + + $toolbar .= '
'.$this->l('Module').' '.$module->name.''.$this->l('Back').''.$this->l('Manage hooks').''.$this->l('Manage translations:').' '; + foreach (Language::getLanguages(false) AS $language) + $toolbar .= ''.$language['iso_code'].''; + $toolbar .= ' +
+ active) ? 'checked="checked"' : '').' '.$activateOnclick.' /> '.$this->l('Activate module for').' '; + if ($this->context->shop->getContextType() == Shop::CONTEXT_SHOP) + $toolbar .= 'shop '.$this->context->shop->name.''; + elseif ($this->context->shop->getContextType() == Shop::CONTEXT_GROUP) + $toolbar .= 'all shops of group shop '.$this->context->shop->getGroup()->name.''; + else + $toolbar .= 'all shops'; + $toolbar .= '
'; + + // Display configure page + // TODO : MAKE SOMETHING CLEANER + $this->context->smarty->assign('module_content', $toolbar.'
 
'.$echo.'
 
'.$toolbar); + } + elseif($echo) + $return = ($method == 'install' ? 12 : 13); + elseif ($echo === false) + $module_errors[] = $name; + + if (Shop::isFeatureActive() && Context::shop() != Shop::CONTEXT_ALL && isset(Context::getContext()->tmpOldShop)) + { + Context::getContext()->shop = clone(Context::getContext()->tmpOldShop); + unset(Context::getContext()->tmpOldShop); + } + } + if ($key != 'configure' && isset($_GET['bpay'])) + Tools::redirectAdmin('index.php?tab=AdminPayment&token='.Tools::getAdminToken('AdminPayment'.(int)(Tab::getIdFromClassName('AdminPayment')).(int)$this->context->employee->id)); + } + if (count($module_errors)) + { + // If error during module installation, no redirection + $html_error = '
    '; + foreach ($module_errors as $module_error) + $html_error .= '
  • '.$module_error.'
  • '; + $html_error .= '
'; + + $this->_errors[] = sprintf(Tools::displayError('The following module(s) were not installed successfully: %s'), $html_error); + } + } + if ($return) + Tools::redirectAdmin(self::$currentIndex.'&conf='.$return.'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name); + } + } + + public function extractArchive($file) + { + $success = false; + if (substr($file, -4) == '.zip') + { + if (!Tools::ZipExtract($file, _PS_MODULE_DIR_)) + $this->_errors[] = Tools::displayError('Error while extracting module (file may be corrupted).'); + } + else + { + $archive = new Archive_Tar($file); + if ($archive->extract(_PS_MODULE_DIR_)) + $success = true; + else + $this->_errors[] = Tools::displayError('Error while extracting module (file may be corrupted).'); + } + + @unlink($file); + if ($success) + Tools::redirectAdmin(self::$currentIndex.'&conf=8'.'&token='.$this->token); + } + + public static function sortModule($a, $b) + { + if (sizeof($a) == sizeof($b)) { + return 0; + } + return (sizeof($a) < sizeof($b)) ? -1 : 1; + } + + + + public function recursiveDeleteOnDisk($dir) + { + if (strpos(realpath($dir), realpath(_PS_MODULE_DIR_)) === false) + return ; + if (is_dir($dir)) + { + $objects = scandir($dir); + foreach ($objects as $object) + if ($object != "." && $object != "..") + { + if (filetype($dir."/".$object) == "dir") + $this->recursiveDeleteOnDisk($dir."/".$object); + else + unlink($dir."/".$object); + } + reset($objects); + rmdir($dir); + } + } + + + + // TODO : CHANGE THESE TWO METHODS INTO TPL + public function displayModuleOptions($module) + { + $return = ''; + $href = self::$currentIndex.'&token='.$this->token.'&module_name='.urlencode($module->name).'&tab_module='.$module->tab; + if ($module->id) + $return .= 'active && method_exists($module, 'onclickOption')? 'onclick="'.$module->onclickOption('desactive', $href).'"' : '').' href="'.self::$currentIndex.'&token='.$this->token.'&module_name='.urlencode($module->name).'&'.($module->active ? 'enable=0' : 'enable=1').'&tab_module='.$module->tab.'" '.((Shop::isFeatureActive()) ? 'title="'.htmlspecialchars($module->active ? $this->l('Disable this module') : $this->l('Enable this module for all shops')).'"' : '').'>'.($module->active ? $this->l('Disable') : $this->l('Enable')).''; + + if ($module->id AND $module->active) + $return .= (!empty($result) ? '|' : '').''.$this->l('Reset').''; + + if ($module->id AND (method_exists($module, 'getContent') OR (isset($module->is_configurable) AND $module->is_configurable) OR Shop::isFeatureActive())) + $return .= (!empty($result) ? '|' : '').''.$this->l('Configure').''; + + $hrefDelete = self::$currentIndex.'&deleteModule='.urlencode($module->name).'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.urlencode($module->name); + $return .= (!empty($result) ? '|' : '').''.$this->l('Delete').''; + + return $return; + } + private function displayModuleAuthorsOptGroup($authors, $fieldName = "UNDEFINED") + { + $out = ''; + foreach($authors as $author_item => $status) + { + $author_item = Tools::htmlentitiesUTF8($author_item); + $disp_author = ((strlen($author_item) > 20) ? substr($author_item, 0, 20).'...' : $author_item); + + $out .= ''; + } + $out .= ''; + return $out; + } + + + + public function initModulesList($modules) + { + foreach ($modules AS $module) + { + if (!in_array($module->name, $this->list_natives_modules)) + $this->serial_modules .= $module->name.' '.$module->version.'-'.($module->active ? 'a' : 'i')."\n"; + $module_author = $module->author; + if (!empty($module_author)&& ($module_author != "")) + $this->modules_authors[(string)$module_author] = true; + } + $this->serial_modules = urlencode($this->serial_modules); + } + + public function makeModulesStats($module) + { + // Count Installed Modules + if (isset($module->id) && $module->id > 0) + $this->nb_modules_installed++; + + // Count Activated Modules + if (isset($module->id) && $module->id > 0 && $module->active > 0) + $this->nb_modules_activated++; + + // Count Modules By Category + if (isset($this->list_modules_categories[$module->tab]['nb'])) + $this->list_modules_categories[$module->tab]['nb']++; + else + $this->list_modules_categories['others']['nb']++; + } + + public function moduleFiltered($module) + { + $showTypeModules = Configuration::get('PS_SHOW_TYPE_MODULES_'.(int)$this->context->employee->id); + $showInstalledModules = Configuration::get('PS_SHOW_INSTALLED_MODULES_'.(int)$this->context->employee->id); + $showEnabledModules = Configuration::get('PS_SHOW_ENABLED_MODULES_'.(int)$this->context->employee->id); + $showCountryModules = Configuration::get('PS_SHOW_COUNTRY_MODULES_'.(int)$this->context->employee->id); + $nameCountryDefault = Country::getNameById($this->context->language->id, Configuration::get('PS_COUNTRY_DEFAULT')); + $isoCountryDefault = $this->context->country->iso_code; + $filterName = Tools::getValue('filtername'); + + $categoryFiltered = array(); + $filterCategories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->context->employee->id)); + if (count($filterCategories) > 0) + foreach ($filterCategories as $fc) + if (!empty($fc)) + $categoryFiltered[$fc] = 1; + if (count($categoryFiltered) > 0 && !isset($categoryFiltered[$module->tab])) + return true; + + + + // beware $module could be an instance of Module or stdClass, that explain the static call + if ($module->id AND !Module::getPermissionStatic($module->id, 'view') AND !Module::getPermissionStatic($module->id, 'configure')) + return true; + + switch ($showTypeModules) + { + case 'nativeModules': + if (!in_array($module->name, $this->list_natives_modules)) + return true; + break; + case 'partnerModules': + if (!in_array($module->name, $this->list_partners_modules)) + return true; + break; + case 'otherModules': + if (in_array($module->name, $this->list_partners_modules) OR in_array($module->name, $this->list_natives_modules)) + return true; + break; + default: + if (strpos($showTypeModules, 'authorModules[') !== false) + { + $author_selected = $this->_getSubmitedModuleAuthor($showTypeModules); + $modulesAuthors[$author_selected] = 'selected'; // setting selected author in authors set + if (empty($module->author) || $module->author != $author_selected) + return true; + } + break; + } + + switch ($showInstalledModules) + { + case 'installed': + if (!$module->id) + return true; + break; + case 'unistalled': + if ($module->id) + return true; + break; + } + + switch ($showEnabledModules) + { + case 'enabled': + if (!$module->active) + return true; + break; + case 'disabled': + if ($module->active) + return true; + break; + } + + if ($showCountryModules AND (isset($module->limited_countries) AND !empty($module->limited_countries) AND ((is_array($module->limited_countries) AND sizeof($module->limited_countries) AND !in_array(strtolower($isoCountryDefault), $module->limited_countries)) OR (!is_array($module->limited_countries) AND strtolower($isoCountryDefault) != strval($module->limited_countries))))) + return true; + + if (!empty($filterName) AND (stristr($module->name, $filterName) === false AND stristr($module->displayName, $filterName) === false AND stristr($module->description, $filterName) === false)) + return true; + + return false; + } + + public function initContent() + { + // Adding Css + $this->addCSS(__PS_BASE_URI__.str_replace(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR, '', _PS_ADMIN_DIR_).'/themes/default/modules.css', 'all'); + + // Init + $smarty = $this->context->smarty; + $autocompleteList = 'var moduleList = ['; + $showTypeModules = Configuration::get('PS_SHOW_TYPE_MODULES_'.(int)$this->context->employee->id); + $showInstalledModules = Configuration::get('PS_SHOW_INSTALLED_MODULES_'.(int)$this->context->employee->id); + $showEnabledModules = Configuration::get('PS_SHOW_ENABLED_MODULES_'.(int)$this->context->employee->id); + $showCountryModules = Configuration::get('PS_SHOW_COUNTRY_MODULES_'.(int)$this->context->employee->id); + $nameCountryDefault = Country::getNameById($this->context->language->id, Configuration::get('PS_COUNTRY_DEFAULT')); + $isoCountryDefault = $this->context->country->iso_code; + $categoryFiltered = array(); + $filterCategories = explode('|', Configuration::get('PS_SHOW_CAT_MODULES_'.(int)$this->context->employee->id)); + if (count($filterCategories) > 0) + foreach ($filterCategories as $fc) + $categoryFiltered[$fc] = 1; + + foreach ($this->list_modules_categories as $k => $v) + $this->list_modules_categories[$k]['nb'] = 0; + + // Retrieve Modules List + $modules = Module::getModulesOnDisk(true); + $this->initModulesList($modules); + $this->nb_modules_total = count($modules); + + // Browse modules list + foreach ($modules as $km => $module) + { + // Make modules stats + $this->makeModulesStats($module); + + // Apply filter + if ($this->moduleFiltered($module)) + unset($modules[$km]); + else + { + // Fill module data + $modules[$km]->optionsHtml = $this->displayModuleOptions($module); + $modules[$km]->categoryName = (isset($this->list_modules_categories[$module->tab]['name']) ? $this->list_modules_categories[$module->tab]['name'] : $this->list_modules_categories['others']['name']); + $modules[$km]->options['install_url'] = self::$currentIndex.'&install='.urlencode($module->name).'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'#anchor'.ucfirst($module->name); + $modules[$km]->options['uninstall_url'] = self::$currentIndex.'&uninstall='.urlencode($module->name).'&token='.$this->token.'&tab_module='.$module->tab.'&module_name='.$module->name.'#anchor'.ucfirst($module->name); + $modules[$km]->options['uninstall_onclick'] = ((!method_exists($module, 'onclickOption')) ? ((empty($module->confirmUninstall)) ? '' : 'if(confirm(\''.addslashes($module->confirmUninstall).'\')) ').'document.location.href=\''.$modules[$km]->options['uninstall_url'].'\'' : $module->onclickOption('uninstall', $modules[$km]->options['uninstall_url'])); + if (Tools::getValue('module_name') == $module->name && (int)Tools::getValue('conf') > 0) + $modules[$km]->message = $this->_conf[(int)Tools::getValue('conf')]; + + // AutoComplete array + $autocompleteList .= Tools::jsonEncode(array( + 'displayName' => (string)$module->displayName, + 'desc' => (string)$module->description, + 'name' => (string)$module->name, + 'author' => (string)$module->author, + 'option' => $this->displayModuleOptions($module) + )).', '; + } + } + + // Init tpl vars for smarty + $tpl_vars = array(); + + $tpl_vars['token'] = $this->token; + $tpl_vars['currentIndex'] = self::$currentIndex; + $tpl_vars['dirNameCurrentIndex'] = dirname(self::$currentIndex); + $tpl_vars['ajaxCurrentIndex'] = str_replace('index', 'ajax-tab', self::$currentIndex); + $tpl_vars['autocompleteList'] = rtrim($autocompleteList, ' ,').'];'; + + $tpl_vars['showTypeModules'] = $showTypeModules; + $tpl_vars['showInstalledModules'] = $showInstalledModules; + $tpl_vars['showEnabledModules'] = $showEnabledModules; + $tpl_vars['showCountryModules'] = $showCountryModules; + $tpl_vars['nameCountryDefault'] = $nameCountryDefault; + $tpl_vars['isoCountryDefault'] = $isoCountryDefault; + + $tpl_vars['authorsOptionsList'] = $this->displayModuleAuthorsOptGroup($this->modules_authors, 'authorModules'); + $tpl_vars['addonsUrl'] = 'index.php?tab=AdminAddonsMyAccount&token='.Tools::getAdminTokenLite('AdminAddonsMyAccount'); + $tpl_vars['categoryFiltered'] = $categoryFiltered; + + $tpl_vars['modules'] = $modules; + $tpl_vars['nb_modules'] = $this->nb_modules_total; + $tpl_vars['nb_modules_installed'] = $this->nb_modules_installed; + $tpl_vars['nb_modules_uninstalled'] = $tpl_vars['nb_modules'] - $tpl_vars['nb_modules_installed']; + $tpl_vars['nb_modules_activated'] = $this->nb_modules_activated; + $tpl_vars['nb_modules_unactivated'] = $tpl_vars['nb_modules_installed'] - $tpl_vars['nb_modules_activated']; + $tpl_vars['list_modules_categories'] = $this->list_modules_categories; + + $smarty->assign($tpl_vars); + } + +}