// Add module upgrader

This commit is contained in:
vSchoener
2011-12-19 17:54:54 +00:00
parent 94195342f6
commit e97baff814
5 changed files with 270 additions and 28 deletions
+3
View File
@@ -340,6 +340,9 @@ class FrontControllerCore extends Controller
$this->iso = $iso;
$this->setMedia();
// Customer wasn't defined at all
$customer = new StdClass();
if($this->context->cookie->id_country)
$customer->geoloc_id_country = (int)$this->context->cookie->id_country;
if($this->context->cookie->id_state)
+211 -13
View File
@@ -33,6 +33,12 @@ abstract class ModuleCore
/** @var float Version */
public $version;
/**
* @since 1.5.1
* @var string Registered Version in database
*/
public $registered_version;
/** @var array filled with known compliant PS versions */
public $ps_versions_compliancy = array('min' => '1.4', 'max' => '1.6');
@@ -74,9 +80,17 @@ abstract class ModuleCore
/** @var string Module web path (eg. '/shop/modules/modulename/') */
protected $_path = NULL;
/**
* @since 1.5.1
* @var string Module local path (eg. '/home/prestashop/modules/modulename/')
*/
protected $local_path = NULL;
/** @var protected array filled with module errors */
protected $_errors = false;
protected $_errors = array();
/** @var protected array filled with module success */
protected $_confirmations = array();
/** @var protected string main table used for modules installed */
protected $table = 'module';
@@ -152,6 +166,7 @@ abstract class ModuleCore
$this->{$key} = $value;
$this->_path = __PS_BASE_URI__.'modules/'.$this->name.'/';
}
$this->local_path = _PS_MODULE_DIR_.$this->name.'/';
}
}
@@ -213,19 +228,22 @@ abstract class ModuleCore
// Permissions management
Db::getInstance()->execute('
INSERT INTO `'._DB_PREFIX_.'module_access` (`id_profile`, `id_module`, `view`, `configure`) (
SELECT id_profile, '.(int)$this->id.', 1, 1
FROM '._DB_PREFIX_.'access a
WHERE id_tab = (SELECT `id_tab` FROM '._DB_PREFIX_.'tab WHERE class_name = \'AdminModules\' LIMIT 1)
AND a.`view` = 1
)');
INSERT INTO `'._DB_PREFIX_.'module_access` (`id_profile`, `id_module`, `view`, `configure`) (
SELECT id_profile, '.(int)$this->id.', 1, 1
FROM '._DB_PREFIX_.'access a
WHERE id_tab = (
SELECT `id_tab` FROM '._DB_PREFIX_.'tab
WHERE class_name = \'AdminModules\' LIMIT 1)
AND a.`view` = 1)');
Db::getInstance()->execute('
INSERT INTO `'._DB_PREFIX_.'module_access` (`id_profile`, `id_module`, `view`, `configure`) (
SELECT id_profile, '.(int)$this->id.', 1, 0
FROM '._DB_PREFIX_.'access a
WHERE id_tab = (SELECT `id_tab` FROM '._DB_PREFIX_.'tab WHERE class_name = \'AdminModules\' LIMIT 1)
AND a.`view` = 0
)');
INSERT INTO `'._DB_PREFIX_.'module_access` (`id_profile`, `id_module`, `view`, `configure`) (
SELECT id_profile, '.(int)$this->id.', 1, 0
FROM '._DB_PREFIX_.'access a
WHERE id_tab = (
SELECT `id_tab` FROM '._DB_PREFIX_.'tab
WHERE class_name = \'AdminModules\' LIMIT 1)
AND a.`view` = 0)');
// Adding Restrictions for client groups
Group::addRestrictionsForModule($this->id, Shop::getShops(true, null, true));
@@ -233,6 +251,179 @@ abstract class ModuleCore
return true;
}
/**
* Set errors, warning or success message of a module upgrade
*
* @param $upgrade_detail
*/
private function setUpgradeMessage($upgrade_detail)
{
// Store information if a module has been upgraded (memory optimization)
if ($upgrade_detail['available_upgrade'])
{
if ($upgrade_detail['success'])
{
$this->_confirmations[] = $this->l('Current version: ').$this->version;
$this->_confirmations[] = $upgrade_detail['number_upgraded'].' '.$this->l('file upgrade applied');
}
else
{
if (!$upgrade_detail['number_upgraded'])
$this->_errors[] = $this->l('None upgrades have been applied');
else
{
$this->_errors[] = $this->l('Upgraded from: ').$upgrade_detail['upgraded_from'].$this->l(' to ').
$upgrade_detail['upgraded_to'];
$this->_errors[] = $upgrade_detail['number_upgrade_left'].' '.$this->l('upgrade left');
}
$this->_errors[] = $this->l('To prevent any problem, this module has been turned off');
}
}
}
/**
* Init the upgrade module
*
* @static
* @param $module_name
* @param $module_version
* @return bool
*/
public static function initUpgradeModule($module_name, $module_version)
{
// Init cache upgrade details
self::$modules_cache[$module_name]['upgrade'] = array(
'success' => false, // bool to know if upgrade succeed or not
'available_upgrade' => 0, // Number of available module before any upgrade
'number_upgraded' => 0, // Number of upgrade done
'number_upgrade_left' => 0,
'upgrade_file_left' => array(), // List of the upgrade file left
'version_fail' => 0, // Version of the upgrade failure
'upgraded_from' => 0, // Version number before upgrading anything
'upgraded_to' => 0, // Last upgrade applied
);
// Need Upgrade will check and load upgrade file to the moduleCache upgrade case detail
return (bool)(Module::isInstalled($module_name) &&
Module::needUpgrade($module_name, $module_version));
}
/**
* Run the upgrade for a given module name and version
*
* @return array
*/
public function runUpgradeModule()
{
$upgrade = &self::$modules_cache[$this->name]['upgrade'];
foreach($upgrade['upgrade_file_left'] as $num => $file_detail)
{
// Default variable required in the included upgrade file need to be set by default there:
// upgrade_version, success_upgrade
$upgrade_result = false;
include($file_detail['file']);
// Call the upgrade function if defined
if (function_exists($file_detail['upgrade_function']))
$upgrade_result = $file_detail['upgrade_function']($this);
$upgrade['success'] = $upgrade_result;
// Set detail when an upgrade succeed or failed
if ($upgrade_result)
{
$upgrade['number_upgraded'] += 1;
$upgrade['upgraded_to'] = $file_detail['version'];
unset($upgrade['upgrade_file_left'][$num]);
}
else
{
$upgrade['version_fail'] = $file_detail['version'];
// If any errors, the module is disabled
$this->disable();
break;
}
}
$upgrade['number_upgrade_left'] = count($upgrade['upgrade_file_left']);
// Update module version in DB with the last succeed upgrade
if ($upgrade['upgraded_to'])
Db::getInstance()->execute('
UPDATE `'._DB_PREFIX_.'module` m
SET m.version = \''.bqSQL($upgrade['upgraded_to']).'\'
WHERE m.name = \''.bqSQL($this->name).'\'');
$this->setUpgradeMessage($upgrade);
return $upgrade;
}
/**
* Check if a module need to be upgraded.
* This method modify the module_cache adding an upgrade list file
*
* @static
* @param $module_name
* @param $module_version
* @return bool
*/
public static function needUpgrade($module_name, $module_version)
{
$registered_version = Db::getInstance()->getValue('
SELECT m.`version` FROM `'._DB_PREFIX_.'module` m
WHERE m.`name` = \''.bqSQL($module_name).'\'');
self::$modules_cache[$module_name]['upgrade']['upgraded_from'] = $registered_version;
// Check the version of the module with the registered one and look if any upgrade file exist
return (bool)(version_compare($module_version, $registered_version, '>') &&
Module::loadUpgradeVersionList($module_name, $module_version, $registered_version));
}
/**
* Load the available list of upgrade of a specified module
* with an associated version
*
* @static
* @param $module_name
* @param $registered_version
* @return bool to know directly if any files have been found
*/
private static function loadUpgradeVersionList($module_name, $module_version, $registered_version)
{
$list = array();
$upgradePath = _PS_MODULE_DIR_.$module_name.'/'.'upgrade/';
// Check if folder exist and it could be read
if (file_exists($upgradePath) && ($files = scandir($upgradePath)))
{
// Read each file name
foreach ($files as $file)
if (!in_array($file, array('.', '..', '.svn')))
{
$tab = explode('-', $file);
$file_version = basename($tab[1], '.php');
// Compare version, if minor than actual, we need to upgrade the module
if (count($tab) == 2 &&
(version_compare($file_version, $module_version, '<=') &&
version_compare($file_version, $registered_version, '>')))
{
$list[] = array(
'file' => $upgradePath.$file,
'version' => $file_version,
'upgrade_function' => 'upgrade_module_'.str_replace('.', '_', $file_version));
}
}
}
// Set the list to module cache
self::$modules_cache[$module_name]['upgrade']['upgrade_file_left'] = $list;
self::$modules_cache[$module_name]['upgrade']['available_upgrade'] = count($list);
return (bool)(count($list));
}
/**
* Delete module from datable
*
@@ -1398,5 +1589,12 @@ abstract class ModuleCore
* @return array errors
*/
public function getErrors() { return $this->_errors; }
/**
* Get module messages confirmation
* @since 1.5.1
* @return array conf
*/
public function getConfirmations() { return $this->_confirmations; }
}
+53 -15
View File
@@ -576,7 +576,7 @@ class AdminModulesControllerCore extends AdminController
elseif($echo === true)
$return = ($method == 'install' ? 12 : 13);
elseif ($echo === false)
$module_errors[] = array('name' => $name, 'errors' => $module->getErrors());
$module_errors[] = array('name' => $name, 'message' => $module->getErrors());
if (Shop::isFeatureActive() && Context::shop() != Shop::CONTEXT_ALL && isset(Context::getContext()->tmpOldShop))
{
@@ -590,17 +590,7 @@ class AdminModulesControllerCore extends AdminController
if (count($module_errors))
{
// If error during module installation, no redirection
$html_error = '<ul style="line-height:20px">';
foreach ($module_errors as $module_error)
{
$html_error_description = '';
if (count($module_error['errors']) > 0)
foreach ($module_error['errors'] as $e)
$html_error_description = '<br />'.$e;
$html_error .= '<li><b>- '.$module_error['name'].'</b> : '.$html_error_description.'</li>';
}
$html_error .= '</ul>';
$html_error = $this->generateHtmlMessage($module_errors);
$this->_errors[] = sprintf(Tools::displayError('The following module(s) were not installed successfully: %s'), $html_error);
}
}
@@ -630,10 +620,31 @@ class AdminModulesControllerCore extends AdminController
$this->postProcessCallback();
}
/**
* Generate html errors for a module process
*
* @param $module_errors
* @return string
*/
private function generateHtmlMessage($module_errors)
{
$html_error = '';
if (count($module_errors))
{
$html_error = '<ul style="line-height:20px">';
foreach ($module_errors as $module_error)
{
$html_error_description = '';
if (count($module_error['message']) > 0)
foreach ($module_error['message'] as $e)
$html_error_description .= '<br />'.$e;
$html_error .= '<li><b>- '.$module_error['name'].'</b> : '.$html_error_description.'</li>';
}
$html_error .= '</ul>';
}
return $html_error;
}
/*
** Display Modules Lists
@@ -792,9 +803,23 @@ class AdminModulesControllerCore extends AdminController
$this->initModulesList($modules);
$this->nb_modules_total = count($modules);
$module_errors = array();
$module_success = array();
// Browse modules list
foreach ($modules as $km => $module)
{
// Upgrade Module process, init check if a module could be upgraded
if (Module::initUpgradeModule($module->name, $module->version))
if ($object = new $module->name())
{
$object->runUpgradeModule();
if ((count($errors_module_list = $object->getErrors())))
$module_errors[] = array('name' => $module->name, 'message' => $errors_module_list);
else if ((count($conf_module_list = $object->getConfirmations())))
$module_success[] = array('name' => $module->name, 'message' => $conf_module_list);
}
// Make modules stats
$this->makeModulesStats($module);
@@ -831,6 +856,19 @@ class AdminModulesControllerCore extends AdminController
'option' => $this->displayModuleOptions($module)
)).', ';
}
unset($object);
}
// Actually used for the report of the upgraded errors
if (count($module_errors))
{
$html = $this->generateHtmlMessage($module_errors);
$this->_errors[] = sprintf(Tools::displayError('The following module(s) were not upgraded successfully: %s'), $html);
}
if (count($module_success))
{
$html = $this->generateHtmlMessage($module_success);
$this->confirmations[] = sprintf($this->l('The following module(s) were upgraded successfully:').' %s', $html);
}
// Init tpl vars for smarty
+1
View File
@@ -951,6 +951,7 @@ CREATE TABLE `PREFIX_module` (
`id_module` int(10) unsigned NOT NULL auto_increment,
`name` varchar(64) NOT NULL,
`active` tinyint(1) unsigned NOT NULL default '0',
`version` VARCHAR(8) NOT NULL,
PRIMARY KEY (`id_module`),
KEY `name` (`name`)
) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8;
+2
View File
@@ -1,5 +1,7 @@
SET NAMES 'utf8';
ALTER TABLE `PREFIX_module` ADD `version` VARCHAR( 8 ) NOT NULL;
INSERT INTO `PREFIX_access` (`id_profile`, `id_tab`, `view`, `add`, `edit`, `delete`) VALUES ('1', '108', '1', '1', '1', '1');
INSERT INTO `PREFIX_access` (`id_profile`, `id_tab`, `view`, `add`, `edit`, `delete`) VALUES ('2', '108', '1', '1', '1', '1');
INSERT INTO `PREFIX_access` (`id_profile`, `id_tab`, `view`, `add`, `edit`, `delete`) VALUES ('3', '108', '1', '1', '1', '1');