@@ -59,7 +59,7 @@
diff --git a/admin/themes/default/template/controllers/modules/page.tpl b/admin/themes/default/template/controllers/modules/page.tpl
index 013b08fd1..dcb00ce5e 100644
--- a/admin/themes/default/template/controllers/modules/page.tpl
+++ b/admin/themes/default/template/controllers/modules/page.tpl
@@ -22,17 +22,59 @@
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*}
+
+
+
+
+
+ {if $module_alerts|@count}
+
+ {l s='There are %d alerts regarding your modules.' sprintf=count($module_alerts)}
+
+ {foreach from=$module_alerts item='alert'}
+ - {$alert}
+ {/foreach}
+
+
+ {else}
+
+ {l s='There are no alerts regarding your modules.'}
+
+ {/if}
+
+
+
+ {if $upgrade_available|@count}
+
+ {l s='An upgrade is available for some of your modules!'}
+
+
+ {else}
+
+ {l s='All modules are up to date!'}
+
+ {/if}
+
+
+
+
{$kpis}
{if $add_permission eq '1'}
{/if}
-{if $upgrade_available|@count}
-
- {l s='An upgrade is available for some of your modules!'}
-
-
-{/if}
\ No newline at end of file
diff --git a/admin/themes/default/template/controllers/modules/tab_module_line.tpl b/admin/themes/default/template/controllers/modules/tab_module_line.tpl
index 561074127..dc96ab14b 100644
--- a/admin/themes/default/template/controllers/modules/tab_module_line.tpl
+++ b/admin/themes/default/template/controllers/modules/tab_module_line.tpl
@@ -35,8 +35,6 @@
v{$module->version} - by {$module->author}
{if isset($module->type) && $module->type == 'addonsBought'}
-
{l s="Bought"}
- {elseif isset($module->type) && $module->type == 'addonsMustHave'}
- -
{l s="Popular"}
{elseif isset($module->type) && $module->type == 'addonsPartner'}
-
{l s="Official"}
{elseif isset($module->id) && $module->id gt 0}
diff --git a/admin/themes/default/template/controllers/modules/tab_modules_list.tpl b/admin/themes/default/template/controllers/modules/tab_modules_list.tpl
index 988c21850..5a875f5b5 100644
--- a/admin/themes/default/template/controllers/modules/tab_modules_list.tpl
+++ b/admin/themes/default/template/controllers/modules/tab_modules_list.tpl
@@ -25,46 +25,16 @@
*}
{if isset($tab_modules_list) && !empty($tab_modules_list)}
-
-
- {if count($tab_modules_list.not_installed)}
-
-
- {foreach from=$tab_modules_list.not_installed item=module}
- {include file='controllers/modules/tab_module_line.tpl' class_row={cycle values=",rowalt"}}
- {/foreach}
-
-
- {/if}
- {if count($tab_modules_list.installed)}
-
-
- {foreach from=$tab_modules_list.installed item=module}
- {include file='controllers/modules/tab_module_line.tpl' class_row={cycle values=",rowalt"}}
- {/foreach}
-
-
- {/if}
-
+
+ {foreach from=$tab_modules_list.not_installed item=module}
+ {include file='controllers/modules/tab_module_line.tpl' class_row={cycle values=",rowalt"}}
+ {/foreach}
+
+
+ {foreach from=$tab_modules_list.installed item=module}
+ {include file='controllers/modules/tab_module_line.tpl' class_row={cycle values=",rowalt"}}
+ {/foreach}
+
{/if}
{l s='More modules on qloapps.com/addons/'}
diff --git a/admin/themes/default/template/controllers/modules_catalog/content.tpl b/admin/themes/default/template/controllers/modules_catalog/content.tpl
new file mode 100644
index 000000000..18344f9a3
--- /dev/null
+++ b/admin/themes/default/template/controllers/modules_catalog/content.tpl
@@ -0,0 +1,12 @@
+
+{* ajaxBox allows*}
+
+
+{* {include file='controllers/modules_catalog/recomended-banner.tpl'} *}
+{include file='recomended-banner.tpl'}
+
+
+
+ {include file='controllers/modules_catalog/page.tpl'}
+
+
\ No newline at end of file
diff --git a/admin/themes/default/template/controllers/modules_catalog/index.php b/admin/themes/default/template/controllers/modules_catalog/index.php
new file mode 100644
index 000000000..239883ccc
--- /dev/null
+++ b/admin/themes/default/template/controllers/modules_catalog/index.php
@@ -0,0 +1,29 @@
+
+* @copyright 2010-2022 Webkul IN
+* @license https://store.webkul.com/license.html
+*/
+
+header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../../');
+exit;
diff --git a/admin/themes/default/template/controllers/modules_catalog/modules_list.tpl b/admin/themes/default/template/controllers/modules_catalog/modules_list.tpl
new file mode 100644
index 000000000..4ad0c5c28
--- /dev/null
+++ b/admin/themes/default/template/controllers/modules_catalog/modules_list.tpl
@@ -0,0 +1,51 @@
+{*
+* 2010-2022 Webkul.
+*
+* NOTICE OF LICENSE
+*
+* All right is reserved,
+* Please go through this link for complete license : https://store.webkul.com/license.html
+*
+* DISCLAIMER
+*
+* Do not edit or add to this file if you wish to upgrade this module to newer
+* versions in the future. If you wish to customize this module for your
+* needs please refer to https://store.webkul.com/customisation-guidelines/ for more information.
+*
+* @author Webkul IN
+* @copyright 2010-2022 Webkul IN
+* @license https://store.webkul.com/license.html
+*}
+
+
+ {foreach $elements as $element}
+
+
+
+
+
![{$element->displayName}]({if isset($element->image)}{$element->image}{else}{$modules_uri}/{$element->name}/{$element->logo}{/if})
+
{$element->displayName}
+
{$element->version} {l s='By'} {$element->author}
+
+
+ {if $element->description_full}
+ {$element->description_full|truncate:90:"..."}
+ {else}
+ {$element->description|truncate:90:"..."}
+ {/if}
+ {* {l s='Read more'} *}
+
+
+
+
+
+ {/foreach}
+
\ No newline at end of file
diff --git a/admin/themes/default/template/controllers/modules_catalog/page.tpl b/admin/themes/default/template/controllers/modules_catalog/page.tpl
new file mode 100644
index 000000000..fcdd22e60
--- /dev/null
+++ b/admin/themes/default/template/controllers/modules_catalog/page.tpl
@@ -0,0 +1,116 @@
+{*
+* 2010-2022 Webkul.
+*
+* NOTICE OF LICENSE
+*
+* All right is reserved,
+* Please go through this link for complete license : https://store.webkul.com/license.html
+*
+* DISCLAIMER
+*
+* Do not edit or add to this file if you wish to upgrade this module to newer
+* versions in the future. If you wish to customize this module for your
+* needs please refer to https://store.webkul.com/customisation-guidelines/ for more information.
+*
+* @author Webkul IN
+* @copyright 2010-2022 Webkul IN
+* @license https://store.webkul.com/license.html
+*}
+
+ {if isset($modules) && $modules}
+
+
+
+ {include file='controllers/modules_catalog/modules_list.tpl' elements=$modules}
+
+
+
+ {l s='No modules found'}
+
+
+
+
+
+
+ {l s='Explore all addon of Qloapps'}
+
{l s='QloApps Addons'}
+
+ {/if}
+ {if isset($themes) && $themes}
+
+
+
+ {include file='controllers/modules_catalog/theme_list.tpl' elements=$themes}
+
+
+
+ {l s='No themes found'}
+
+
+
+
+
+
+ {l s='Explore all themes of Qloapps'}
+
{l s='QloApps Themes'}
+
+ {/if}
+
diff --git a/admin/themes/default/template/controllers/modules_catalog/theme_list.tpl b/admin/themes/default/template/controllers/modules_catalog/theme_list.tpl
new file mode 100644
index 000000000..8aaa417c6
--- /dev/null
+++ b/admin/themes/default/template/controllers/modules_catalog/theme_list.tpl
@@ -0,0 +1,46 @@
+{*
+* 2010-2022 Webkul.
+*
+* NOTICE OF LICENSE
+*
+* All right is reserved,
+* Please go through this link for complete license : https://store.webkul.com/license.html
+*
+* DISCLAIMER
+*
+* Do not edit or add to this file if you wish to upgrade this module to newer
+* versions in the future. If you wish to customize this module for your
+* needs please refer to https://store.webkul.com/customisation-guidelines/ for more information.
+*
+* @author Webkul IN
+* @copyright 2010-2022 Webkul IN
+* @license https://store.webkul.com/license.html
+*}
+
+
+ {foreach $elements as $element}
+
+
+
+
+
![{$element->displayName}]({if isset($element->image)}{$element->image}{else}{$modules_uri}/{$element->name}/{$element->logo}{/if})
+
+
+
{$element->displayName}
+
{$element->version} {l s='By'} {$element->author}
+
+ {if $element->description_full}{$element->description_full|truncate:180:"..."}{else}{$element->description|truncate:180:"..."}{/if}
+
+
+ {if isset($element->type) && $element->type == 'addonsMustHave'}
+
{if isset($element->price)}{if $element->price|floatval == 0}{l s='Free'}{elseif isset($element->id_currency)}{displayPrice price=$element->price currency=$element->id_currency}{/if}{/if}
+
{l s='Explore'}
+ {else}
+
{l s='Install'}
+ {/if}
+
+
+
+
+ {/foreach}
+
\ No newline at end of file
diff --git a/admin/themes/default/template/header.tpl b/admin/themes/default/template/header.tpl
index 6decb7bbc..659433c3a 100644
--- a/admin/themes/default/template/header.tpl
+++ b/admin/themes/default/template/header.tpl
@@ -135,167 +135,171 @@
{/if}
-{if count($quick_access) >= 0}
-
{* end header_infos*}
@@ -349,13 +354,13 @@
{if isset($page_header_toolbar)}{$page_header_toolbar}{/if}
{if isset($modal_module_list)}{$modal_module_list}{/if}
-{if $install_dir_exists}
+ {if $install_dir_exists}
{l s='For security reasons, you must also delete the /install folder.'}
-{/if}
+ {/if}
- {hook h='displayAdminAfterHeader'}
+ {hook h='displayAdminAfterHeader'}
{* end display_header*}
diff --git a/admin/themes/default/template/helpers/modules_list/list.tpl b/admin/themes/default/template/helpers/modules_list/list.tpl
index 4329660fc..de8129f0a 100644
--- a/admin/themes/default/template/helpers/modules_list/list.tpl
+++ b/admin/themes/default/template/helpers/modules_list/list.tpl
@@ -37,7 +37,7 @@
{counter}
{/foreach}
- {if $controller_name == 'AdminPayment' && isset($view_all)}
+ {* {if $controller_name == 'AdminPayment' && isset($view_all)}
- {/if}
+ {/if} *}
{else}
diff --git a/admin/themes/default/template/page_header_toolbar.tpl b/admin/themes/default/template/page_header_toolbar.tpl
index 3e7a4cd09..8aaaa9726 100644
--- a/admin/themes/default/template/page_header_toolbar.tpl
+++ b/admin/themes/default/template/page_header_toolbar.tpl
@@ -105,7 +105,6 @@
{/if} *}
- {if (isset($tab_modules_open) && $tab_modules_open) || isset($tab_modules_list)}
- {/if}
{/block}
diff --git a/admin/themes/default/template/recomended-banner.tpl b/admin/themes/default/template/recomended-banner.tpl
new file mode 100644
index 000000000..343cd5899
--- /dev/null
+++ b/admin/themes/default/template/recomended-banner.tpl
@@ -0,0 +1,42 @@
+{*
+* 2010-2022 Webkul.
+*
+* NOTICE OF LICENSE
+*
+* All right is reserved,
+* Please go through this link for complete license : https://store.webkul.com/license.html
+*
+* DISCLAIMER
+*
+* Do not edit or add to this file if you wish to upgrade this module to newer
+* versions in the future. If you wish to customize this module for your
+* needs please refer to https://store.webkul.com/customisation-guidelines/ for more information.
+*
+* @author Webkul IN
+* @copyright 2010-2022 Webkul IN
+* @license https://store.webkul.com/license.html
+*}
+
+
+
+
+
\ No newline at end of file
diff --git a/classes/Tab.php b/classes/Tab.php
index 24932aed8..cf68e32fa 100644
--- a/classes/Tab.php
+++ b/classes/Tab.php
@@ -46,8 +46,6 @@ class TabCore extends ObjectModel
/** @var int hide_host_mode */
public $hide_host_mode = false;
- const TAB_MODULE_LIST_URL = _QLO_TAB_MODULE_LIST_URL_;
-
/**
* @see ObjectModel::$definition
*/
@@ -597,4 +595,9 @@ public static function getTabModulesList($id_tab)
return $modules_list;
}
+
+ public static function isTabModuleListAvailable()
+ {
+ return file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_TAB_MODULES_LIST);
+ }
}
diff --git a/classes/Tools.php b/classes/Tools.php
index f66db4bd0..abae3eebc 100644
--- a/classes/Tools.php
+++ b/classes/Tools.php
@@ -3323,7 +3323,8 @@ public static function addonsRequest($request, $params = array())
'version' => isset($params['version']) ? $params['version'] : _QLOAPPS_VERSION_,
'iso_lang' => Tools::strtolower(isset($params['iso_lang']) ? $params['iso_lang'] : Context::getContext()->language->iso_code),
'iso_code' => Tools::strtolower(isset($params['iso_country']) ? $params['iso_country'] : Country::getIsoById(Configuration::get('PS_COUNTRY_DEFAULT'))),
- 'shop_url' => isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomain(),
+ 'shop_url_ssl' => isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomainSsl(),
+ 'physical_uri' => Context::getContext()->shop->physical_uri,
'mail' => isset($params['email']) ? $params['email'] : Configuration::get('PS_SHOP_EMAIL')
));
@@ -3347,6 +3348,10 @@ public static function addonsRequest($request, $params = array())
$protocols[] = 'http';
$post_data .= '&method=listing&action=must-have-themes';
break;
+ case 'addons-modules':
+ $protocols[] = 'http';
+ $post_data .= '&method=listing&action=addons-modules';
+ break;
case 'customer':
$post_data .= '&method=listing&action=customer&username='.urlencode(trim(Context::getContext()->cookie->username_addons))
.'&password='.urlencode(trim(Context::getContext()->cookie->password_addons));
@@ -3359,10 +3364,10 @@ public static function addonsRequest($request, $params = array())
$post_data .= '&method=check_customer&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']);
break;
case 'check_module':
- $post_data .= '&method=check&module_name='.urlencode($params['module_name']).'&module_key='.urlencode($params['module_key']);
- break;
+ $post_data .= '&method=check&module='.urlencode($params['module_name']);
+ break;
case 'module':
- $post_data .= '&method=module&module_name='.urlencode($params['module_name']);
+ $post_data .= '&method=module&module='.urlencode($params['module_name']);
if (isset($params['username_addons']) && isset($params['password_addons'])) {
$post_data .= '&username='.urlencode($params['username_addons']).'&password='.urlencode($params['password_addons']);
} else {
@@ -3374,13 +3379,24 @@ public static function addonsRequest($request, $params = array())
.'&password='.urlencode($params['password_addons'])
.'&shop_url='.urlencode(isset($params['shop_url']) ? $params['shop_url'] : Tools::getShopDomain())
.'&mail='.urlencode(isset($params['email']) ? $params['email'] : Configuration::get('PS_SHOP_EMAIL'));
- $protocols[] = 'https';
break;
case 'install-modules':
- $protocols[] = 'http';
$post_data .= '&method=listing&action=install-modules';
$post_data .= defined('_PS_HOST_MODE_') ? '-od' : '';
break;
+ case 'catalog-recommendation':
+ $protocols[] = 'http';
+ $post_data .= '&method=content&action=catalogRecommendation';
+ $post_data .= defined('_PS_HOST_MODE_') ? '-od' : '';
+ break;
+ case 'dashboard-recommendation':
+ $protocols[] = 'http';
+ $post_data .= '&method=content&action=dashboardRecommendation';
+ $post_data .= defined('_PS_HOST_MODE_') ? '-od' : '';
+ break;
+ case 'check-version':
+ $post_data .= '&method=check-version&autoupgrade='.(int)(Module::isInstalled('qloautoupgrade') && Module::isEnabled('qloautoupgrade'));
+ break;
default:
return false;
}
diff --git a/classes/Upgrader.php b/classes/Upgrader.php
index 966598e78..19e52e249 100644
--- a/classes/Upgrader.php
+++ b/classes/Upgrader.php
@@ -27,6 +27,10 @@
class UpgraderCore
{
const DEFAULT_CHECK_VERSION_DELAY_HOURS = 24;
+
+ // @todo find correct class to declare upgrade_info for header
+ const CACHE_FILE_UPGRADE_AVAILABE = '/config/xml/upgrade_available.xml';
+
public $rss_version_link;
public $rss_md5file_link_dir;
/**
diff --git a/classes/controller/AdminController.php b/classes/controller/AdminController.php
index cf7bd5c4a..4a9597d5c 100644
--- a/classes/controller/AdminController.php
+++ b/classes/controller/AdminController.php
@@ -1575,6 +1575,7 @@ public function initPageHeaderToolbar()
$this->page_header_toolbar_title = $this->toolbar_title[count($this->toolbar_title) - 1];
}
+ $this->initTabModuleList();
$this->addPageHeaderToolBarModulesListButton();
$this->context->smarty->assign('help_link', 'http://help.prestashop.com/'.Language::getIsoById($this->context->employee->id_lang).'/doc/'
@@ -1652,7 +1653,6 @@ public function initToolbar()
);
}
}
- $this->addToolBarModulesListButton();
}
/**
@@ -2086,7 +2086,7 @@ public function initContent()
$this->getLanguages();
$this->initToolbar();
- $this->initTabModuleList();
+ // $this->initTabModuleList();
$this->initPageHeaderToolbar();
if ($this->display == 'edit' || $this->display == 'add') {
@@ -2128,22 +2128,10 @@ public function initContent()
*/
protected function initTabModuleList()
{
- if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400)) {
- @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have'));
- }
- if (!$this->isFresh(Module::CACHE_FILE_TAB_MODULES_LIST, 604800)) {
- $this->refresh(Module::CACHE_FILE_TAB_MODULES_LIST, _QLO_TAB_MODULE_LIST_URL_);
- }
-
- $this->tab_modules_list = Tab::getTabModulesList($this->id);
-
if (is_array($this->tab_modules_list['default_list']) && count($this->tab_modules_list['default_list'])) {
$this->filter_modules_list = $this->tab_modules_list['default_list'];
} elseif (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) {
- $this->addToolBarModulesListButton();
- $this->addPageHeaderToolBarModulesListButton();
$this->context->smarty->assign(array(
- 'tab_modules_list' => implode(',', $this->tab_modules_list['slider_list']),
'admin_module_ajax_url' => $this->context->link->getAdminLink('AdminModules'),
'back_tab_modules_list' => $this->context->link->getAdminLink(Tools::getValue('controller')),
'tab_modules_open' => (int)Tools::getValue('tab_modules_open')
@@ -2151,11 +2139,17 @@ protected function initTabModuleList()
}
}
+
+
protected function addPageHeaderToolBarModulesListButton()
{
- $this->filterTabModuleList();
+ $tab_modules_list = Tab::getTabModulesList($this->id);
- if (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) {
+ $tab_modules_list = $this->filterTabModuleList($tab_modules_list);
+
+ if ((is_array($tab_modules_list['slider_list']) && count($tab_modules_list['slider_list']))
+ || !Tab::isTabModuleListAvailable()
+ ) {
$this->page_header_toolbar_btn['modules-list'] = array(
'href' => '#',
'desc' => $this->l('Recommended Modules and Services')
@@ -2163,19 +2157,8 @@ protected function addPageHeaderToolBarModulesListButton()
}
}
- protected function addToolBarModulesListButton()
- {
- $this->filterTabModuleList();
-
- if (is_array($this->tab_modules_list['slider_list']) && count($this->tab_modules_list['slider_list'])) {
- $this->toolbar_btn['modules-list'] = array(
- 'href' => '#',
- 'desc' => $this->l('Recommended Modules and Services')
- );
- }
- }
- protected function filterTabModuleList()
+ protected function filterTabModuleList($tab_modules_list)
{
static $list_is_filtered = null;
@@ -2183,59 +2166,83 @@ protected function filterTabModuleList()
return;
}
- if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400)) {
- file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native'));
- }
-
- if (!$this->isFresh(Module::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, 86400)) {
- file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_ALL_COUNTRY_MODULES_LIST, Tools::addonsRequest('native_all'));
- }
-
- if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400)) {
- @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have'));
- }
+ $all_module_list = array();
libxml_use_internal_errors(true);
+ if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST)) {
+ $country_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST);
+ if (!empty($country_module_list) && $country_module_list_xml = @simplexml_load_string($country_module_list)) {
+ $country_module_list_array = array();
+ if (is_object($country_module_list_xml->module)) {
+ foreach ($country_module_list_xml->module as $k => $m) {
+ $all_module_list[] = (string)$m->name;
+ }
+ }
+ } else {
+ foreach (libxml_get_errors() as $error) {
+ $this->errors[] = Tools::displayError(sprintf('Error found : %1$s in country_module_list.xml file.', $error->message));
+ }
+ }
+ }
- $country_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST);
- $must_have_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST);
- $all_module_list = array();
+ libxml_clear_errors();
- if (!empty($country_module_list) && $country_module_list_xml = @simplexml_load_string($country_module_list)) {
- $country_module_list_array = array();
- if (is_object($country_module_list_xml->module)) {
- foreach ($country_module_list_xml->module as $k => $m) {
- $all_module_list[] = (string)$m->name;
+ if (file_exists(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST)) {
+ $must_have_module_list = file_get_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST);
+ if (!empty($must_have_module_list) && $must_have_module_list_xml = @simplexml_load_string($must_have_module_list)) {
+ $must_have_module_list_array = array();
+ if (is_object($country_module_list_xml->module)) {
+ foreach ($must_have_module_list_xml->module as $l => $mo) {
+ $all_module_list[] = (string)$mo->name;
+ }
+ }
+ } else {
+ foreach (libxml_get_errors() as $error) {
+ $this->errors[] = Tools::displayError(sprintf('Error found : %1$s in must_have_module_list.xml file.', $error->message));
}
- }
- } else {
- foreach (libxml_get_errors() as $error) {
- $this->errors[] = Tools::displayError(sprintf('Error found : %1$s in country_module_list.xml file.', $error->message));
}
}
libxml_clear_errors();
+ $tab_modules_list['slider_list'] = array_intersect($tab_modules_list['slider_list'], $all_module_list);
+
+ $list_is_filtered = true;
+ return $tab_modules_list;
+ }
- if (!empty($must_have_module_list) && $must_have_module_list_xml = @simplexml_load_string($must_have_module_list)) {
- $must_have_module_list_array = array();
- if (is_object($country_module_list_xml->module)) {
- foreach ($must_have_module_list_xml->module as $l => $mo) {
- $all_module_list[] = (string)$mo->name;
- }
+ public function ajaxProcessRefreshModuleList($force_reload_cache = false)
+ {
+ if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, _TIME_1_DAY_) || $force_reload_cache) {
+ if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native'))) {
+ $this->status = 'refresh';
+ } else {
+ $this->status = 'error';
}
} else {
- foreach (libxml_get_errors() as $error) {
- $this->errors[] = Tools::displayError(sprintf('Error found : %1$s in must_have_module_list.xml file.', $error->message));
- }
+ $this->status = 'cache';
}
- libxml_clear_errors();
-
- $this->tab_modules_list['slider_list'] = array_intersect($this->tab_modules_list['slider_list'], $all_module_list);
+ if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, _TIME_1_DAY_) || $force_reload_cache) {
+ if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have'))) {
+ $this->status = 'refresh';
+ } else {
+ $this->status = 'error';
+ }
+ } else {
+ $this->status = 'cache';
+ }
- $list_is_filtered = true;
+ if (!$this->isFresh(Module::CACHE_FILE_TAB_MODULES_LIST, _TIME_1_WEEK_)) {
+ if ($this->refresh(Module::CACHE_FILE_TAB_MODULES_LIST, _QLO_TAB_MODULE_LIST_URL_)) {
+ $this->status = 'refresh';
+ } else {
+ $this->status = 'error';
+ }
+ } else {
+ $this->status = 'cache';
+ }
}
/**
@@ -2369,7 +2376,9 @@ public function renderModulesList()
foreach ($xml_module->children() as $module) {
/** @var SimpleXMLElement $module */
foreach ($module->attributes() as $key => $value) {
- if ($xml_module->attributes() == 'native' && $key == 'name') {
+ if (($xml_module->attributes() == 'native' || $xml_module->attributes() == 'disk')
+ && $key == 'name'
+ ) {
$this->list_natives_modules[] = (string)$value;
}
if ($xml_module->attributes() == 'partner' && $key == 'name') {
@@ -2441,6 +2450,8 @@ public function renderList()
$helper = new HelperList();
+ unset($this->toolbar_btn);
+ $this->initToolbar();
// Empty list is ok
if (!is_array($this->_list)) {
$this->displayWarning($this->l('Bad SQL query', 'Helper').'
'.htmlspecialchars($this->_list_error));
@@ -2824,6 +2835,19 @@ public function init()
'submit_form_ajax' => (int)Tools::getValue('submitFormAjax')
));
+ // get upgrade available info
+ if (!$this->isFresh(Upgrader::CACHE_FILE_UPGRADE_AVAILABE, _TIME_1_DAY_)) {
+ file_put_contents(_PS_ROOT_DIR_.Upgrader::CACHE_FILE_UPGRADE_AVAILABE, Tools::addonsRequest('check-version'));
+ }
+ if (file_exists(_PS_ROOT_DIR_.Upgrader::CACHE_FILE_UPGRADE_AVAILABE)) {
+ $content = Tools::file_get_contents( _PS_ROOT_DIR_.Upgrader::CACHE_FILE_UPGRADE_AVAILABE);
+ $upgradeInfo = simplexml_load_string($content);
+
+ $this->context->smarty->assign(array(
+ 'upgrade_info' => $upgradeInfo
+ ));
+ }
+
Employee::setLastConnectionDate($this->context->employee->id);
$this->initProcess();
@@ -4053,7 +4077,7 @@ public function jsonError($message)
* @param int $timeout
* @return bool
*/
- public function isFresh($file, $timeout = 604800)
+ public function isFresh($file, $timeout = _TIME_1_WEEK_)
{
if (($time = @filemtime(_PS_ROOT_DIR_.$file)) && filesize(_PS_ROOT_DIR_.$file) > 0) {
return ((time() - $time) < $timeout);
@@ -4103,8 +4127,17 @@ public function fillModuleData(&$module, $output_type = 'link', $back = null)
$link_admin_modules = $this->context->link->getAdminLink('AdminModules', true);
$module->options['install_url'] = $link_admin_modules.'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name);
- $module->options['update_url'] = $link_admin_modules.'&update='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name);
+ if ($module->is_native) {
+ $module->options['update_url'] = $link_admin_modules.'&update='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name);
+ } else {
+ if ($module->url) {
+ $module->options['update_url'] = $module->url;
+ } else {
+ $module->options['update_url'] = '';
+ }
+ }
$module->options['uninstall_url'] = $link_admin_modules.'&uninstall='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name);
+ $module->options['delete_url'] = $link_admin_modules.'&delete='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name);
$module->optionsHtml = $this->displayModuleOptions($module, $output_type, $back);
diff --git a/classes/module/Module.php b/classes/module/Module.php
index bd8b554a8..108a9a8e8 100644
--- a/classes/module/Module.php
+++ b/classes/module/Module.php
@@ -171,13 +171,15 @@ abstract class ModuleCore
const CACHE_FILE_TAB_MODULES_LIST = '/config/xml/tab_modules_list.xml';
- const CACHE_FILE_ALL_COUNTRY_MODULES_LIST = '/config/xml/modules_native_addons.xml';
+ // const CACHE_FILE_ALL_COUNTRY_MODULES_LIST = '/config/xml/modules_native_addons.xml';
const CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST = '/config/xml/default_country_modules_list.xml';
const CACHE_FILE_CUSTOMER_MODULES_LIST = '/config/xml/customer_modules_list.xml';
const CACHE_FILE_MUST_HAVE_MODULES_LIST = '/config/xml/must_have_modules_list.xml';
+ const CACHE_FILE_ADDONS_MODULES_LIST = '/config/xml/addons_modules_list.xml';
+
const CACHE_FILE_TRUSTED_MODULES_LIST = '/config/xml/trusted_modules_list.xml';
const CACHE_FILE_UNTRUSTED_MODULES_LIST = '/config/xml/untrusted_modules_list.xml';
@@ -1259,6 +1261,16 @@ public static function getModuleName($module)
return Translate::getModuleTranslation((string)$xml_module->name, Module::configXmlStringFormat($xml_module->displayName), (string)$xml_module->name);
}
+ public static function getModuleInstallVersion($module)
+ {
+ return Db::getInstance()->getRow('
+ SELECT m.`name`, m.`version`, mp.`interest`, module_shop.`enable_device`
+ FROM `'._DB_PREFIX_.'module` m
+ '.Shop::addSqlAssociation('module', 'm', false).'
+ LEFT JOIN `'._DB_PREFIX_.'module_preference` mp ON (mp.`module` = m.`name` AND mp.`id_employee` = '.(int)$id_employee.')
+ WHERE m.`name` = "'.pSQL($module).'"');
+ }
+
protected static function useTooMuchMemory()
{
$memory_limit = Tools::getMemoryLimit();
@@ -1297,7 +1309,7 @@ public static function getModulesOnDisk($use_config = false, $logged_on_addons =
$result = Db::getInstance()->executeS('
SELECT m.name, m.version, mp.interest, module_shop.enable_device
FROM `'._DB_PREFIX_.'module` m
- '.Shop::addSqlAssociation('module', 'm').'
+ '.Shop::addSqlAssociation('module', 'm', false).'
LEFT JOIN `'._DB_PREFIX_.'module_preference` mp ON (mp.`module` = m.`name` AND mp.`id_employee` = '.(int)$id_employee.')');
foreach ($result as $row) {
$modules_installed[$row['name']] = $row;
@@ -1364,7 +1376,21 @@ public static function getModulesOnDisk($use_config = false, $logged_on_addons =
$item->active = 0;
$item->onclick_option = false;
- $item->trusted = Module::isModuleTrusted($item->name);
+ $item->url = false;
+ $item->is_native = false;
+
+ if (defined('_PS_HOST_MODE_') && in_array($item->name, self::$hosted_modules_blacklist)) {
+ continue;
+ } elseif (isset($modules_installed[$item->name])) {
+ $item->installed = true;
+ $item->database_version = $modules_installed[$item->name]['version'];
+ $item->interest = $modules_installed[$item->name]['interest'];
+ $item->enable_device = $modules_installed[$item->name]['enable_device'];
+ } else {
+ $item->installed = false;
+ $item->database_version = 0;
+ $item->interest = 0;
+ }
$module_list[] = $item;
@@ -1417,7 +1443,6 @@ public static function getModulesOnDisk($use_config = false, $logged_on_addons =
$item->is_configurable = $tmp_module->is_configurable = method_exists($tmp_module, 'getContent') ? 1 : 0;
$item->need_instance = isset($tmp_module->need_instance) ? $tmp_module->need_instance : 0;
$item->active = $tmp_module->active;
- $item->trusted = Module::isModuleTrusted($tmp_module->name);
$item->currencies = isset($tmp_module->currencies) ? $tmp_module->currencies : null;
$item->currencies_mode = isset($tmp_module->currencies_mode) ? $tmp_module->currencies_mode : null;
$item->confirmUninstall = isset($tmp_module->confirmUninstall) ? html_entity_decode($tmp_module->confirmUninstall) : null;
@@ -1429,6 +1454,7 @@ public static function getModulesOnDisk($use_config = false, $logged_on_addons =
$item->badges = isset($tmp_module->badges) ? (array)$tmp_module->badges : null;
$item->url = isset($tmp_module->url) ? $tmp_module->url : null;
$item->onclick_option = method_exists($module, 'onclickOption') ? true : false;
+ $item->is_native = false;
if ($item->onclick_option) {
$href = Context::getContext()->link->getAdminLink('Module', true).'&module_name='.$tmp_module->name.'&tab_module='.$tmp_module->tab;
@@ -1440,6 +1466,19 @@ public static function getModulesOnDisk($use_config = false, $logged_on_addons =
}
}
+ if (defined('_PS_HOST_MODE_') && in_array($item->name, self::$hosted_modules_blacklist)) {
+ continue;
+ } elseif (isset($modules_installed[$item->name])) {
+ $item->installed = true;
+ $item->database_version = $modules_installed[$item->name]['version'];
+ $item->interest = $modules_installed[$item->name]['interest'];
+ $item->enable_device = $modules_installed[$item->name]['enable_device'];
+ } else {
+ $item->installed = false;
+ $item->database_version = 0;
+ $item->interest = 0;
+ }
+
$module_list[] = $item;
if (!$xml_exist || $need_new_config_file) {
@@ -1475,9 +1514,8 @@ public static function getModulesOnDisk($use_config = false, $logged_on_addons =
}
$files_list = array(
+ array('type' => 'addonsModules', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_ADDONS_MODULES_LIST, 'loggedOnAddons' => 0),
array('type' => 'addonsNative', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0),
- array('type' => 'addonsMustHave', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_MUST_HAVE_MODULES_LIST, 'loggedOnAddons' => 0),
- array('type' => 'addonsBought', 'file' => _PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST, 'loggedOnAddons' => 1),
);
foreach ($files_list as $f) {
if (file_exists($f['file']) && ($f['loggedOnAddons'] == 0 || $logged_on_addons)) {
@@ -1497,90 +1535,20 @@ public static function getModulesOnDisk($use_config = false, $logged_on_addons =
if (Tools::strtolower($m->name) == Tools::strtolower($modaddons->name) && !isset($m->available_on_addons)) {
$flag_found = 1;
if ($m->version != $modaddons->version && version_compare($m->version, $modaddons->version) === -1) {
- $module_list[$k]->version_addons = $modaddons->version;
- }
- }
- }
-
- if ($flag_found == 0) {
- $item = new stdClass();
- $item->id = 0;
- $item->warning = '';
- $item->type = strip_tags((string)$f['type']);
- $item->name = strip_tags((string)$modaddons->name);
- $item->version = strip_tags((string)$modaddons->version);
- $item->tab = strip_tags((string)$modaddons->tab);
- $item->displayName = strip_tags((string)$modaddons->displayName);
- $item->description = stripslashes(strip_tags((string)$modaddons->description));
- $item->description_full = stripslashes(strip_tags((string)$modaddons->description_full));
- $item->author = strip_tags((string)$modaddons->author);
- $item->limited_countries = array();
- $item->parent_class = '';
- $item->onclick_option = false;
- $item->is_configurable = 0;
- $item->need_instance = 0;
- $item->not_on_disk = 1;
- $item->available_on_addons = 1;
- $item->trusted = Module::isModuleTrusted($item->name);
- $item->active = 0;
- $item->description_full = stripslashes($modaddons->description_full);
- $item->additional_description = isset($modaddons->additional_description) ? stripslashes($modaddons->additional_description) : null;
- $item->compatibility = isset($modaddons->compatibility) ? (array)$modaddons->compatibility : null;
- $item->nb_rates = isset($modaddons->nb_rates) ? (array)$modaddons->nb_rates : null;
- $item->avg_rate = isset($modaddons->avg_rate) ? (array)$modaddons->avg_rate : null;
- $item->badges = isset($modaddons->badges) ? (array)$modaddons->badges : null;
- $item->url = isset($modaddons->url) ? $modaddons->url : null;
-
- if (isset($modaddons->img)) {
- if (!file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) {
- if (!file_put_contents(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg', Tools::file_get_contents($modaddons->img))) {
- copy(_PS_IMG_DIR_.'404.gif', _PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg');
- }
+ $module_list[$k]->version_addons = strip_tags((string)$modaddons->version);
}
+ $module_list[$k]->url = isset($modaddons->url) ? strip_tags((string)$modaddons->url) : null;
- if (file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) {
- $item->image = '../img/tmp/'.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg';
+ if ($f['type'] == 'addonsNative') {
+ $module_list[$k]->is_native = true;
}
}
-
- if ($item->type == 'addonsMustHave') {
- $item->addons_buy_url = strip_tags((string)$modaddons->url);
- $prices = (array)$modaddons->price;
- $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT');
-
- foreach ($prices as $currency => $price) {
- if ($id_currency = Currency::getIdByIsoCode($currency)) {
- $item->price = (float)$price;
- $item->id_currency = (int)$id_currency;
-
- if ($id_default_currency == $id_currency) {
- break;
- }
- }
- }
- }
-
- $module_list[$modaddons->id.'-'.$item->name] = $item;
}
}
}
}
}
- foreach ($module_list as $key => &$module) {
- if (defined('_PS_HOST_MODE_') && in_array($module->name, self::$hosted_modules_blacklist)) {
- unset($module_list[$key]);
- } elseif (isset($modules_installed[$module->name])) {
- $module->installed = true;
- $module->database_version = $modules_installed[$module->name]['version'];
- $module->interest = $modules_installed[$module->name]['interest'];
- $module->enable_device = $modules_installed[$module->name]['enable_device'];
- } else {
- $module->installed = false;
- $module->database_version = 0;
- $module->interest = 0;
- }
- }
usort($module_list, function ($a, $b) { return strnatcasecmp($a->displayName, $b->displayName); });
if ($errors) {
if (!isset(Context::getContext()->controller) && !Context::getContext()->controller->controller_name) {
@@ -1622,6 +1590,91 @@ public static function getModulesDirOnDisk()
return $module_list;
}
+ public static function getInstalledModulesOnDisk($use_config = false, $logged_on_addons = false, $id_employee = false)
+ {
+ $modules = self::getModulesOnDisk($use_config, $logged_on_addons, $id_employee);
+ return array_filter($modules, function($m) {
+ return $m->installed;
+ });
+ }
+
+ public static function getSuggestedModules()
+ {
+ $files_list = array(
+ array('type' => 'addonsMustHave', 'file' => _PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 'loggedOnAddons' => 0),
+ array('type' => 'addonsNative', 'file' => _PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0),
+ );
+ $module_list = array();
+ foreach ($files_list as $f) {
+ $file = $f['file'];
+ $content = Tools::file_get_contents($file);
+ $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA);
+ if ($xml && isset($xml->module)) {
+ foreach ($xml->module as $modaddons) {
+ $item = new stdClass();
+ $item->id = 0;
+ $item->warning = '';
+ $item->type = strip_tags((string)$f['type']);
+ $item->name = strip_tags((string)$modaddons->name);
+ $item->version = strip_tags((string)$modaddons->version);
+ $item->tab = strip_tags((string)$modaddons->tab);
+ $item->displayName = strip_tags((string)$modaddons->displayName);
+ $item->description = stripslashes(strip_tags((string)$modaddons->description));
+ $item->description_full = stripslashes(strip_tags((string)$modaddons->description_full));
+ $item->author = strip_tags((string)$modaddons->author);
+ $item->limited_countries = array();
+ $item->parent_class = '';
+ $item->onclick_option = false;
+ $item->is_configurable = 0;
+ $item->need_instance = 0;
+ $item->not_on_disk = 1;
+ $item->available_on_addons = 1;
+ $item->active = 0;
+ $item->description_full = stripslashes($modaddons->description_full);
+ $item->additional_description = isset($modaddons->additional_description) ? stripslashes($modaddons->additional_description) : null;
+ $item->compatibility = isset($modaddons->compatibility) ? (array)$modaddons->compatibility : null;
+ $item->nb_rates = isset($modaddons->nb_rates) ? (array)$modaddons->nb_rates : null;
+ $item->avg_rate = isset($modaddons->avg_rate) ? (array)$modaddons->avg_rate : null;
+ $item->badges = isset($modaddons->badges) ? (array)$modaddons->badges : null;
+ $item->url = isset($modaddons->url) ? $modaddons->url : null;
+ $item->is_native = false;
+
+ if (isset($modaddons->img)) {
+ if (!file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) {
+ if (!file_put_contents(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg', Tools::file_get_contents($modaddons->img))) {
+ copy(_PS_IMG_DIR_.'404.gif', _PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg');
+ }
+ }
+
+ if (file_exists(_PS_TMP_IMG_DIR_.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg')) {
+ $item->image = '../img/tmp/'.md5((int)$modaddons->id.'-'.$modaddons->name).'.jpg';
+ }
+ }
+
+ if ($item->type == 'addonsMustHave') {
+ $item->addons_buy_url = strip_tags((string)$modaddons->url);
+ $prices = (array)$modaddons->price;
+ $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT');
+
+ foreach ($prices as $currency => $price) {
+ if ($id_currency = Currency::getIdByIsoCode($currency)) {
+ $item->price = (float)$price;
+ $item->id_currency = (int)$id_currency;
+
+ if ($id_default_currency == $id_currency) {
+ break;
+ }
+ }
+ }
+ }
+
+ $module_list[$modaddons->id.'-'.$item->name] = $item;
+ }
+ }
+ }
+ $module_list = array_values($module_list);
+ return $module_list;
+ }
/**
* Return non native module
@@ -1641,7 +1694,7 @@ public static function getNonNativeModuleList()
$arr_native_modules = array();
if (is_array($native_modules)) {
foreach ($native_modules as $native_modules_type) {
- if (in_array($native_modules_type['type'], array('native', 'partner'))) {
+ if (in_array($native_modules_type['type'], array('native', 'disk', 'partner'))) {
$arr_native_modules[] = '""';
foreach ($native_modules_type->module as $module) {
$arr_native_modules[] = '"'.pSQL($module['name']).'"';
@@ -1710,7 +1763,7 @@ public static function getModulesInstalled($position = 0)
* @param string $key The key provided by addons
* @return int
*/
- final public static function isModuleTrusted($module_name)
+ final public static function isModuleTrusted($module_name, $check_api = true)
{
static $trusted_modules_list_content = null;
static $modules_list_content = null;
@@ -1724,7 +1777,7 @@ final public static function isModuleTrusted($module_name)
// we use the file, otherwise we regenerate it
if (!(file_exists(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST)
&& filesize(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST) > 0
- && ((time() - filemtime(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST)) < 86400)
+ && ((time() - filemtime(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST)) < _TIME_1_DAY_)
)) {
self::generateTrustedXml();
}
@@ -1748,8 +1801,6 @@ final public static function isModuleTrusted($module_name)
$untrusted_modules_list_content = Tools::file_get_contents(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST);
}
- $objModule = Module::getInstanceByName($module_name);
-
// If the module is trusted, which includes both partner modules and modules bought on Addons
if (stripos($trusted_modules_list_content, $module_name) !== false) {
@@ -1769,10 +1820,11 @@ final public static function isModuleTrusted($module_name)
// If the module isn't in one of the xml files
// It might have been uploaded recenlty so we check
// Addons API and clear XML files to be regenerated next time
- Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST);
- Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST);
-
- return (int)Module::checkModuleFromAddonsApi($module_name);
+ if ($check_api) {
+ Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_TRUSTED_MODULES_LIST);
+ Tools::deleteFile(_PS_ROOT_DIR_.self::CACHE_FILE_UNTRUSTED_MODULES_LIST);
+ return (int)Module::checkModuleFromAddonsApi($module_name);
+ }
}
}
@@ -1787,9 +1839,11 @@ final public static function generateTrustedXml()
$untrusted = array();
$trusted_modules_xml = array(
- _PS_ROOT_DIR_.self::CACHE_FILE_ALL_COUNTRY_MODULES_LIST,
- _PS_ROOT_DIR_.self::CACHE_FILE_MUST_HAVE_MODULES_LIST,
- );
+ // _PS_ROOT_DIR_.self::CACHE_FILE_ALL_COUNTRY_MODULES_LIST,
+ _PS_ROOT_DIR_.self::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST,
+ _PS_ROOT_DIR_.self::CACHE_FILE_MUST_HAVE_MODULES_LIST,
+ _PS_ROOT_DIR_.self::CACHE_FILE_ADDONS_MODULES_LIST,
+ );
if (file_exists(_PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST)) {
$trusted_modules_xml[] = _PS_ROOT_DIR_.self::CACHE_FILE_CUSTOMER_MODULES_LIST;
@@ -1874,12 +1928,12 @@ final public static function checkModuleFromAddonsApi($module_name)
if (!is_object($obj)) {
return false;
- } elseif ($obj->module_key === '') {
- return false;
+ // } elseif ($obj->module_key === '') {
+ // return false;
} else {
$params = array(
'module_name' => $obj->name,
- 'module_key' => $obj->module_key,
+ // 'module_key' => $obj->module_key,
);
$xml = Tools::addonsRequest('check_module', $params);
return (bool)(strpos($xml, 'success') !== false);
diff --git a/config/config.inc.php b/config/config.inc.php
index c9b3f60ca..880d0fc41 100644
--- a/config/config.inc.php
+++ b/config/config.inc.php
@@ -77,6 +77,8 @@
include_once(_PS_TOOL_DIR_.'profiling/Tools.php');
}
+require_once (_PS_ROOT_DIR_.'/modules/hotelreservationsystem/define.php');
+
if (Tools::convertBytes(ini_get('upload_max_filesize')) < Tools::convertBytes('100M')) {
ini_set('upload_max_filesize', '100M');
}
@@ -264,4 +266,5 @@
define('_MEDIA_SERVER_3_', Configuration::get('PS_MEDIA_SERVER_3'));
}
-require_once (_PS_ROOT_DIR_.'/modules/hotelreservationsystem/define.php');
\ No newline at end of file
+define('_TIME_1_DAY_', 86400);
+define('_TIME_1_WEEK_', 604800);
\ No newline at end of file
diff --git a/config/defines_uri.inc.php b/config/defines_uri.inc.php
index 19b2fd530..142d80a55 100644
--- a/config/defines_uri.inc.php
+++ b/config/defines_uri.inc.php
@@ -84,5 +84,5 @@
Tools::safeDefine('_PS_API_URL_', 'http://'._PS_API_DOMAIN_);
Tools::safeDefine('_PS_CURRENCY_FEED_URL_', _PS_API_URL_.'/xml/currencies.xml');
Tools::safeDefine('_QLO_API_DOMAIN_', 'api.qloapps.com');
-Tools::safeDefine('_QLO_API_URL_', 'http://'._QLO_API_DOMAIN_);
+Tools::safeDefine('_QLO_API_URL_', 'https://'._QLO_API_DOMAIN_);
Tools::safeDefine('_QLO_TAB_MODULE_LIST_URL_', _QLO_API_URL_.'/xml/tab_modules_list.xml');
diff --git a/controllers/admin/AdminDashboardController.php b/controllers/admin/AdminDashboardController.php
index 8a458273c..a5f6f871f 100644
--- a/controllers/admin/AdminDashboardController.php
+++ b/controllers/admin/AdminDashboardController.php
@@ -26,6 +26,9 @@
class AdminDashboardControllerCore extends AdminController
{
+
+ const DASHBOARD_RECOMMENDATION_CONTENT = '/cache/dashboard_recommendation.html';
+
public function __construct()
{
$this->bootstrap = true;
@@ -282,6 +285,15 @@ public function renderView()
'hotel_name' => $objHotelBranchInfo->hotel_name.', '.$hotelAddressInfo['city'],
);
}
+
+ if (file_exists(_PS_ROOT_DIR_.Upgrader::CACHE_FILE_UPGRADE_AVAILABE)) {
+ $content = Tools::file_get_contents( _PS_ROOT_DIR_.Upgrader::CACHE_FILE_UPGRADE_AVAILABE);
+ $upgradeInfo = simplexml_load_string($content);
+ $this->context->smarty->assign(array(
+ 'upgrade_info' => $upgradeInfo
+ ));
+ }
+
$this->tpl_view_vars = array(
'date_from' => $this->context->employee->stats_date_from,
'date_to' => $this->context->employee->stats_date_to,
@@ -294,7 +306,7 @@ public function renderView()
//'translations' => $translations,
'action' => self::$currentIndex.'&token='.$this->token,
'warning' => $this->getWarningDomainName(),
- 'new_version_url' => Tools::getCurrentUrlProtocolPrefix()._PS_API_DOMAIN_.'/version/check_version.php?v='._PS_VERSION_.'&lang='.$this->context->language->iso_code.'&autoupgrade='.(int)(Module::isInstalled('autoupgrade') && Module::isEnabled('autoupgrade')).'&hosted_mode='.(int)defined('_PS_HOST_MODE_'),
+ 'new_version_url' => Tools::getCurrentUrlProtocolPrefix()._QLO_API_DOMAIN_.'/index.php?version='._QLOAPPS_VERSION_.'&lang='.$this->context->language->iso_code.'&method=check-version&autoupgrade='.(int)(Module::isInstalled('qloautoupgrade') && Module::isEnabled('qloautoupgrade')).'&hosted_mode='.(int)defined('_PS_HOST_MODE_'),
'dashboard_use_push' => Configuration::get('PS_DASHBOARD_USE_PUSH'),
'calendar' => $calendar_helper->generate(),
'PS_DASHBOARD_SIMULATION' => Configuration::get('PS_DASHBOARD_SIMULATION'),
@@ -411,7 +423,7 @@ public function ajaxProcessSetSimulationMode()
public function ajaxProcessGetBlogRss()
{
$return = array('has_errors' => false, 'rss' => array());
- if (!$this->isFresh('/config/xml/blog-'.$this->context->language->iso_code.'.xml', 86400)) {
+ if (!$this->isFresh('/config/xml/blog-'.$this->context->language->iso_code.'.xml', _TIME_1_DAY_)) {
if (!$this->refresh('/config/xml/blog-'.$this->context->language->iso_code.'.xml', _PS_API_URL_.'/rss/blog/blog-'.$this->context->language->iso_code.'.xml')) {
$return['has_errors'] = true;
}
@@ -506,4 +518,25 @@ public function ajaxProcessSaveDashConfig()
die(json_encode($return));
}
+
+ public function ajaxProcessGetRecommendationContent()
+ {
+ $response = array('success' => false);
+ if ($content = $this->getRecommendationContent()) {
+ $response['success'] = true;
+ $response['content'] = $content;
+ }
+ $this->ajaxDie(json_encode($response));
+ }
+
+ public function getRecommendationContent()
+ {
+ if (!$this->isFresh(self::DASHBOARD_RECOMMENDATION_CONTENT, _TIME_1_DAY_)) {
+ @file_put_contents(_PS_ROOT_DIR_.self::DASHBOARD_RECOMMENDATION_CONTENT, Tools::addonsRequest('dashboard-recommendation'));
+ }
+ if (file_exists(_PS_ROOT_DIR_.self::DASHBOARD_RECOMMENDATION_CONTENT)) {
+ return Tools::file_get_contents(_PS_ROOT_DIR_.self::DASHBOARD_RECOMMENDATION_CONTENT);
+ }
+ return false;
+ }
}
diff --git a/controllers/admin/AdminEmailsController.php b/controllers/admin/AdminEmailsController.php
index 6ddddcec9..b933780ad 100644
--- a/controllers/admin/AdminEmailsController.php
+++ b/controllers/admin/AdminEmailsController.php
@@ -278,7 +278,6 @@ public function initContent()
$this->initTabModuleList();
$this->initToolbar();
$this->initPageHeaderToolbar();
- $this->addToolBarModulesListButton();
unset($this->toolbar_btn['save']);
$back = $this->context->link->getAdminLink('AdminDashboard');
diff --git a/controllers/admin/AdminModulesCatalogController.php b/controllers/admin/AdminModulesCatalogController.php
new file mode 100644
index 000000000..071bb0756
--- /dev/null
+++ b/controllers/admin/AdminModulesCatalogController.php
@@ -0,0 +1,332 @@
+
+* @copyright 2010-2020 Webkul IN
+* @license https://store.webkul.com/license.html
+*/
+
+class AdminModulesCatalogControllerCore extends AdminController
+{
+
+ public $modules;
+
+ const CATALOG_RECOMMENDATION_CONTENT = '/cache/catalog_recommendation.html';
+
+ const ELEMENT_TYPE_MODULE = 1;
+ const ELEMENT_TYPE_THEME = 2;
+
+ const MODULES_PER_PAGE = 18;
+
+ public function __construct()
+ {
+ $this->bootstrap = true;
+ parent::__construct();
+ }
+
+ public function init()
+ {
+ parent::init();
+ $this->initSuggestedModulesList();
+ }
+
+ public function initContent()
+ {
+ parent::initContent();
+
+ $suggestedModules = Module::getSuggestedModules();
+
+ $modulesToAdd = array();
+ $dirModules = ModuleCore::getModulesOnDisk();
+ $modules_name = array_column($suggestedModules, 'name');
+ foreach ($dirModules as $mod) {
+ if (($id = array_search($mod->name, $modules_name)) !== false) {
+ if ($mod->installed) {
+ unset($suggestedModules[$id]);
+ } else {
+ $suggestedModules[$id]->not_on_disk = false;
+ }
+ } else {
+ if (!$mod->installed) {
+ $modulesToAdd[] = $mod;
+ }
+ }
+ }
+
+ $modules = array_merge($suggestedModules, $modulesToAdd);
+
+ $link_admin_modules = $this->context->link->getAdminLink('AdminModules', true);
+ foreach ($modules as $key => $module) {
+ $module->options['install_url'] = $link_admin_modules.'&install='.urlencode($module->name).'&tab_module='.$module->tab.'&module_name='.$module->name.'&anchor='.ucfirst($module->name);
+ $module->element_type = self::ELEMENT_TYPE_MODULE;
+ $module->logo = '../../img/questionmark.png';
+
+ if (@filemtime(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.basename(_PS_MODULE_DIR_).DIRECTORY_SEPARATOR.$module->name
+ .DIRECTORY_SEPARATOR.'logo.gif')) {
+ $module->logo = 'logo.gif';
+ }
+ if (@filemtime(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.basename(_PS_MODULE_DIR_).DIRECTORY_SEPARATOR.$module->name
+ .DIRECTORY_SEPARATOR.'logo.png')) {
+ $module->logo = 'logo.png';
+ }
+
+ $modules[$key] = $module;
+ }
+
+ $this->sortList($modules, 'module');
+ $this->modules = $modules;
+
+ $this->themes = $this->getSuggestedThemes();
+
+ $this->assignSortCriteria();
+
+ $this->context->smarty->assign(array(
+ 'modules' => $this->modules,
+ 'themes' => $this->themes,
+ 'modules_uri' => __PS_BASE_URI__.basename(_PS_MODULE_DIR_),
+ 'element_type_module' => self::ELEMENT_TYPE_MODULE,
+ 'element_type_theme' => self::ELEMENT_TYPE_THEME,
+
+ ));
+ }
+
+ public function initModal()
+ {
+ parent::initModal();
+
+ $modal_content = $this->context->smarty->fetch('controllers/modules/'.(($this->context->mode == Context::MODE_HOST) ? 'modal_not_trusted_blocked.tpl' : 'modal_not_trusted.tpl'));
+ $this->modals[] = array(
+ 'modal_id' => 'moduleNotTrusted',
+ 'modal_class' => 'modal-lg',
+ 'modal_title' => ($this->context->mode == Context::MODE_HOST) ? $this->l('This module cannot be installed') : $this->l('Important Notice'),
+ 'modal_content' => $modal_content
+ );
+ }
+
+ public function assignSortCriteria()
+ {
+ $sortCriterta = array(
+ array (
+ 'key' => 'popularity',
+ 'value' => 'popularity',
+ 'title' => $this->l('Popularity')
+ ),
+ array (
+ 'key' => 'name',
+ 'value' => 'name',
+ 'title' => $this->l('Name')
+ ),
+ array (
+ 'key' => 'price_increasing',
+ 'value' => 'price_increasing',
+ 'title' => $this->l('Price (low to high)')
+ ),
+ array (
+ 'key' => 'price_decreasing',
+ 'value' => 'price_decreasing',
+ 'title' => $this->l('Price (high to low)')
+ ),
+ );
+ $this->context->smarty->assign(array(
+ 'sort_criterta' => $sortCriterta,
+ 'module_sort' => Configuration::get('PS_SORT_MODULE_MODULES_CATALOG_'.(int)$this->context->employee->id),
+ 'theme_sort' => Configuration::get('PS_SORT_THEME_MODULES_CATALOG_'.(int)$this->context->employee->id),
+ ));
+ }
+
+ public function getSuggestedThemes()
+ {
+ $installedThemes = array();
+ $themes = Theme::getAllThemes()->getAll();
+ foreach ($themes as $theme) {
+ $installedThemes[] = Theme::getThemeInfo($theme->id);
+ }
+ $files_list = array(
+ array('type' => 'addonsMustHave', 'file' => _PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 'loggedOnAddons' => 0),
+ );
+
+ $theme_list = array();
+ foreach ($files_list as $f) {
+ $file = $f['file'];
+ $content = Tools::file_get_contents($file);
+ $xml = @simplexml_load_string($content, null, LIBXML_NOCDATA);
+ if ($xml && isset($xml->theme)) {
+ foreach ($xml->theme as $modthemes) {
+ foreach ($installedThemes as $theme) {
+ if ($theme['theme_name'] == $modthemes->name)
+ continue;
+ $item = new stdClass();
+ $item->id = 0;
+ $item->warning = '';
+ $item->type = strip_tags((string)$f['type']);
+ $item->element_type = self::ELEMENT_TYPE_THEME;
+ $item->name = strip_tags((string)$modthemes->name);
+ $item->version = strip_tags((string)$modthemes->version);
+ $item->displayName = strip_tags((string)$modthemes->displayName);
+ $item->description = stripslashes(strip_tags((string)$modthemes->description));
+ $item->description_full = stripslashes(strip_tags((string)$modthemes->description_full));
+ $item->author = strip_tags((string)$modthemes->author);
+ $item->limited_countries = array();
+ $item->parent_class = '';
+ $item->onclick_option = false;
+ $item->available_on_addons = 1;
+ $item->active = 0;
+ $item->additional_description = isset($modthemes->additional_description) ? stripslashes($modthemes->additional_description) : null;
+ $item->compatibility = isset($modthemes->compatibility) ? (array)$modthemes->compatibility : null;
+ $item->nb_rates = isset($modthemes->nb_rates) ? (array)$modthemes->nb_rates : null;
+ $item->avg_rate = isset($modthemes->avg_rate) ? (array)$modthemes->avg_rate : null;
+ $item->badges = isset($modthemes->badges) ? (array)$modthemes->badges : null;
+ $item->url = isset($modthemes->url) ? $modthemes->url : null;
+
+ if (isset($modthemes->img)) {
+ if (!file_exists(_PS_TMP_IMG_DIR_.md5((int)$modthemes->id.'-'.$modthemes->name).'.jpg')) {
+ if (!file_put_contents(_PS_TMP_IMG_DIR_.md5((int)$modthemes->id.'-'.$modthemes->name).'.jpg', Tools::file_get_contents($modthemes->img))) {
+ copy(_PS_IMG_DIR_.'404.gif', _PS_TMP_IMG_DIR_.md5((int)$modthemes->id.'-'.$modthemes->name).'.jpg');
+ }
+ }
+
+ if (file_exists(_PS_TMP_IMG_DIR_.md5((int)$modthemes->id.'-'.$modthemes->name).'.jpg')) {
+ $item->image = '../img/tmp/'.md5((int)$modthemes->id.'-'.$modthemes->name).'.jpg';
+ }
+ }
+
+ if ($item->type == 'addonsMustHave') {
+ $item->addons_buy_url = strip_tags((string)$modthemes->url);
+ $prices = (array)$modthemes->price;
+ $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT');
+
+ foreach ($prices as $currency => $price) {
+ if ($id_currency = Currency::getIdByIsoCode($currency)) {
+ $item->price = (float)$price;
+ $item->id_currency = (int)$id_currency;
+
+ if ($id_default_currency == $id_currency) {
+ break;
+ }
+ }
+ }
+ }
+ $theme_list[$modthemes->id.'-'.$item->name] = $item;
+ }
+ }
+ }
+ }
+ $theme_list = array_values($theme_list);
+ $this->sortList($theme_list, 'theme');
+
+ return $theme_list;
+ }
+
+ public function initToolbar()
+ {
+ parent::initToolbar();
+ $this->page_header_toolbar_btn['addons'] = array(
+ 'href' => 'https://qloapps.com/addons/',
+ 'desc' => $this->l('Explore all Addons'),
+ 'imgclass' => 'modules-list',
+ 'target' => true
+ );
+ }
+
+ public function getRecommendationContent()
+ {
+ if (!$this->isFresh(self::CATALOG_RECOMMENDATION_CONTENT, _TIME_1_DAY_)) {
+ @file_put_contents(_PS_ROOT_DIR_.self::CATALOG_RECOMMENDATION_CONTENT, Tools::addonsRequest('catalog-recommendation'));
+ }
+ if (file_exists(_PS_ROOT_DIR_.self::CATALOG_RECOMMENDATION_CONTENT)) {
+ return Tools::file_get_contents(_PS_ROOT_DIR_.self::CATALOG_RECOMMENDATION_CONTENT);
+ }
+ return false;
+ }
+
+ public function sortList(&$list, $type)
+ {
+
+ switch($type) {
+ case 'module':
+ $criteria = Configuration::get('PS_SORT_MODULE_MODULES_CATALOG_'.(int)$this->context->employee->id);
+ break;
+ case 'theme':
+ $criteria = Configuration::get('PS_SORT_THEME_MODULES_CATALOG_'.(int)$this->context->employee->id);
+ break;
+ }
+ if ($criteria != 'popularity') {
+ usort($list, function($a, $b) use($criteria){
+ if ($criteria == 'name') {
+ return strnatcasecmp($a->displayName, $b->displayName);
+ } else if ($criteria == 'price_increasing') {
+ if (isset($a->price) && isset($b->price))
+ return $a->price > $b->price;
+ else if (isset($b->price) && $b->price)
+ return true;
+ } else if ($criteria == 'price_decreasing') {
+ if (isset($a->price) && isset($b->price))
+ return $a->price < $b->price;
+ else if (isset($b->price) && $b->price)
+ return true;
+ }
+
+ });
+ }
+ return true;
+ }
+
+ protected function setSorting($module_sorting, $theme_sorting)
+ {
+ Configuration::updateValue('PS_SORT_MODULE_MODULES_CATALOG_'.(int)$this->context->employee->id, $module_sorting);
+ Configuration::updateValue('PS_SORT_THEME_MODULES_CATALOG_'.(int)$this->context->employee->id, $theme_sorting);
+ }
+
+
+ public function ajaxProcessGetRecommendationContent()
+ {
+ $response = array('success' => false);
+ if ($content = $this->getRecommendationContent()) {
+ $response['success'] = true;
+ $response['content'] = $content;
+ }
+ $this->ajaxDie(json_encode($response));
+ }
+
+ public function ajaxProcessSetSorting()
+ {
+ $this->setSorting(Tools::getValue('module_sorting'), Tools::getValue('theme_sorting'));
+ $this->ajaxDie(json_encode(array(
+ 'success' => true
+ )));
+ }
+
+
+ protected function initSuggestedModulesList()
+ {
+ if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, _TIME_1_DAY_)) {
+ file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native'));
+ }
+
+ if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, _TIME_1_DAY_)) {
+ @file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have'));
+ }
+ }
+
+ public function setMedia()
+ {
+ parent::setMedia();
+ $this->addJS(_PS_JS_DIR_.'admin/modules_catalog.js');
+ $this->context->controller->addJS(_PS_JS_DIR_.'/twbs-pagination/jquery.twbsPagination.min.js');
+ Media::addJSdef(array(
+ 'num_block_per_page' => self::MODULES_PER_PAGE
+ ));
+ }
+}
\ No newline at end of file
diff --git a/controllers/admin/AdminModulesController.php b/controllers/admin/AdminModulesController.php
index 5e9a41d8a..b385f33f6 100644
--- a/controllers/admin/AdminModulesController.php
+++ b/controllers/admin/AdminModulesController.php
@@ -130,7 +130,9 @@ public function __construct()
foreach ($xml_module->children() as $module) {
/** @var SimpleXMLElement $module */
foreach ($module->attributes() as $key => $value) {
- if ($xml_module->attributes() == 'native' && $key == 'name') {
+ if (($xml_module->attributes() == 'native' || $xml_module->attributes() == 'disk')
+ && $key == 'name'
+ ) {
$this->list_natives_modules[] = (string)$value;
}
if ($xml_module->attributes() == 'partner' && $key == 'name') {
@@ -156,17 +158,22 @@ public function setMedia()
parent::setMedia();
$this->addJqueryPlugin(array('autocomplete', 'fancybox', 'tablefilter'));
- if ($this->context->mode == Context::MODE_HOST && Tools::isSubmit('addnewmodule')) {
+ Media::addjsDef(array(
+ 'remove_uploaded_module_txt' => $this->l('Do you want to remove the uploaded/installed module?'),
+ 'module_install_error_txt' => $this->l('There was an error while installing module.'),
+ ));
+ $this->addJS(_PS_JS_DIR_.'admin/modules.js');
+
+ if ($this->context->mode == Context::MODE_HOST && Tools::isSubmit('addnewmodule')) {
$this->addJS(_PS_JS_DIR_.'admin/addons.js');
}
}
public function ajaxProcessRefreshModuleList($force_reload_cache = false)
{
- $xml_modules_list = _QLO_API_DOMAIN_.'/xml/'.str_replace('.', '', _QLOAPPS_VERSION_).'.xml';
-
// Refresh modules_list.xml every week
- if (!$this->isFresh(Module::CACHE_FILE_MODULES_LIST, 86400) || $force_reload_cache) {
+ if (!$this->isFresh(Module::CACHE_FILE_MODULES_LIST, _TIME_1_DAY_) || $force_reload_cache) {
+ $xml_modules_list = _QLO_API_DOMAIN_.'/xml/'.str_replace('.', '', _QLOAPPS_VERSION_).'.xml';
if ($this->refresh(Module::CACHE_FILE_MODULES_LIST, 'https://'.$xml_modules_list)) {
$this->status = 'refresh';
} elseif ($this->refresh(Module::CACHE_FILE_MODULES_LIST, 'http://'.$xml_modules_list)) {
@@ -180,7 +187,7 @@ public function ajaxProcessRefreshModuleList($force_reload_cache = false)
// If logged to Addons Webservices, refresh default country native modules list every day
if ($this->status != 'error') {
- if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 86400) || $force_reload_cache) {
+ if (!$this->isFresh(Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, _TIME_1_DAY_) || $force_reload_cache) {
if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, Tools::addonsRequest('native'))) {
$this->status = 'refresh';
} else {
@@ -190,7 +197,17 @@ public function ajaxProcessRefreshModuleList($force_reload_cache = false)
$this->status = 'cache';
}
- if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 86400) || $force_reload_cache) {
+ if (!$this->isFresh(Module::CACHE_FILE_ADDONS_MODULES_LIST, _TIME_1_DAY_) || $force_reload_cache) {
+ if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_ADDONS_MODULES_LIST, Tools::addonsRequest('addons-modules'))) {
+ $this->status = 'refresh';
+ } else {
+ $this->status = 'error';
+ }
+ } else {
+ $this->status = 'cache';
+ }
+
+ if (!$this->isFresh(Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, _TIME_1_DAY_) || $force_reload_cache) {
if (file_put_contents(_PS_ROOT_DIR_.Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, Tools::addonsRequest('must-have'))) {
$this->status = 'refresh';
} else {
@@ -213,6 +230,7 @@ public function ajaxProcessRefreshModuleList($force_reload_cache = false)
$this->status = 'cache';
}
}
+ Module::generateTrustedXml();
}
public function displayAjaxRefreshModuleList()
@@ -268,19 +286,29 @@ public function ajaxProcessReloadModulesList()
public function ajaxProcessGetTabModulesList()
{
- $tab_modules_list = Tools::getValue('tab_modules_list');
+ // $tab_modules_list = Tools::getValue('tab_modules_list');
+ $conrollerClass = Tools::getValue('controller_class');
+ $controllerId = Tab::getIdFromClassName($conrollerClass);
+
+ if (!Tab::isTabModuleListAvailable()) {
+ $this->ajaxProcessRefreshModuleList();
+ }
+
+ if ($tab_modules_list = Tab::getTabModulesList($controllerId)) {
+ $tab_modules_list = $this->filterTabModuleList($tab_modules_list);
+ }
+
$back = Tools::getValue('back_tab_modules_list');
if ($back) {
$back .= '&tab_modules_open=1';
}
$modules_list = array('installed' =>array(), 'not_installed' => array());
- if ($tab_modules_list) {
- $tab_modules_list = explode(',', $tab_modules_list);
- $modules_list_unsort = $this->getModulesByInstallation($tab_modules_list);
+ if (count($tab_modules_list['slider_list'])) {
+ $modules_list_unsort = $this->getModulesByInstallation($tab_modules_list['slider_list']);
}
$installed = $uninstalled = array();
- foreach ($tab_modules_list as $key => $value) {
+ foreach ($tab_modules_list['slider_list'] as $key => $value) {
$continue = 0;
foreach ($modules_list_unsort['installed'] as $mod_in) {
if ($mod_in->name == $value) {
@@ -551,7 +579,7 @@ public function postProcessReset()
}
}
- public function postProcessDownload()
+ public function postProcessDownload($redirect = true)
{
/* PrestaShop demo mode */
if (_PS_MODE_DEMO_ || ($this->context->mode == Context::MODE_HOST)) {
@@ -593,7 +621,7 @@ public function postProcessDownload()
} elseif (!move_uploaded_file($_FILES['file']['tmp_name'], _PS_MODULE_DIR_.$_FILES['file']['name'])) {
$this->errors[] = Tools::displayError('An error occurred while copying the archive to the module directory.');
} else {
- $this->extractArchive(_PS_MODULE_DIR_.$_FILES['file']['name']);
+ $this->extractArchive(_PS_MODULE_DIR_.$_FILES['file']['name'], $redirect);
}
} else {
$this->errors[] = Tools::displayError('You do not have permission to add this.');
@@ -709,12 +737,9 @@ public function postProcessCallback()
return;
}
- if ($key == 'check') {
- $this->ajaxProcessRefreshModuleList(true);
- } elseif ($key == 'checkAndUpdate') {
+ if ($key == 'checkAndUpdate') {
$modules = array();
- $this->ajaxProcessRefreshModuleList(true);
- $modules_on_disk = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee);
+ $modules_on_disk = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee, true);
// Browse modules list
foreach ($modules_on_disk as $km => $module_on_disk) {
@@ -769,6 +794,7 @@ public function postProcessCallback()
array('type' => 'addonsNative', 'file' => Module::CACHE_FILE_DEFAULT_COUNTRY_MODULES_LIST, 'loggedOnAddons' => 0),
// array('type' => 'addonsBought', 'file' => Module::CACHE_FILE_CUSTOMER_MODULES_LIST, 'loggedOnAddons' => 1),
// array('type' => 'addonsMustHave', 'file' => Module::CACHE_FILE_MUST_HAVE_MODULES_LIST, 'loggedOnAddons' => 1),
+ array('type' => 'addonsMustHave', 'file' => Module::CACHE_FILE_ADDONS_MODULES_LIST, 'loggedOnAddons' => 1),
);
foreach ($files_list as $f) {
@@ -782,6 +808,9 @@ public function postProcessCallback()
$module_to_update[$name]['name'] = $modaddons->name;
$module_to_update[$name]['displayName'] = $modaddons->displayName;
$module_to_update[$name]['need_loggedOnAddons'] = $f['loggedOnAddons'];
+ if ($modaddons->url) {
+ $module_to_update[$name]['url'] = $modaddons->url;
+ }
}
}
}
@@ -790,7 +819,8 @@ public function postProcessCallback()
foreach ($module_to_update as $name => $attr) {
if ((is_null($attr) && $this->logged_on_addons == 0) || ($attr['need_loggedOnAddons'] == 1 && $this->logged_on_addons == 0)) {
- $this->errors[] = sprintf(Tools::displayError('You need to be logged in to your PrestaShop Addons account in order to update the %s module. %s'), ''.$name.'', ''.$this->l('Click here to log in.').'');
+ $this->errors[] = sprintf(Tools::displayError('You need to be download this module from store in order to update the %s module. %s'), ''.$name.'', ''.$this->l('Click here to download.').'');
+ // $this->errors[] = sprintf(Tools::displayError('You need to be logged in to your PrestaShop Addons account in order to update the %s module. %s'), ''.$name.'', ''.$this->l('Click here to log in.').'');
} elseif (!is_null($attr['name'])) {
$download_ok = false;
if ($attr['need_loggedOnAddons'] == 0 && file_put_contents(_PS_MODULE_DIR_.$name.'.zip', Tools::addonsRequest('module', array('module_name' => pSQL($attr['name']))))) {
@@ -1041,7 +1071,8 @@ public function postProcessCallback()
protected function getModulesByInstallation($tab_modules_list = null)
{
- $all_modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee);
+ // $all_modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee);
+ $all_modules = Module::getSuggestedModules();
$all_unik_modules = array();
$modules_list = array('installed' =>array(), 'not_installed' => array());
@@ -1426,12 +1457,13 @@ public function initContent()
}
// Retrieve Modules List
- $modules = Module::getModulesOnDisk(true, $this->logged_on_addons, $this->id_employee);
+ $modules = Module::getInstalledModulesOnDisk(true, $this->logged_on_addons, $this->id_employee);
$this->initModulesList($modules);
$this->nb_modules_total = count($modules);
$module_errors = array();
$module_success = array();
$upgrade_available = array();
+ $module_alerts = array();
$dont_filter = false;
//Add succes message for one module update
@@ -1514,7 +1546,7 @@ public function initContent()
$href = Context::getContext()->link->getAdminLink('AdminModules', true).'&module_name='.$module->name.'&tab_module='.$module->tab.'&configure='.$module->name;
$this->context->smarty->assign('text', sprintf($this->l('%1$s: %2$s'), $module->displayName, $module->warning));
$this->context->smarty->assign('module_link', $href);
- $this->displayWarning($this->context->smarty->fetch('controllers/modules/warning_module.tpl'));
+ $module_alerts[] = $this->context->smarty->fetch('controllers/modules/warning_module.tpl');
}
// AutoComplete array
@@ -1540,7 +1572,7 @@ public function initContent()
}
unset($object);
if ($module->installed && isset($module->version_addons) && $module->version_addons) {
- $upgrade_available[] = array('anchor' => ucfirst($module->name), 'name' => $module->name, 'displayName' => $module->displayName);
+ $upgrade_available[] = array('anchor' => ucfirst($module->name), 'name' => $module->name, 'displayName' => $module->displayName, 'is_native' => $module->is_native);
}
if (in_array($module->name, $this->list_partners_modules)) {
@@ -1578,6 +1610,7 @@ public function initContent()
$tpl_vars = array(
'token' => $this->token,
'upgrade_available' => $upgrade_available,
+ 'module_alerts' => $module_alerts,
'currentIndex' => self::$currentIndex,
'dirNameCurrentIndex' => dirname(self::$currentIndex),
'ajaxCurrentIndex' => str_replace('index', 'ajax-tab', self::$currentIndex),
@@ -1648,4 +1681,192 @@ public function ajaxProcessGetModuleQuickView()
));
$this->smartyOutputContent('controllers/modules/quickview.tpl');
}
+
+ public function ajaxProcessUploadModule()
+ {
+ $response = array('success' => false);
+ $this->postProcessDownload(false);
+ if (!count($this->errors)) {
+ $filename = $_FILES['file']['name'];
+ $filename = explode('.', $filename);
+ if ($module = Module::getInstanceByName($filename[0])) {
+ $response['success'] = true;
+ if (Module::isInstalled($module->name)) {
+ $response['msg'] = $this->l('module already installed, update if available');
+ } else {
+ $response['msg'] = $this->l('module uploaded successfully');
+ }
+ if (@filemtime(_PS_ROOT_DIR_.DIRECTORY_SEPARATOR.basename(_PS_MODULE_DIR_).DIRECTORY_SEPARATOR.$module->name
+ .DIRECTORY_SEPARATOR.'logo.png')) {
+ $module->image = _MODULE_DIR_.DIRECTORY_SEPARATOR.$module->name
+ .DIRECTORY_SEPARATOR.'logo.png';
+ }
+ $response['data']['module'] = array(
+ 'module_name' => $module->name,
+ 'displayName' => $module->displayName,
+ 'installed' => Module::isInstalled($module->name),
+ 'author' => $module->author,
+ 'image' => $module->image ? $module->image : ''
+ );
+ }
+ } else {
+ $response['errors'] = $this->errors;
+ }
+ $this->logAndResponseAjax($response);
+ }
+
+ public function ajaxProcessCheckModuleTrusted()
+ {
+ $response = array(
+ 'success' => false,
+ 'data' => array('trusted' => false)
+ );
+ if ($moduleName = Tools::getValue('module_name')) {
+ if ($module = Module::getInstanceByName($moduleName)) {
+ if ($response['data']['trusted'] = Module::isModuleTrusted($moduleName)) {
+ $response['msg'] = $this->l('Module trusted');
+ } else {
+ $response['msg'] = $this->l('Module not trusted');
+ }
+ $response['success'] = true;
+ } else {
+ $this->errors[] = $this->l('Module not found.');
+ }
+ } else {
+ $this->errors[] = $this->l('Invalid module provided');
+ }
+ $response['errors'] = $this->errors;
+ $this->logAndResponseAjax($response);
+ }
+
+ public function ajaxProcessInstallModule()
+ {
+ $response = array(
+ 'success' => false,
+ );
+ if ($moduleName = Tools::getValue('module_name')) {
+ if ($module = Module::getInstanceByName($moduleName)) {
+ if (!Module::isInstalled($module->name)) {
+ if ($response['success'] = $module->install()) {
+ $response['msg'] = $this->l('Module installed successfully');
+ $response['data']['redirect'] = $this->context->link->getAdminLink('AdminModules').'&conf=12&anchor='.$module->name;
+ } else {
+ $this->errors[] = $this->l('Cannot install this module.');
+ }
+ } else {
+ $response['success'] = true;
+ $response['msg'] = $this->l('Module already installed');
+ }
+ } else {
+ $this->errors[] = $this->l('Module not found.');
+ }
+ }
+
+ if (count($this->errors)) {
+ $response['data']['callback']['process'] = 'delete';
+ $response['data']['callback']['msg'] = $this->l('There was some error while installing the module, do you want to delete the uploded module');
+ $response['errors'] = $this->errors;
+ }
+ $this->logAndResponseAjax($response);
+ }
+
+ public function ajaxProcessRollbackModuleUpload()
+ {
+ $response = array(
+ 'success' => false
+ );
+ $process = Tools::getValue('process');
+ if ($moduleName = Tools::getValue('module_name')) {
+ if($process == 'disable') {
+ if ($module = Module::getInstanceByName($moduleName)) {
+ if (Module::isInstalled($module->name)) {
+ $module->disable();
+ $response['success'] = true;
+ $response['msg'] = $this->l('Module disable successfully');
+ $response['data']['redirect'] = $this->context->link->getAdminLink('AdminModules').'&conf=5';
+ }
+ }
+ } else if($process == 'delete' || $process == 'uninstall') {
+ if ($module = Module::getInstanceByName($moduleName)) {
+ if (Module::isInstalled($module->name)) {
+ if ($module->uninstall()) {
+ if ($process == 'uninstall') {
+ $response['success'] = true;
+ $response['msg'] = $this->l('Module uninstall process completed');
+ $response['data']['redirect'] = $this->context->link->getAdminLink('AdminModules').'&conf=22';
+ }
+ }
+ }
+ }
+ if($process == 'delete') {
+ if (is_dir(_PS_MODULE_DIR_.$moduleName)) {
+ $this->recursiveDeleteOnDisk(_PS_MODULE_DIR_.$moduleName);
+ $response['success'] = true;
+ $response['msg'] = $this->l('Module rollback process completed');
+ $response['data']['redirect'] = $this->context->link->getAdminLink('AdminModules').'&conf=22';
+ }
+ }
+ }
+ }
+
+ $response['errors'] = $this->errors;
+
+ $this->logAndResponseAjax($response);
+ }
+
+ public function ajaxProcessUpdateModule()
+ {
+ $response = array(
+ 'success' => false
+ );
+ if ($moduleName = Tools::getValue('module_name')) {
+ if ($module = Module::getInstanceByName($moduleName)) {
+ if ($installed = Module::getModuleInstallVersion($module->name)) {
+ $module->installed = (bool)$installed;
+ $module->database_version = $installed['version'];
+ if (Module::initUpgradeModule($module)) {
+ if (!class_exists($module->name)) {
+ require_once(_PS_MODULE_DIR_.$module->name.'/'.$module->name.'.php');
+ }
+ if ($object = Adapter_ServiceLocator::get($module->name)) {
+ $object->runUpgradeModule();
+ if ((count($errors_module_list = $object->getErrors()))) {
+ $this->errors = array_merge($this->errors, array('name' => $module->displayName, 'message' => $errors_module_list));
+ } elseif ((count($conf_module_list = $object->getConfirmations()))) {
+ $response['data']['upgrade'][] = array('name' => $module->displayName, 'message' => $conf_module_list);
+ $response['success'] = true;
+ $html = $this->generateHtmlMessage($response['data']['upgrade']);
+ $response['msg'] = sprintf($this->l('The following module was upgraded successfully: %s.'), $html);
+ $response['data']['redirect'] = $this->context->link->getAdminLink('AdminModules').'&conf=29&anchor='.$module->name;
+ }
+ unset($object);
+ } else {
+ $this->errors[] = $this->l('Module not found!');
+ }
+ } else {
+ $this->errors[] = $this->l('There was some error while updating the module');
+ }
+ } else {
+ $this->errors[] = $this->l('Module not installed, install module before updating.');
+ }
+ } else {
+ $this->errors[] = $this->l('Module not found!');
+ }
+ }
+ if (count($this->errors)) {
+ $response['data']['callback']['process'] = 'disable';
+ $response['data']['callback']['msg'] = $this->l('There was some error while updating the module, do you want to disable the module');
+ $response['errors'] = $this->errors;
+ }
+
+ $this->logAndResponseAjax($response);
+ }
+
+ public function logAndResponseAjax($response)
+ {
+ if (isset($response['errors']) && count($response['errors'])) {
+ PrestaShopLogger::addLog('Module install/upload error : Resquest => '.json_encode(Tools::getAllValues()).' || Response =>'.(json_encode($response)), 1, null, 'Module', null, true, (int)$this->context->employee->id);
+ }
+ $this->ajaxDie(json_encode($response));
+ }
}
diff --git a/controllers/admin/AdminPaymentController.php b/controllers/admin/AdminPaymentController.php
index 4d88b5986..2985ff95a 100644
--- a/controllers/admin/AdminPaymentController.php
+++ b/controllers/admin/AdminPaymentController.php
@@ -92,12 +92,6 @@ public function initToolbarTitle()
$this->toolbar_title = array_unique($this->breadcrumbs);
}
- public function initPageHeaderToolbar()
- {
- parent::initPageHeaderToolbar();
- $this->page_header_toolbar_btn = array();
- }
-
public function postProcess()
{
if (Tools::getValue('action') == 'GetModuleQuickView' && Tools::getValue('ajax') == '1') {
@@ -274,40 +268,4 @@ public function renderView()
return parent::renderView();
}
-
- public function renderModulesList()
- {
- if ($this->getModulesList($this->filter_modules_list)) {
- $active_list = array();
- foreach ($this->modules_list as $key => $module) {
- if (in_array($module->name, $this->list_partners_modules)) {
- $this->modules_list[$key]->type = 'addonsPartner';
- }
- if (isset($module->description_full) && trim($module->description_full) != '') {
- $module->show_quick_view = true;
- }
-
- if ($module->active) {
- $active_list[] = $module;
- } else {
- $unactive_list[] = $module;
- }
- }
-
- $helper = new Helper();
- $fetch = '';
-
- if (isset($active_list)) {
- $this->context->smarty->assign('panel_title', $this->l('Active payment'));
- $fetch = $helper->renderModulesList($active_list);
- }
-
- $this->context->smarty->assign(array(
- 'panel_title' => $this->l('Recommended payment gateways'),
- 'view_all' => true
- ));
- $fetch .= $helper->renderModulesList($unactive_list);
- return $fetch;
- }
- }
}
diff --git a/controllers/admin/AdminStatsTabController.php b/controllers/admin/AdminStatsTabController.php
index 54b1682fb..014750dd6 100644
--- a/controllers/admin/AdminStatsTabController.php
+++ b/controllers/admin/AdminStatsTabController.php
@@ -41,7 +41,6 @@ public function initContent()
}
$this->initTabModuleList();
- $this->addToolBarModulesListButton();
$this->toolbar_title = $this->l('Stats', 'AdminStatsTab');
$this->initPageHeaderToolbar();
if ($this->display == 'view') {
diff --git a/controllers/admin/AdminThemesController.php b/controllers/admin/AdminThemesController.php
index ca48faac1..9330a2b2e 100644
--- a/controllers/admin/AdminThemesController.php
+++ b/controllers/admin/AdminThemesController.php
@@ -506,7 +506,7 @@ public function downloadAddonsThemes()
) {
return false;
}
- if (!$this->isFresh(Theme::CACHE_FILE_CUSTOMER_THEMES_LIST, 86400)) {
+ if (!$this->isFresh(Theme::CACHE_FILE_CUSTOMER_THEMES_LIST, _TIME_1_DAY_)) {
file_put_contents(_PS_ROOT_DIR_.Theme::CACHE_FILE_CUSTOMER_THEMES_LIST, Tools::addonsRequest('customer_themes'));
}
@@ -2075,6 +2075,15 @@ private function getNativeModule($type = 0)
}
}
break;
+ case 3:
+ foreach ($xml->modules as $row) {
+ if ($row['type'] == 'disk') {
+ foreach ($row->module as $row2) {
+ $natives[] = (string)$row2['name'];
+ }
+ }
+ }
+ break;
}
if (count($natives) > 0) {
diff --git a/install/data/xml/tab.xml b/install/data/xml/tab.xml
index 4b0833fae..38f072811 100644
--- a/install/data/xml/tab.xml
+++ b/install/data/xml/tab.xml
@@ -186,6 +186,9 @@
AdminModules
+
+ AdminModulesCatalog
+
diff --git a/install/fixtures/fashion/data/access.xml b/install/fixtures/fashion/data/access.xml
index c943c2b04..5b5f0d074 100644
--- a/install/fixtures/fashion/data/access.xml
+++ b/install/fixtures/fashion/data/access.xml
@@ -69,6 +69,7 @@
+
@@ -169,6 +170,7 @@
+
@@ -269,6 +271,7 @@
+
diff --git a/install/langs/bg/data/tab.xml b/install/langs/bg/data/tab.xml
index fb12295a1..18e8716d8 100644
--- a/install/langs/bg/data/tab.xml
+++ b/install/langs/bg/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/bn/data/tab.xml b/install/langs/bn/data/tab.xml
index 9355c5bf1..dc9fbc64c 100644
--- a/install/langs/bn/data/tab.xml
+++ b/install/langs/bn/data/tab.xml
@@ -61,6 +61,7 @@
+
diff --git a/install/langs/br/data/tab.xml b/install/langs/br/data/tab.xml
index 4ff2d7858..3456cc548 100644
--- a/install/langs/br/data/tab.xml
+++ b/install/langs/br/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/cs/data/tab.xml b/install/langs/cs/data/tab.xml
index 1828e3bb7..0e58531ea 100644
--- a/install/langs/cs/data/tab.xml
+++ b/install/langs/cs/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/de/data/tab.xml b/install/langs/de/data/tab.xml
index ecbe5aacf..6e6a7fa59 100644
--- a/install/langs/de/data/tab.xml
+++ b/install/langs/de/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/en/data/tab.xml b/install/langs/en/data/tab.xml
index 2506bba30..c2450b111 100644
--- a/install/langs/en/data/tab.xml
+++ b/install/langs/en/data/tab.xml
@@ -58,7 +58,8 @@
-
+
+
diff --git a/install/langs/es/data/tab.xml b/install/langs/es/data/tab.xml
index c60fbcb4d..c2b326480 100644
--- a/install/langs/es/data/tab.xml
+++ b/install/langs/es/data/tab.xml
@@ -58,6 +58,7 @@
+
diff --git a/install/langs/fa/data/tab.xml b/install/langs/fa/data/tab.xml
index 5a53cc285..99d6017af 100644
--- a/install/langs/fa/data/tab.xml
+++ b/install/langs/fa/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/fr/data/tab.xml b/install/langs/fr/data/tab.xml
index 81d20d2d3..20dc6cfdf 100644
--- a/install/langs/fr/data/tab.xml
+++ b/install/langs/fr/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/he/data/tab.xml b/install/langs/he/data/tab.xml
index 8c7221d75..657f73c57 100644
--- a/install/langs/he/data/tab.xml
+++ b/install/langs/he/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/hr/data/tab.xml b/install/langs/hr/data/tab.xml
index 6a2d99fa6..8e0554658 100644
--- a/install/langs/hr/data/tab.xml
+++ b/install/langs/hr/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/hu/data/tab.xml b/install/langs/hu/data/tab.xml
index 6afefb0b4..ba956472a 100644
--- a/install/langs/hu/data/tab.xml
+++ b/install/langs/hu/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/id/data/tab.xml b/install/langs/id/data/tab.xml
index 7bf3f7484..9d1abb784 100644
--- a/install/langs/id/data/tab.xml
+++ b/install/langs/id/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/it/data/tab.xml b/install/langs/it/data/tab.xml
index 720186efb..1c0396cc2 100644
--- a/install/langs/it/data/tab.xml
+++ b/install/langs/it/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/lt/data/tab.xml b/install/langs/lt/data/tab.xml
index 77957f945..aaf9c5548 100644
--- a/install/langs/lt/data/tab.xml
+++ b/install/langs/lt/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/mk/data/tab.xml b/install/langs/mk/data/tab.xml
index 9daeef192..b18f57736 100644
--- a/install/langs/mk/data/tab.xml
+++ b/install/langs/mk/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/nl/data/tab.xml b/install/langs/nl/data/tab.xml
index 7bb6f40e5..2580f90d0 100644
--- a/install/langs/nl/data/tab.xml
+++ b/install/langs/nl/data/tab.xml
@@ -61,6 +61,7 @@
+
diff --git a/install/langs/no/data/tab.xml b/install/langs/no/data/tab.xml
index 852e50b94..d3810aac1 100644
--- a/install/langs/no/data/tab.xml
+++ b/install/langs/no/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/pl/data/tab.xml b/install/langs/pl/data/tab.xml
index 92698de64..9386cdb1e 100644
--- a/install/langs/pl/data/tab.xml
+++ b/install/langs/pl/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/pt/data/tab.xml b/install/langs/pt/data/tab.xml
index bc64e8365..d0d156f45 100644
--- a/install/langs/pt/data/tab.xml
+++ b/install/langs/pt/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/qc/data/tab.xml b/install/langs/qc/data/tab.xml
index 90984efb3..97a0cd4e6 100644
--- a/install/langs/qc/data/tab.xml
+++ b/install/langs/qc/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/ro/data/tab.xml b/install/langs/ro/data/tab.xml
index 720cba541..538a36389 100644
--- a/install/langs/ro/data/tab.xml
+++ b/install/langs/ro/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/ru/data/tab.xml b/install/langs/ru/data/tab.xml
index 18be4c013..8074f77a1 100644
--- a/install/langs/ru/data/tab.xml
+++ b/install/langs/ru/data/tab.xml
@@ -51,6 +51,7 @@
+
diff --git a/install/langs/si/data/tab.xml b/install/langs/si/data/tab.xml
index 4bfb023a9..f586e4eda 100644
--- a/install/langs/si/data/tab.xml
+++ b/install/langs/si/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/sr/data/tab.xml b/install/langs/sr/data/tab.xml
index dfb87619f..d4870637b 100644
--- a/install/langs/sr/data/tab.xml
+++ b/install/langs/sr/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/sv/data/tab.xml b/install/langs/sv/data/tab.xml
index ff442f775..07d714118 100644
--- a/install/langs/sv/data/tab.xml
+++ b/install/langs/sv/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/langs/tw/data/tab.xml b/install/langs/tw/data/tab.xml
index a50e791fb..3e560de6f 100644
--- a/install/langs/tw/data/tab.xml
+++ b/install/langs/tw/data/tab.xml
@@ -63,6 +63,7 @@
+
diff --git a/install/langs/vn/data/tab.xml b/install/langs/vn/data/tab.xml
index 4e0fa97ea..00a32af60 100644
--- a/install/langs/vn/data/tab.xml
+++ b/install/langs/vn/data/tab.xml
@@ -49,6 +49,7 @@
+
diff --git a/install/langs/zh/data/tab.xml b/install/langs/zh/data/tab.xml
index b1f8a9633..4c12fcf91 100644
--- a/install/langs/zh/data/tab.xml
+++ b/install/langs/zh/data/tab.xml
@@ -59,6 +59,7 @@
+
diff --git a/install/upgrade/php/deactivate_custom_modules.php b/install/upgrade/php/deactivate_custom_modules.php
index 428c76079..567ac8dc3 100644
--- a/install/upgrade/php/deactivate_custom_modules.php
+++ b/install/upgrade/php/deactivate_custom_modules.php
@@ -54,7 +54,7 @@ function deactivate_custom_modules()
$arrNativeModules = array();
if (is_array($nativeModules)) {
foreach ($nativeModules as $nativeModulesType) {
- if (in_array($nativeModulesType['type'], array('native', 'partner'))) {
+ if (in_array($nativeModulesType['type'], array('native', 'disk', 'partner'))) {
$arrNativeModules[] = '""';
foreach ($nativeModulesType->module as $module) {
$arrNativeModules[] = '"'.pSQL($module['name']).'"';
diff --git a/js/admin.js b/js/admin.js
index 2edebf24d..62da0859c 100644
--- a/js/admin.js
+++ b/js/admin.js
@@ -728,6 +728,27 @@ $(document).ready(function()
$('#theme_fieldset_'+formToMove+' .form-wrapper').appendTo('#'+formDestination);
}
+ try
+ {
+ resAjax = $.ajax({
+ type:"POST",
+ url: 'index.php',
+ headers: {"cache-control": "no-cache"},
+ async: true,
+ cache: false,
+ data: {
+ ajax : "1",
+ token : token,
+ action : "refreshModuleList"
+ },
+ success: function(data){
+ }
+ });
+ }
+ catch(e) { }
+
+
+
$('select.chosen').each(function(k, item){
$(item).chosen({disable_search_threshold: 10, search_contains: true});
});
@@ -863,7 +884,6 @@ $(document).ready(function()
var moduleLink = $(this).data('link');
var authorUri = $(this).data('author-uri');
var isValidUri = /(https?):\/\/([a-z0-9\.]*)?(prestashop.com).*/gi;
- var addonsSearchLink = 'http://addons.prestashop.com/en/search?search_query='+encodeURIComponent(moduleDisplayName)+'&utm_source=back-office&utm_medium=addons-certified&utm_campaign=back-office-'+iso_user.toUpperCase();
$('.modal #untrusted-module-logo').attr('src', moduleImage);
$('.modal .module-display-name-placeholder').text(moduleDisplayName);
@@ -873,7 +893,6 @@ $(document).ready(function()
$('.modal .author-name-placeholder').wrap('');
$('.modal #proceed-install-anyway').attr('href', moduleLink);
- $('.modal .catalog-link').attr('href', addonsSearchLink);
$('.modal .catalog-link').attr('onclick', 'window.open(this.href);return false;');
});
@@ -1206,14 +1225,14 @@ function openModulesList()
ajax : "1",
controller : "AdminModules",
action : "getTabModulesList",
- tab_modules_list : tab_modules_list,
+ controller_class: help_class_name,
back_tab_modules_list : window.location.href
},
success : function(data)
{
$('#modules_list_container_tab_modal').html(data).slideDown();
$('#modules_list_loader').hide();
- modules_list_loaded = true;
+ // modules_list_loaded = true;
$('.help-tooltip').tooltip();
}
});
@@ -1576,3 +1595,28 @@ function countDown($source, $target) {
$target.html(max-$source.val().length);
});
}
+
+function loadRecommendation()
+{
+ $.ajax({
+ type: 'POST',
+ url: 'index.php',
+ async: true,
+ dataType: 'JSON',
+ data: {
+ action: 'getRecommendationContent',
+ tab: help_class_name,
+ ajax: 1,
+ token: token
+ },
+ success: function(res) {
+ $('#recommendation-wrapper-skeleton').fadeOut('slow').hide();
+ if (res.success) {
+ $('#recommendation-wrapper').html(res.content).fadeIn('slow');
+ }
+ },
+ error: function(res) {
+ $('#recommendation-wrapper-skeleton').fadeOut('slow').hide();
+ }
+ });
+}
diff --git a/js/admin/dashboard.js b/js/admin/dashboard.js
index 8757970b7..a36e571e6 100644
--- a/js/admin/dashboard.js
+++ b/js/admin/dashboard.js
@@ -297,7 +297,6 @@ $(document).ready(function() {
});
refreshDashboard(false, false);
- getBlogRss();
bindSubmitDashConfig();
bindCancelDashConfig();
diff --git a/js/admin/modules.js b/js/admin/modules.js
new file mode 100644
index 000000000..de1198fc9
--- /dev/null
+++ b/js/admin/modules.js
@@ -0,0 +1,299 @@
+/**
+* 2010-2022 Webkul.
+*
+* NOTICE OF LICENSE
+*
+* All right is reserved,
+* Please go through LICENSE.txt file inside our module
+*
+* DISCLAIMER
+*
+* Do not edit or add to this file if you wish to upgrade this module to newer
+* versions in the future. If you wish to customize this module for your
+* needs please refer to CustomizationPolicy.txt file inside our module for more information.
+*
+* @author Webkul IN
+* @copyright 2010-2022 Webkul IN
+* @license LICENSE.txt
+*/
+
+$('document').ready( function() {
+
+ $('[data-toggle="tab"]').click(function() {
+ if ($(this).parent().hasClass('active')) {
+ $($(this).attr("href")).toggleClass('active');
+ setTimeout(() => {
+ $(this).parent().removeClass('active');
+ }, 0);
+ }
+ });
+
+ $('#module_install_form').on('submit', function(e) {
+ e.preventDefault();
+ let module;
+ initializeUploadPanel();
+ uploadModule(this).then((response) => {
+ module = response.data.module;
+ if (!module.installed) {
+ checkModuleTrusted(module).then((response) => {
+ if (!response.data.trusted) {
+ return displayWariningIfUntrusted(module);
+ } else {
+ return Promise.resolve(true);
+ }
+ }).then((install) => {
+ if (install) {
+ return installModule(module);
+ } else {
+ if (confirm(remove_uploaded_module_txt)) {
+ return rollBackChanges(module, 'delete');
+ } else {
+ window.location.href = admin_modules_link + '&conf=18';
+ }
+ }
+ }).catch((response) => {
+ handleError(response, module);
+ });
+ } else {
+ updateModule(module).catch((response) => {
+ handleError(response, module);
+ });
+ }
+ }).catch((response) => {
+ displayErrors(response, module);
+ }).finally(() => {
+ $('#module_install_form').find('button[type="submit"]').attr("disabled", false);
+ });
+ });
+
+ $('#proceed-install-anyway').on('click', function(e) {
+ e.preventDefault();
+ })
+
+ function displayErrors(response, module)
+ {
+ let error_list = $('').appendTo('#module_install_status .install_errors .list');
+ $.each(response.errors, function(i, val) {
+ $('').text(val).appendTo(error_list);
+ });
+ $('#module_install_status div.install_errors').show();
+ }
+
+ function handleError(response, module)
+ {
+ displayErrors(response, module);
+ if (response.data.callback.process) {
+ setTimeout(() => {
+ if (confirm(response.data.callback.msg ? response.data.callback.msg : module_install_error_txt+' '+remove_uploaded_module_txt)) {
+ rollBackChanges(module, response.data.callback.process);
+ }
+ }, 1000);
+ }
+ }
+
+ function displayWariningIfUntrusted(data)
+ {
+ return new Promise((resolve) => {
+ var moduleDisplayName = data.displayName;
+ var moduleImage = data.image;
+ var authorName = data.author;
+
+ $('.modal #untrusted-module-logo').attr('src', moduleImage);
+ $('.modal .module-display-name-placeholder').text(moduleDisplayName);
+ $('.modal .author-name-placeholder').text(authorName);
+
+ $('#moduleNotTrusted').modal('show');
+
+ $('#proceed-install-anyway').click(() => {
+ $('#moduleNotTrusted').modal('hide');
+ resolve(true);
+ });
+ $('#moduleNotTrusted').on('hidden.bs.modal', (e) => {
+ resolve(false);
+ });
+ });
+ }
+
+ function initializeUploadPanel()
+ {
+ $('#module_install_form').find('button[type="submit"]').attr("disabled","disabled");
+ $('#module_install_status').show().find('ul li').hide().find('i').removeClass('icon-check icon-times text-danger text-success').addClass('icon-refresh icon-spin');
+ $('#module_install_status div.install_errors').hide();
+ return
+ }
+
+ function uploadModule(uploadModule)
+ {
+ return new Promise((resolve, reject) => {
+ let formData = new FormData(uploadModule);
+ formData.append('ajax', true);
+ formData.append('action', 'uploadModule');
+ $.ajax({
+ type: 'POST',
+ url: admin_modules_link,
+ data: formData,
+ dataType: 'json',
+ contentType: false,
+ cache: false,
+ processData:false,
+ beforeSend: function(){
+ $('#module_install_status').find('.mod_status_upload').show();
+ },
+ success: function(json) {
+ if (json.success) {
+ $('#module_install_status').find('.mod_status_upload i').addClass('icon-check text-success').removeClass('icon-refresh icon-spin');
+ resolve(json);
+ }
+ else {
+ $('#module_install_status').find('.mod_status_upload i').addClass('icon-times text-danger').removeClass('icon-refresh icon-spin');
+ reject(json);
+ }
+ }
+ });
+ });
+ }
+
+ function checkModuleTrusted(data)
+ {
+ return new Promise((resolve, reject) => {
+ $.ajax({
+ type: 'POST',
+ url: admin_modules_link,
+ data: {
+ ajax: true,
+ action: 'checkModuleTrusted',
+ module_name: data.module_name
+ },
+ dataType: 'JSON',
+ cache: false,
+ beforeSend: function(){
+ $('#module_install_status').find('.mod_status_check').show();
+ },
+ success: function(json) {
+ if (json.success){
+ $('#module_install_status').find('.mod_status_check i').addClass('icon-check text-success').removeClass('icon-refresh icon-spin');
+ if (json.msg){
+ $('#module_install_status').find('.mod_status_check').append(' '+json.msg+'');
+ if (json.data.trusted) {
+ $('#module_install_status').find('.mod_status_check b').addClass('text-success');
+ } else {
+ $('#module_install_status').find('.mod_status_check b').addClass('text-danger');
+ }
+ }
+ resolve(json);
+ } else {
+ $('#module_install_status').find('.mod_status_check i').addClass('icon-times text-danger').removeClass('icon-refresh icon-spin');
+ reject(json);
+ }
+ }
+ });
+ });
+ }
+
+ function installModule(data)
+ {
+ return new Promise((resolve, reject) => {
+ $.ajax({
+ type: 'POST',
+ url: admin_modules_link,
+ data: {
+ ajax: true,
+ action: 'installModule',
+ module_name: data.module_name
+ },
+ dataType: 'JSON',
+ cache: false,
+ beforeSend: function(){
+ $('#module_install_status').find('.mod_status_install').show();
+ },
+ success: function(json) {
+ if (json.success){
+ $('#module_install_status').find('.mod_status_install i').addClass('icon-check text-success').removeClass('icon-refresh icon-spin');
+ resolve(json);
+
+ if (json.data.redirect) {
+ window.location.href = json.data.redirect;
+ }
+ }
+ else{
+ $('#module_install_status').find('.mod_status_install i').addClass('icon-times text-danger').removeClass('icon-refresh icon-spin');
+ reject(json);
+ }
+ }
+ });
+
+
+ });
+ }
+
+ function rollBackChanges(data, process)
+ {
+ if (!process) {
+ process = 'delete';
+ }
+ return new Promise((resolve, reject) => {
+ $.ajax({
+ type:"POST",
+ url : admin_modules_link,
+ data : {
+ ajax : true,
+ token : token,
+ action : "rollbackModuleUpload",
+ process : process,
+ module_name: data.module_name
+ },
+ dataType: 'JSON',
+ cache: false,
+ beforeSend: function(){
+ $('#module_install_status').find('.mod_status_rollback').show();
+ },
+ success: function(json){
+ if (json.success) {
+ $('#module_install_status').find('.mod_status_rollback i').addClass('icon-check text-success').removeClass('icon-refresh icon-spin');
+ if (json.data.redirect) {
+ window.location.href = json.data.redirect;
+ }
+ } else {
+ $('#module_install_status').find('.mod_status_install i').addClass('icon-times text-danger').removeClass('icon-refresh icon-spin');
+ reject(json);
+ }
+ }
+ });
+ });
+ }
+
+ function updateModule(data)
+ {
+ return new Promise((resolve, reject) => {
+ $.ajax({
+ type:"POST",
+ url : admin_modules_link,
+ data : {
+ ajax : true,
+ token : token,
+ action : "updateModule",
+ module_name: data.module_name
+ },
+ dataType: 'JSON',
+ cache: false,
+ beforeSend: function(){
+ $('#module_install_status').find('.mod_status_update').show();
+ },
+ success: function(json){
+ if (json.success) {
+ $('#module_install_status').find('.mod_status_update i').addClass('icon-check text-success').removeClass('icon-refresh icon-spin');
+ $('#module_install_status div.install_msg').append(json.msg);
+ if (json.data.redirect) {
+ window.location.href = json.data.redirect;
+ }
+ resolve(json);
+ } else {
+ $('#module_install_status').find('.mod_status_update i').addClass('icon-times text-danger').removeClass('icon-refresh icon-spin');
+ reject(json);
+ }
+ }
+ });
+ });
+ }
+
+});
diff --git a/js/admin/modules_catalog.js b/js/admin/modules_catalog.js
new file mode 100644
index 000000000..171d3ba56
--- /dev/null
+++ b/js/admin/modules_catalog.js
@@ -0,0 +1,118 @@
+/**
+* 2010-2022 Webkul.
+*
+* NOTICE OF LICENSE
+*
+* All right is reserved,
+* Please go through LICENSE.txt file inside our module
+*
+* DISCLAIMER
+*
+* Do not edit or add to this file if you wish to upgrade this module to newer
+* versions in the future. If you wish to customize this module for your
+* needs please refer to CustomizationPolicy.txt file inside our module for more information.
+*
+* @author Webkul IN
+* @copyright 2010-2022 Webkul IN
+* @license LICENSE.txt
+*/
+
+$('document').ready( function() {
+ initPagination();
+ // ScrollTo
+ $('#module-search').on('keyup', function(){
+ val = this.value;
+ setTimeout(function () {
+ filterPanel(val, 'suggested-modules-list');
+ }, 200);
+ }).on('keydown', function(e){
+ if (e.keyCode == 13)
+ return false;
+ if (e.keyCode == 27) {
+ this.value = '';
+ }
+ });
+
+ $('#theme-search').on('keyup', function(){
+ val = this.value;
+ setTimeout(function () {
+ filterPanel(val, 'suggested-theme-list');
+ }, 200);
+ }).on('keydown', function(e){
+ if (e.keyCode == 13)
+ return false;
+ if (e.keyCode == 27) {
+ this.value = '';
+ }
+ });
+
+ $('#theme-sort, #module-sort').on('change', function(){
+ setFilter();
+ });
+
+ function filterPanel(val, element_class)
+ {
+ $('#'+element_class+' .list-empty').hide();
+ $('#'+element_class+' .element-panel').css('display', 'flex').removeClass('hidden');
+
+ if (val != '') {
+ var reg = new RegExp(val, "i");
+ $('#'+element_class+' .element-panel .name').each(function(id, ele_name) {
+ if (!reg.test($(ele_name).text()) && !reg.test($(ele_name).data('name'))){
+ // if (!$(mod_name).text().includes(val)) {
+ $(ele_name).closest('.element-panel').hide().addClass('hidden');
+ }
+ });
+ }
+ if (!$('#'+element_class+' .element-panel:visible').length) {
+ $('#'+element_class+' .list-empty').css('display', 'flex');
+ }
+ initPagination(element_class);
+ }
+
+ function setFilter()
+ {
+ let theme_sorting = $("#theme-sort").val();
+ let module_sorting = $("#module-sort").val();
+ $.ajax({
+ type: 'POST',
+ url: 'index.php',
+ async: true,
+ dataType: 'JSON',
+ data: {
+ action: 'setSorting',
+ theme_sorting: theme_sorting,
+ module_sorting: module_sorting,
+ tab: 'AdminModulesCatalog',
+ ajax: 1,
+ token: token
+ },
+ success: function(res) {
+ location.reload();
+ },
+ });
+ }
+
+ function initPagination(selected_element_class) {
+ $.each($('.suggested-elements'), function(i, element) {
+ if (selected_element_class) {
+ if ($(element).closest('.list-container').attr('id') != selected_element_class)
+ return;
+ }
+ $(element).siblings('.pagination-container').find('.pagination-block').twbsPagination('destroy');
+ let items = $(element).children(':not(.hidden)');
+ if (items.length) {
+ let total_pages = Math.ceil(items.length / num_block_per_page);
+ $(element).siblings('.pagination-container').find('.pagination-block').twbsPagination({
+ totalPages: total_pages,
+ visiblePages: 5,
+ onPageClick: function(e, pageNumber) {
+ let showFrom = num_block_per_page * (pageNumber - 1);
+ let showTo = showFrom + num_block_per_page;
+ items.hide().slice(showFrom, showTo).css('display', 'flex');
+ }
+ });
+ }
+ });
+ }
+});
diff --git a/js/twbs-pagination/LICENSE b/js/twbs-pagination/LICENSE
new file mode 100644
index 000000000..704b37b00
--- /dev/null
+++ b/js/twbs-pagination/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2014-2018 © Eugene Simakin
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/js/twbs-pagination/index.php b/js/twbs-pagination/index.php
new file mode 100644
index 000000000..239883ccc
--- /dev/null
+++ b/js/twbs-pagination/index.php
@@ -0,0 +1,29 @@
+
+* @copyright 2010-2022 Webkul IN
+* @license https://store.webkul.com/license.html
+*/
+
+header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
+header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
+
+header('Cache-Control: no-store, no-cache, must-revalidate');
+header('Cache-Control: post-check=0, pre-check=0', false);
+header('Pragma: no-cache');
+
+header('Location: ../../');
+exit;
diff --git a/js/twbs-pagination/jquery.twbsPagination.js b/js/twbs-pagination/jquery.twbsPagination.js
new file mode 100644
index 000000000..2451a6109
--- /dev/null
+++ b/js/twbs-pagination/jquery.twbsPagination.js
@@ -0,0 +1,364 @@
+/*!
+ * jQuery pagination plugin v1.4.2
+ * http://josecebe.github.io/twbs-pagination/
+ *
+ * Copyright 2014-2018, Eugene Simakin
+ * Released under Apache 2.0 license
+ * http://apache.org/licenses/LICENSE-2.0.html
+ */
+(function ($, window, document, undefined) {
+
+ 'use strict';
+
+ var old = $.fn.twbsPagination;
+
+ // PROTOTYPE AND CONSTRUCTOR
+
+ var TwbsPagination = function (element, options) {
+ this.$element = $(element);
+ this.options = $.extend({}, $.fn.twbsPagination.defaults, options);
+
+ if (this.options.startPage < 1 || this.options.startPage > this.options.totalPages) {
+ throw new Error('Start page option is incorrect');
+ }
+
+ this.options.totalPages = parseInt(this.options.totalPages);
+ if (isNaN(this.options.totalPages)) {
+ throw new Error('Total pages option is not correct!');
+ }
+
+ this.options.visiblePages = parseInt(this.options.visiblePages);
+ if (isNaN(this.options.visiblePages)) {
+ throw new Error('Visible pages option is not correct!');
+ }
+
+ if (this.options.beforePageClick instanceof Function) {
+ this.$element.first().on('beforePage', this.options.beforePageClick);
+ }
+
+ if (this.options.onPageClick instanceof Function) {
+ this.$element.first().on('page', this.options.onPageClick);
+ }
+
+ // hide if only one page exists
+ if (this.options.hideOnlyOnePage && this.options.totalPages == 1) {
+ if (this.options.initiateStartPageClick) {
+ this.$element.trigger('page', 1);
+ }
+ return this;
+ }
+
+ if (this.options.href) {
+ this.options.startPage = this.getPageFromQueryString();
+ if (!this.options.startPage) {
+ this.options.startPage = 1;
+ }
+ }
+
+ var tagName = (typeof this.$element.prop === 'function') ?
+ this.$element.prop('tagName') : this.$element.attr('tagName');
+
+ if (tagName === 'UL') {
+ this.$listContainer = this.$element;
+ } else {
+ var elements = this.$element;
+ var $newListContainer = $([]);
+ elements.each(function(index) {
+ var $newElem = $("");
+ $(this).append($newElem);
+ $newListContainer.push($newElem[0]);
+ });
+ this.$listContainer = $newListContainer;
+ this.$element = $newListContainer;
+ }
+
+ this.$listContainer.addClass(this.options.paginationClass);
+
+ if (this.options.initiateStartPageClick) {
+ this.show(this.options.startPage);
+ } else {
+ this.currentPage = this.options.startPage;
+ this.render(this.getPages(this.options.startPage));
+ this.setupEvents();
+ }
+
+ return this;
+ };
+
+ TwbsPagination.prototype = {
+
+ constructor: TwbsPagination,
+
+ destroy: function () {
+ this.$element.empty();
+ this.$element.removeData('twbs-pagination');
+ this.$element.off('page');
+
+ return this;
+ },
+
+ show: function (page) {
+ if (page < 1 || page > this.options.totalPages) {
+ throw new Error('Page is incorrect.');
+ }
+ this.currentPage = page;
+
+ this.$element.trigger('beforePage', page);
+
+ var pages = this.getPages(page);
+ this.render(pages);
+ this.setupEvents();
+
+ this.$element.trigger('page', page);
+
+ return pages;
+ },
+
+ enable: function () {
+ this.show(this.currentPage);
+ },
+
+ disable: function () {
+ var _this = this;
+ this.$listContainer.off('click').on('click', 'li', function (evt) {
+ evt.preventDefault();
+ });
+ this.$listContainer.children().each(function () {
+ var $this = $(this);
+ if (!$this.hasClass(_this.options.activeClass)) {
+ $(this).addClass(_this.options.disabledClass);
+ }
+ });
+ },
+
+ buildListItems: function (pages) {
+ var listItems = [];
+
+ if (this.options.first) {
+ listItems.push(this.buildItem('first', 1));
+ }
+
+ if (this.options.prev) {
+ var prev = pages.currentPage > 1 ? pages.currentPage - 1 : this.options.loop ? this.options.totalPages : 1;
+ listItems.push(this.buildItem('prev', prev));
+ }
+
+ for (var i = 0; i < pages.numeric.length; i++) {
+ listItems.push(this.buildItem('page', pages.numeric[i]));
+ }
+
+ if (this.options.next) {
+ var next = pages.currentPage < this.options.totalPages ? pages.currentPage + 1 : this.options.loop ? 1 : this.options.totalPages;
+ listItems.push(this.buildItem('next', next));
+ }
+
+ if (this.options.last) {
+ listItems.push(this.buildItem('last', this.options.totalPages));
+ }
+
+ return listItems;
+ },
+
+ buildItem: function (type, page) {
+ var $itemContainer = $(''),
+ $itemContent = $(''),
+ itemText = this.options[type] ? this.makeText(this.options[type], page) : page;
+
+ $itemContainer.addClass(this.options[type + 'Class']);
+ $itemContainer.data('page', page);
+ $itemContainer.data('page-type', type);
+ $itemContainer.append($itemContent.attr('href', this.makeHref(page)).addClass(this.options.anchorClass).html(itemText));
+
+ return $itemContainer;
+ },
+
+ getPages: function (currentPage) {
+ var pages = [];
+
+ var half = Math.floor(this.options.visiblePages / 2);
+ var start = currentPage - half + 1 - this.options.visiblePages % 2;
+ var end = currentPage + half;
+
+ var visiblePages = this.options.visiblePages;
+ if (visiblePages > this.options.totalPages) {
+ visiblePages = this.options.totalPages;
+ }
+
+ // handle boundary case
+ if (start <= 0) {
+ start = 1;
+ end = visiblePages;
+ }
+ if (end > this.options.totalPages) {
+ start = this.options.totalPages - visiblePages + 1;
+ end = this.options.totalPages;
+ }
+
+ var itPage = start;
+ while (itPage <= end) {
+ pages.push(itPage);
+ itPage++;
+ }
+
+ return {"currentPage": currentPage, "numeric": pages};
+ },
+
+ render: function (pages) {
+ var _this = this;
+ this.$listContainer.children().remove();
+ var items = this.buildListItems(pages);
+ $.each(items, function(key, item){
+ _this.$listContainer.append(item);
+ });
+
+ this.$listContainer.children().each(function () {
+ var $this = $(this),
+ pageType = $this.data('page-type');
+
+ switch (pageType) {
+ case 'page':
+ if ($this.data('page') === pages.currentPage) {
+ $this.addClass(_this.options.activeClass);
+ }
+ break;
+ case 'first':
+ $this.toggleClass(_this.options.disabledClass, pages.currentPage === 1);
+ break;
+ case 'last':
+ $this.toggleClass(_this.options.disabledClass, pages.currentPage === _this.options.totalPages);
+ break;
+ case 'prev':
+ $this.toggleClass(_this.options.disabledClass, !_this.options.loop && pages.currentPage === 1);
+ break;
+ case 'next':
+ $this.toggleClass(_this.options.disabledClass,
+ !_this.options.loop && pages.currentPage === _this.options.totalPages);
+ break;
+ default:
+ break;
+ }
+
+ });
+ },
+
+ setupEvents: function () {
+ var _this = this;
+ this.$listContainer.off('click').on('click', 'li', function (evt) {
+ var $this = $(this);
+ if ($this.hasClass(_this.options.disabledClass) || $this.hasClass(_this.options.activeClass)) {
+ return false;
+ }
+ // Prevent click event if href is not set.
+ !_this.options.href && evt.preventDefault();
+ _this.show(parseInt($this.data('page')));
+ });
+ },
+
+ changeTotalPages: function(totalPages, currentPage) {
+ this.options.totalPages = totalPages;
+ return this.show(currentPage);
+ },
+
+ makeHref: function (page) {
+ return this.options.href ? this.generateQueryString(page) : "#";
+ },
+
+ makeText: function (text, page) {
+ return text.replace(this.options.pageVariable, page)
+ .replace(this.options.totalPagesVariable, this.options.totalPages)
+ },
+
+ getPageFromQueryString: function (searchStr) {
+ var search = this.getSearchString(searchStr),
+ regex = new RegExp(this.options.pageVariable + '(=([^]*)|&|#|$)'),
+ page = regex.exec(search);
+ if (!page || !page[2]) {
+ return null;
+ }
+ page = decodeURIComponent(page[2]);
+ page = parseInt(page);
+ if (isNaN(page)) {
+ return null;
+ }
+ return page;
+ },
+
+ generateQueryString: function (pageNumber, searchStr) {
+ var search = this.getSearchString(searchStr),
+ regex = new RegExp(this.options.pageVariable + '=*[^]*');
+ if (!search) return '';
+ return '?' + search.replace(regex, this.options.pageVariable + '=' + pageNumber);
+ },
+
+ getSearchString: function (searchStr) {
+ var search = searchStr || window.location.search;
+ if (search === '') {
+ return null;
+ }
+ if (search.indexOf('?') === 0) search = search.substr(1);
+ return search;
+ },
+
+ getCurrentPage: function () {
+ return this.currentPage;
+ },
+
+ getTotalPages: function () {
+ return this.options.totalPages;
+ }
+ };
+
+ // PLUGIN DEFINITION
+
+ $.fn.twbsPagination = function (option) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var methodReturn;
+
+ var $this = $(this);
+ var data = $this.data('twbs-pagination');
+ var options = typeof option === 'object' ? option : {};
+
+ if (!data) $this.data('twbs-pagination', (data = new TwbsPagination(this, options) ));
+ if (typeof option === 'string') methodReturn = data[ option ].apply(data, args);
+
+ return ( methodReturn === undefined ) ? $this : methodReturn;
+ };
+
+ $.fn.twbsPagination.defaults = {
+ totalPages: 1,
+ startPage: 1,
+ visiblePages: 5,
+ initiateStartPageClick: true,
+ hideOnlyOnePage: false,
+ href: false,
+ pageVariable: '{{page}}',
+ totalPagesVariable: '{{total_pages}}',
+ page: null,
+ first: 'First',
+ prev: 'Previous',
+ next: 'Next',
+ last: 'Last',
+ loop: false,
+ beforePageClick: null,
+ onPageClick: null,
+ paginationClass: 'pagination',
+ nextClass: 'page-item next',
+ prevClass: 'page-item prev',
+ lastClass: 'page-item last',
+ firstClass: 'page-item first',
+ pageClass: 'page-item',
+ activeClass: 'active',
+ disabledClass: 'disabled',
+ anchorClass: 'page-link'
+ };
+
+ $.fn.twbsPagination.Constructor = TwbsPagination;
+
+ $.fn.twbsPagination.noConflict = function () {
+ $.fn.twbsPagination = old;
+ return this;
+ };
+
+ $.fn.twbsPagination.version = "1.4.2";
+
+})(window.jQuery, window, document);
diff --git a/js/twbs-pagination/jquery.twbsPagination.min.js b/js/twbs-pagination/jquery.twbsPagination.min.js
new file mode 100644
index 000000000..315f27bc7
--- /dev/null
+++ b/js/twbs-pagination/jquery.twbsPagination.min.js
@@ -0,0 +1,10 @@
+/*
+ * jQuery Bootstrap Pagination v1.4.2
+ * https://github.com/josecebe/twbs-pagination
+ *
+ * Copyright 2014-2018, Eugene Simakin
+ * Released under Apache-2.0 license
+ * http://apache.org/licenses/LICENSE-2.0.html
+ */
+
+!function(o,e,t,s){"use strict";var i=o.fn.twbsPagination,r=function(t,s){if(this.$element=o(t),this.options=o.extend({},o.fn.twbsPagination.defaults,s),this.options.startPage<1||this.options.startPage>this.options.totalPages)throw new Error("Start page option is incorrect");if(this.options.totalPages=parseInt(this.options.totalPages),isNaN(this.options.totalPages))throw new Error("Total pages option is not correct!");if(this.options.visiblePages=parseInt(this.options.visiblePages),isNaN(this.options.visiblePages))throw new Error("Visible pages option is not correct!");if(this.options.beforePageClick instanceof Function&&this.$element.first().on("beforePage",this.options.beforePageClick),this.options.onPageClick instanceof Function&&this.$element.first().on("page",this.options.onPageClick),this.options.hideOnlyOnePage&&1==this.options.totalPages)return this.options.initiateStartPageClick&&this.$element.trigger("page",1),this;if(this.options.href&&(this.options.startPage=this.getPageFromQueryString(),this.options.startPage||(this.options.startPage=1)),"UL"===("function"==typeof this.$element.prop?this.$element.prop("tagName"):this.$element.attr("tagName")))this.$listContainer=this.$element;else{var e=this.$element,i=o([]);e.each(function(t){var s=o("");o(this).append(s),i.push(s[0])}),this.$listContainer=i,this.$element=i}return this.$listContainer.addClass(this.options.paginationClass),this.options.initiateStartPageClick?this.show(this.options.startPage):(this.currentPage=this.options.startPage,this.render(this.getPages(this.options.startPage)),this.setupEvents()),this};r.prototype={constructor:r,destroy:function(){return this.$element.empty(),this.$element.removeData("twbs-pagination"),this.$element.off("page"),this},show:function(t){if(t<1||t>this.options.totalPages)throw new Error("Page is incorrect.");this.currentPage=t,this.$element.trigger("beforePage",t);var s=this.getPages(t);return this.render(s),this.setupEvents(),this.$element.trigger("page",t),s},enable:function(){this.show(this.currentPage)},disable:function(){var t=this;this.$listContainer.off("click").on("click","li",function(t){t.preventDefault()}),this.$listContainer.children().each(function(){o(this).hasClass(t.options.activeClass)||o(this).addClass(t.options.disabledClass)})},buildListItems:function(t){var s=[];if(this.options.first&&s.push(this.buildItem("first",1)),this.options.prev){var e=1"),i=o(""),a=this.options[t]?this.makeText(this.options[t],s):s;return e.addClass(this.options[t+"Class"]),e.data("page",s),e.data("page-type",t),e.append(i.attr("href",this.makeHref(s)).addClass(this.options.anchorClass).html(a)),e},getPages:function(t){var s=[],e=Math.floor(this.options.visiblePages/2),i=t-e+1-this.options.visiblePages%2,a=t+e,n=this.options.visiblePages;n>this.options.totalPages&&(n=this.options.totalPages),i<=0&&(i=1,a=n),a>this.options.totalPages&&(i=this.options.totalPages-n+1,a=this.options.totalPages);for(var o=i;o<=a;)s.push(o),o++;return{currentPage:t,numeric:s}},render:function(s){var e=this;this.$listContainer.children().remove();var t=this.buildListItems(s);o.each(t,function(t,s){e.$listContainer.append(s)}),this.$listContainer.children().each(function(){var t=o(this);switch(t.data("page-type")){case"page":t.data("page")===s.currentPage&&t.addClass(e.options.activeClass);break;case"first":t.toggleClass(e.options.disabledClass,1===s.currentPage);break;case"last":t.toggleClass(e.options.disabledClass,s.currentPage===e.options.totalPages);break;case"prev":t.toggleClass(e.options.disabledClass,!e.options.loop&&1===s.currentPage);break;case"next":t.toggleClass(e.options.disabledClass,!e.options.loop&&s.currentPage===e.options.totalPages)}})},setupEvents:function(){var e=this;this.$listContainer.off("click").on("click","li",function(t){var s=o(this);if(s.hasClass(e.options.disabledClass)||s.hasClass(e.options.activeClass))return!1;!e.options.href&&t.preventDefault(),e.show(parseInt(s.data("page")))})},changeTotalPages:function(t,s){return this.options.totalPages=t,this.show(s)},makeHref:function(t){return this.options.href?this.generateQueryString(t):"#"},makeText:function(t,s){return t.replace(this.options.pageVariable,s).replace(this.options.totalPagesVariable,this.options.totalPages)},getPageFromQueryString:function(t){var s=this.getSearchString(t),e=new RegExp(this.options.pageVariable+"(=([^]*)|&|#|$)").exec(s);return e&&e[2]?(e=decodeURIComponent(e[2]),e=parseInt(e),isNaN(e)?null:e):null},generateQueryString:function(t,s){var e=this.getSearchString(s),i=new RegExp(this.options.pageVariable+"=*[^]*");return e?"?"+e.replace(i,this.options.pageVariable+"="+t):""},getSearchString:function(t){var s=t||e.location.search;return""===s?null:(0===s.indexOf("?")&&(s=s.substr(1)),s)},getCurrentPage:function(){return this.currentPage},getTotalPages:function(){return this.options.totalPages}},o.fn.twbsPagination=function(t){var s,e=Array.prototype.slice.call(arguments,1),i=o(this),a=i.data("twbs-pagination"),n="object"==typeof t?t:{};return a||i.data("twbs-pagination",a=new r(this,n)),"string"==typeof t&&(s=a[t].apply(a,e)),void 0===s?i:s},o.fn.twbsPagination.defaults={totalPages:1,startPage:1,visiblePages:5,initiateStartPageClick:!0,hideOnlyOnePage:!1,href:!1,pageVariable:"{{page}}",totalPagesVariable:"{{total_pages}}",page:null,first:"First",prev:"Previous",next:"Next",last:"Last",loop:!1,beforePageClick:null,onPageClick:null,paginationClass:"pagination",nextClass:"page-item next",prevClass:"page-item prev",lastClass:"page-item last",firstClass:"page-item first",pageClass:"page-item",activeClass:"active",disabledClass:"disabled",anchorClass:"page-link"},o.fn.twbsPagination.Constructor=r,o.fn.twbsPagination.noConflict=function(){return o.fn.twbsPagination=i,this},o.fn.twbsPagination.version="1.4.2"}(window.jQuery,window,document);
\ No newline at end of file