- Removed file system execute permission for all files (no directories)

- application/extensions file system permission now is 775
- application/logs file system permission now is 775
- Added extensions directory in application/: config, controllers, helpers, hooks, libraries, models, views and widgets
- Added view views/extensions/manage.php
- Added controller controllers/system/extensions/Manager.php
- Added library ExtensionsLib to manage extensions
- Added model models/system/Extensions_model.php
- Moved code related to print out info from MigrationLib to EPrintfLib
This commit is contained in:
Paolo
2017-11-13 10:45:49 +01:00
parent 3c4ca2a9cc
commit 0bc0a09bf4
1127 changed files with 1351 additions and 175 deletions
Executable → Regular
View File
Vendored Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
@@ -0,0 +1 @@
View File
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
View File
View File
View File
@@ -0,0 +1 @@
View File
View File
View File
View File
@@ -0,0 +1,83 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*
*/
class Manager extends VileSci_Controller
{
/**
*
*/
public function __construct()
{
parent::__construct();
// Load helpers to upload files
$this->load->helper(array('form', 'url'));
// Loads the extensions library
$this->load->library('ExtensionsLib');
}
/**
*
*/
public function index()
{
$viewData = array(
'extensions' => $this->extensionslib->getInstalledExtensions()
);
$this->load->view('core/system/extensions/manager.php', $viewData);
}
/**
*
*/
public function toggleExtension()
{
$toggleExtension = false;
$extension_id = $this->input->post('extension_id');
$enabled = $this->input->post('enabled');
if ($enabled === 'true')
{
$toggleExtension = $this->extensionslib->enableExtension($extension_id);
}
else
{
$toggleExtension = $this->extensionslib->disableExtension($extension_id);
}
$this->output
->set_content_type('application/json')
->set_output(json_encode($toggleExtension));
}
/**
*
*/
public function delExtension()
{
$delExtension = false;
$extension_id = $this->input->post('extension_id');
$delExtension = $this->extensionslib->delExtension($extension_id);
$this->output
->set_content_type('application/json')
->set_output(json_encode($delExtension));
}
/**
*
*/
public function uploadExtension()
{
$this->extensionslib->installExtension();
}
}
Executable → Regular
View File
@@ -0,0 +1 @@
Executable → Regular
View File
@@ -0,0 +1 @@
Executable → Regular
View File
Executable → Regular
View File
View File
Executable → Regular
View File
View File
+138
View File
@@ -0,0 +1,138 @@
<?php
if (! defined("BASEPATH")) exit("No direct script access allowed");
/**
* Enhanced printf utility library
* Usefull to print messages in a fancy and cool way from CLI and web interface
*/
class EPrintfLib
{
// Prefixes and separator for messages
const MSG_PREFIX = "[-]";
const INFO_PREFIX = "[I]";
const ERROR_PREFIX = "[E]";
const SEPARATOR = "------------------------------";
// Console colors codes
const ERROR_COLOR = 31;
const INFO_COLOR = 33;
const PRINT_QUERY_LEN = 60;
// HTML colors names
private $HTML_COLORS = array(31 => "red", 33 => "orange");
// Used to set if the migration process is called via command line or via browser
private $cli;
/**
* Object initialization
*/
public function __construct()
{
// Get code igniter instance
$this->ci =& get_instance();
$this->setCli();
}
// -------------------------------------------------------------------------------------------------
// Public methods
/**
* Prints a formatted message
*/
public function printMessage($message)
{
$this->_print(EPrintfLib::MSG_PREFIX, $message);
}
/**
* Prints a formatted info
*/
public function printInfo($info)
{
$this->_print(EPrintfLib::INFO_PREFIX, $info, EPrintfLib::INFO_COLOR);
}
/**
* Prints a formatted error
*/
public function printError($error)
{
$this->_print(EPrintfLib::ERROR_PREFIX, $error, EPrintfLib::ERROR_COLOR);
}
/**
* Print only the end of line
*/
public function printEOL()
{
echo $this->getEOL();
}
// -------------------------------------------------------------------------------------------------
// Private methods
/**
* Set property cli to false if the migration process is called via command line
* otherwise to false if it's called via browser
*/
private function setCli()
{
if ($this->ci->input->is_cli_request())
{
$this->cli = true;
}
else
{
$this->cli = false;
}
}
/**
* Returns the character of end of line
* PHP_EOL platform dependent if cli is true
* Tag <br> if cli is false
*/
private function getEOL()
{
if ($this->cli === true)
{
return PHP_EOL;
}
else
{
return "<br>";
}
}
/**
* Returns the string needed to color the output
*/
private function getColored($color)
{
$colored = "%s";
if (!is_null($color))
{
if ($this->cli === true)
{
$colored = "\033[".$color."m%s\033[37m";
}
else
{
$colored = "<font color=\"".$this->HTML_COLORS[$color]."\">%s</font>";
}
}
return $colored;
}
/**
* Print a message, even colored if specified
*/
private function _print($prefix, $text, $color = null)
{
printf($this->getColored($color), sprintf("%s %s".$this->getEOL(), $prefix, $text));
}
}
+824
View File
@@ -0,0 +1,824 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Library to manage core extensions
*/
class ExtensionsLib
{
const SQL_DIRECTORY = 'sql';
const SQL_FILE_EXTENSION = '.sql';
const FILE_INPUT_NAME = 'extension';
const ARCHIVE_EXTENSIONS = array('.tgz', '.tbz2');
const EXTENSION_JSON_NAME = 'extension.json';
const EXTENSIONS_PATH = APPPATH.'extensions/';
const UPLOAD_PATH = ExtensionsLib::EXTENSIONS_PATH.'tmp/';
const DIRECTORIES_BLACKLIST = array('api', 'bo', 'core', 'errors', 'jobs', 'html', 'ms', 'tmp', 'udf');
const SOFTLINK_TARGET_DIRECTORIES = array('config', 'controllers', 'helpers', 'libraries', 'models', 'views', 'widgets');
private $_errorOccurred; //
private $_currentInstalledExtensionVersion; //
/**
* Class constructor
*/
public function __construct()
{
// Get code igniter instance
$this->ci =& get_instance();
// Loads message configurationx
$this->ci->config->load('message');
// Loads EPrintfLib
$this->ci->load->library('EPrintfLib');
// Loading models
$this->ci->load->model('core/system/Extensions_model', 'ExtensionsModel');
//
$this->_errorOccurred = false;
$this->_currentInstalledExtensionVersion = 0;
}
// -------------------------------------------------------------------------------------------------
// Public methods
/**
*
*/
public function installExtension()
{
$extensionDB = null;
$extensionJson = null;
$this->_printInfo('WARNING!!! Please do not change page or stop this procedure before it is finished');
$this->_loadUploadLibrary();
$uploadData = $this->_uploadExtension();
if ($uploadData != null)
{
$this->_extractExtension($uploadData->fullPath);
if (!$this->_errorOccurred)
{
$extensionDB = $this->_loadPreviousInstallation($uploadData->extensionName);
}
if (!$this->_errorOccurred)
{
$this->_chkFSStructure($uploadData->extensionName);
}
if (!$this->_errorOccurred)
{
$extensionJson = $this->_chkExtensionJson($uploadData->extensionName, $extensionDB);
}
if ($extensionJson != null)
{
$this->_printStart('Proceding with the installation of the extension: '.$extensionJson->name);
$this->_printEnd();
$this->_cleanPreviousInstallation($extensionJson);
$this->_installExtension($extensionJson);
if (!$this->_errorOccurred)
{
$this->_loadSQLs(
ExtensionsLib::UPLOAD_PATH.$extensionJson->name.'/'.ExtensionsLib::SQL_DIRECTORY,
$extensionJson
);
}
if (!$this->_errorOccurred)
{
$this->_moveExtension($extensionJson->name);
}
if (!$this->_errorOccurred)
{
$this->_createSymLinks($extensionJson->name);
}
}
else
{
$this->_errorOccurred = true;
}
}
else
{
$this->_errorOccurred = true;
}
if ($this->_errorOccurred === false)
{
if (!$this->_rrm($uploadData->fullPath))
{
$this->_printInfo('Error while cleaning upload directory. Not a blocking error');
}
$this->_printMessage('Extension correctly installed, you can safely close this page');
}
else
{
$this->_printError('There was a blocking error while installing/updating an extension, rolling back');
$this->_rollback($uploadData, $extensionDB, $extensionJson);
}
}
/**
*
*/
public function delExtension($extensionId)
{
$delExtension = false;
$result = $this->ci->ExtensionsModel->load($extensionId);
if (hasData($result))
{
$extensionName = $result->retval[0]->name;
$this->_delSoftLinks($extensionName); // not to be checked, could fail if the extension is disabled
$delExtension = $this->_rrm(ExtensionsLib::EXTENSIONS_PATH.$extensionName);
$this->ci->ExtensionsModel->addSelect('extension_id');
$result = $this->ci->ExtensionsModel->loadWhere(array('name' => $extensionName));
if (hasData($result))
{
$extsArray = array();
foreach ($result->retval as $key => $extension)
{
$result = $this->ci->ExtensionsModel->delete($extension->extension_id);
if (isSuccess($result))
{
$delExtension = true;
}
}
}
}
return $delExtension;
}
/**
*
*/
public function getInstalledExtensions()
{
return $this->ci->ExtensionsModel->getInstalledExtensions();
}
/**
*
*/
public function enableExtension($extensionId)
{
return $this->_toggleExtension($extensionId, true);
}
/**
*
*/
public function disableExtension($extensionId)
{
return $this->_toggleExtension($extensionId, false);
}
// -------------------------------------------------------------------------------------------------
// Private methods
/**
*
*/
private function _loadUploadLibrary()
{
$this->ci->load->library(
'upload',
array(
'upload_path' => ExtensionsLib::UPLOAD_PATH,
'allowed_types' => '*',
'overwrite' => true
)
);
}
/**
*
*/
private function _uploadExtension()
{
$_uploadExtension = null;
$this->_printStart('Uploading extension');
if ($this->ci->upload->do_upload(ExtensionsLib::FILE_INPUT_NAME))
{
$uploadData = $this->ci->upload->data();
$uploadedFileExtension = '.'.pathinfo($uploadData['full_path'], PATHINFO_EXTENSION);
if (!in_array($uploadedFileExtension, ExtensionsLib::ARCHIVE_EXTENSIONS))
{
$this->_printFailure('file extension must be tgz OR tbz2');
if (isset($uploadData['full_path']) && file_exists($uploadData['full_path']))
{
$this->_rrm($uploadData['full_path']);
}
}
else
{
$_uploadExtension = new stdClass();
$_uploadExtension->extensionName = str_replace(ExtensionsLib::ARCHIVE_EXTENSIONS, '', $uploadData['file_name']);
$_uploadExtension->fullPath = $uploadData['full_path'];
}
}
else
{
$this->_printFailure($this->ci->upload->display_errors('', ''));
}
$this->_printSuccess($_uploadExtension != null);
$this->_printEnd();
return $_uploadExtension;
}
/**
*
*/
private function _extractExtension($uploadPath)
{
$this->_printStart('Extracting extension');
try
{
$pd = new PharData($uploadPath);
$pd->extractTo(ExtensionsLib::UPLOAD_PATH, null, true);
}
catch (UnexpectedValueException $uva)
{
$this->_errorOccurred = true;
$this->_printFailure('provided an invalid archive');
}
catch (PharException $pe)
{
$this->_errorOccurred = true;
$this->_printFailure('generic error occurred, check logs');
}
$this->_printSuccess(!$this->_errorOccurred);
$this->_printEnd();
}
/**
*
*/
private function _loadPreviousInstallation($extensionName)
{
$extensionDB = null;
$this->_printStart('Loads any previous installation data');
$this->ci->ExtensionsModel->addOrder('version', 'DESC');
$this->ci->ExtensionsModel->addLimit(1);
$result = $this->ci->ExtensionsModel->loadWhere(array('name' => $extensionName));
if (isError($result))
{
$this->_errorOccurred = true;
$this->_printFailure('data base error');
}
else
{
if (hasData($result))
{
$extensionDB = $result->retval[0];
}
else
{
$this->_printMessage('not found');
}
}
$this->_printSuccess(!$this->_errorOccurred);
$this->_printEnd();
return $extensionDB;
}
/**
*
*/
private function _chkFSStructure($extensionName)
{
$this->_printStart('Checking extension file system structure');
if (is_dir(ExtensionsLib::UPLOAD_PATH.$extensionName))
{
if (!file_exists(ExtensionsLib::UPLOAD_PATH.$extensionName.'/'.ExtensionsLib::EXTENSION_JSON_NAME))
{
$this->_errorOccurred = true;
$this->_printFailure('missing extension.json');
}
}
else
{
$this->_errorOccurred = true;
$this->_printFailure('the root directory of the archive must have the same extension name');
}
$this->_printSuccess(!$this->_errorOccurred);
$this->_printEnd();
}
/**
*
*/
private function _chkExtensionJson($extensionName, $extensionDB)
{
$this->_printStart('Parsing and checking extension.json');
$extensionJson = json_decode(
file_get_contents(ExtensionsLib::UPLOAD_PATH.$extensionName.'/'.ExtensionsLib::EXTENSION_JSON_NAME)
);
if ($extensionJson != null && isset($extensionJson->name) && $extensionJson->name == $extensionName)
{
if (isset($extensionJson->version))
{
$extensionJson->currentInstalledVersion = 0;
if ($extensionDB != null)
{
$extensionJson->extension_id = $extensionDB->extension_id; //
$extensionJson->currentInstalledVersion = $extensionDB->version;
$this->_printMessage('Extension already installed!');
$this->_printMessage('Current version: '.$extensionDB->version);
$this->_printMessage('Version of the uploaded extension: '.$extensionJson->version);
if ($extensionJson->version == $extensionDB->version)
{
$this->_printMessage('Updating the same version!');
}
elseif ($extensionJson->version > $extensionDB->version)
{
$this->_printMessage('Updating to a new version!');
}
else
{
$extensionJson = null;
$this->_printFailure('downgrade must be performed manually');
}
}
else
{
$this->_printMessage('Version of the uploaded extension: '.$extensionJson->version);
}
if ($extensionJson != null)
{
require_once('version.php');
if (isset($extensionJson->core_version) && $extensionJson->core_version == $fhcomplete_version)
{
$this->_printMessage('Required core version: '.$extensionJson->core_version);
$this->_printMessage('Current core version: '.$fhcomplete_version);
if (isset($extensionJson->dependencies)
&& is_array($extensionJson->dependencies)
&& count($extensionJson->dependencies) > 0)
{
$result = $this->ci->ExtensionsModel->getDependencies($extensionJson->dependencies);
if (hasData($result) && count($result->retval) == count($extensionJson->dependencies))
{
if (isset($extensionJson->dependencies))
{
$extensionJson->dependencies = str_replace('[', '{', json_encode($extensionJson->dependencies));
$extensionJson->dependencies = str_replace(']', '}', $extensionJson->dependencies);
$this->_printMessage('Required dependencies: '.$extensionJson->dependencies);
}
else
{
$extensionJson->dependencies = '';
$this->_printMessage('No dependencies are required');
}
}
else
{
$extensionJson = null;
$this->_printFailure('dependencies are missing, install them to proceed');
}
}
elseif (isset($extensionJson->dependencies) && !is_array($extensionJson->dependencies))
{
$extensionJson = null;
$this->_printFailure('dependencies parameter must be an array');
}
elseif (!isset($extensionJson->dependencies))
{
$this->_printMessage('No dependencies are required');
}
}
else
{
$extensionJson = null;
$this->_printFailure('core_version parameter is missing or it is not equal to the versione of the core');
}
}
}
else
{
$extensionJson = null;
$this->_printFailure('version is missing');
}
}
else
{
$extensionJson = null;
$this->_printFailure('name is missing or not equal to extension name');
}
$this->_printSuccess($extensionJson != null);
$this->_printEnd();
return $extensionJson;
}
/**
*
*/
private function _cleanPreviousInstallation($extensionJson)
{
$this->_printStart('Cleaning any previous installations in DB and file system');
if (isset($extensionJson->extension_id))
{
if ($this->delExtension($extensionJson->extension_id))
{
$this->_printSuccess(true);
}
else
{
$this->_printFailure('please check logs');
}
}
else
{
$this->_printMessage('No need to clean, no previous installations found');
}
$this->_printEnd();
}
/**
*
*/
private function _installExtension($extensionJson)
{
$this->_printStart('Adding new entry in the DB');
$result = $this->ci->ExtensionsModel->insert(
array(
'name' => $extensionJson->name,
'description' => isset($extensionJson->description) ? $extensionJson->description : null,
'version' => $extensionJson->version,
'license' => isset($extensionJson->license) ? $extensionJson->license : null,
'url' => isset($extensionJson->url) ? $extensionJson->url : null,
'core_version' => $extensionJson->core_version,
'dependencies' => $extensionJson->dependencies
)
);
if (isSuccess($result))
{
$this->_printSuccess(true);
}
else
{
$this->_errorOccurred = true;
$this->_printFailure('error while saving extension into DB');
}
$this->_printEnd();
}
/**
* TODO
*/
private function _loadSQLs($pkgSQLsPath, $extensionJson)
{
$this->_printStart('Loading and executing SQL files');
for ($sqlDir = $extensionJson->currentInstalledVersion; $sqlDir <= $extensionJson->version; $sqlDir++)
{
if (($files = glob($pkgSQLsPath.'/'.$sqlDir.'/*'.ExtensionsLib::SQL_FILE_EXTENSION)) != false)
{
foreach ($files as $file)
{
$sql = file_get_contents($file);
$this->_printMessage('Executing query:');
$this->_printMessage($sql);
if (!isSuccess($result = @$this->ci->ExtensionsModel->executeQuery($sql)))
{
$this->_errorOccurred = true;
$this->_printFailure(' error occurred while executing the query');
$this->_printInfo('Is not possible to rollback the DB changes, must be done manually');
break;
}
else
{
$this->_printMessage('Query result:');
var_dump($result->retval);
$this->ci->eprintflib->printEOL();
}
}
}
}
$this->_printSuccess(!$this->_errorOccurred);
$this->_printEnd();
}
/**
*
*/
private function _moveExtension($extensionName)
{
$this->_printStart('Moving the upload extension from upload folder to extension folder');
$this->_printMessage('Current extension directory: '.ExtensionsLib::UPLOAD_PATH.$extensionName);
$this->_printMessage('Directory where it will be moved: '.ExtensionsLib::EXTENSIONS_PATH.$extensionName);
if (rename(ExtensionsLib::UPLOAD_PATH.$extensionName.'/', ExtensionsLib::EXTENSIONS_PATH.$extensionName))
{
$this->_printSuccess(true);
}
else
{
$this->_errorOccurred = true;
$this->_printFailure('error while moving');
}
$this->_printEnd();
}
/**
*
*/
private function _createSymLinks($extensionName)
{
$this->_printStart('Creating symlinks');
if ($this->_addSoftLinks($extensionName))
{
$this->_printSuccess(true);
}
else
{
$this->_errorOccurred = true;
$this->_printFailure('error while creating sym links');
}
$this->_printEnd();
}
/**
*
*/
private function _delSoftLinks($extensionName)
{
$_delSoftLinks = false;
foreach (ExtensionsLib::SOFTLINK_TARGET_DIRECTORIES as $key => $targetDirectory)
{
if (file_exists(APPPATH.$targetDirectory.'/'.$extensionName))
{
$_delSoftLinks = unlink(APPPATH.$targetDirectory.'/'.$extensionName);
if (!$_delSoftLinks)
{
break;
}
}
}
return $_delSoftLinks;
}
/**
* Recursive remove
*/
private function _rrm($dir)
{
if (!file_exists($dir))
{
return true;
}
if (!is_dir($dir))
{
return unlink($dir);
}
foreach (scandir($dir) as $item)
{
if ($item == '.' || $item == '..')
{
continue;
}
if (!$this->_rrm($dir . DIRECTORY_SEPARATOR . $item))
{
return false;
}
}
return rmdir($dir);
}
/**
*
*/
private function _addSoftLinks($extensionName)
{
$_addSoftLinks = false;
$extensionPath = ExtensionsLib::EXTENSIONS_PATH.$extensionName.'/';
foreach (ExtensionsLib::SOFTLINK_TARGET_DIRECTORIES as $key => $targetDirectory)
{
if (!file_exists(APPPATH.$targetDirectory.'/'.$extensionName))
{
if (!is_dir($extensionPath.$targetDirectory))
{
mkdir($extensionPath.$targetDirectory);
}
$_addSoftLinks = symlink($extensionPath.$targetDirectory, APPPATH.$targetDirectory.'/'.$extensionName);
if (!$_addSoftLinks)
{
break;
}
}
}
return $_addSoftLinks;
}
/**
*
*/
private function _rollback($uploadData, $extensionDB, $extensionJson)
{
$this->_printStart('Rolling back the installation');
$this->_printMessage('Removing the uploaded file from upload directory');
if ($uploadData != null && isset($uploadData->fullPath) && file_exists($uploadData->fullPath))
{
$this->_rrm($uploadData->fullPath);
}
$this->_printMessage('Removing the extracted data from the upload directory');
if ($uploadData != null
&& isset($uploadData->extensionName)
&& file_exists(ExtensionsLib::UPLOAD_PATH.$uploadData->extensionName))
{
$this->_rrm(ExtensionsLib::UPLOAD_PATH.$uploadData->extensionName);
}
if ($uploadData != null && isset($uploadData->extensionName) && $extensionDB == null)
{
$this->ci->ExtensionsModel->addOrder('version', 'DESC');
$this->ci->ExtensionsModel->addLimit(1);
$result = $this->ci->ExtensionsModel->loadWhere(array('name' => $uploadData->extensionName));
if (hasData($result))
{
$this->_printMessage('Removing entries in the DB related to this extension');
$this->delExtension($result->retval[0]->extension_id);
}
}
else
{
if ($extensionJson != null && isset($extensionJson->extension_id))
{
$this->ci->ExtensionsModel->delete($extensionJson->extension_id);
}
}
$this->_printMessage('Rollback finished');
$this->_printEnd();
}
/**
*
*/
private function _toggleExtension($extensionId, $enabled)
{
$_toggleExtension = false;
$result = $this->ci->ExtensionsModel->load($extensionId);
if (hasData($result))
{
$extensionName = $result->retval[0]->name;
if (!in_array($extensionName, ExtensionsLib::DIRECTORIES_BLACKLIST))
{
if ($enabled === true)
{
$_toggleExtension = $this->_addSoftLinks($extensionName);
}
else
{
$_toggleExtension = $this->_delSoftLinks($extensionName);
}
if ($_toggleExtension)
{
$result = $this->ci->ExtensionsModel->update($extensionId, array('enabled' => $enabled));
if (isSuccess($result))
{
$_toggleExtension = true;
}
else
{
$this->_delSoftLinks($extensionName);
}
}
}
}
return $_toggleExtension;
}
/**
*
*/
private function _printError($error)
{
$this->ci->eprintflib->printError($error);
}
/**
*
*/
private function _printFailure($error)
{
$this->_printError('Failed: '.$error);
}
/**
*
*/
private function _printMessage($message)
{
$this->ci->eprintflib->printMessage($message);
}
/**
*
*/
private function _printSuccess($cond)
{
if ($cond === true)
{
$this->_printMessage('Success!!!');
}
}
/**
*
*/
private function _printInfo($info)
{
$this->ci->eprintflib->printInfo($info);
}
/**
*
*/
private function _printStart($startMessage)
{
$this->_printInfo('------------------------------------------------------------------------------------------');
$this->_printMessage($startMessage);
}
/**
*
*/
private function _printEnd()
{
$this->_printInfo('------------------------------------------------------------------------------------------');
}
}
View File
View File
+74 -175
View File
@@ -7,173 +7,72 @@ if (! defined("BASEPATH")) exit("No direct script access allowed");
*/
class MigrationLib extends CI_Migration
{
// Prefixes and separator for messages
const MSG_PREFIX = "[-]";
const INFO_PREFIX = "[I]";
const ERROR_PREFIX = "[E]";
const SEPARATOR = "------------------------------";
// Console colors codes
const ERROR_COLOR = 31;
const INFO_COLOR = 33;
const PRINT_QUERY_LEN = 60;
// HTML colors names
private $HTML_COLORS = array(31 => "red", 33 => "orange");
// Used to set if the migration process is called via command line or via browser
private $cli;
/**
* Object initialization
*/
public function __construct()
{
parent::__construct();
$this->setCli();
// Loads EPrintfLib
$this->load->library('EPrintfLib');
}
/**
* Set property cli to false if the migration process is called via command line
* otherwise to false if it's called via browser
*/
private function setCli()
{
if ($this->input->is_cli_request())
{
$this->cli = true;
}
else
{
$this->cli = false;
}
}
/**
* Returns the character of end of line
* PHP_EOL platform dependent if cli is true
* Tag <br> if cli is false
*/
private function getEOL()
{
if ($this->cli === true)
{
return PHP_EOL;
}
else
{
return "<br>";
}
}
/**
* Returns the string needed to color the output
*/
private function getColored($color)
{
$colored = "%s";
if (!is_null($color))
{
if ($this->cli === true)
{
$colored = "\033[".$color."m%s\033[37m";
}
else
{
$colored = "<font color=\"".$this->HTML_COLORS[$color]."\">%s</font>";
}
}
return $colored;
}
/**
* Print a message, even colored if specified
*/
private function _print($prefix, $text, $color = null)
{
printf($this->getColored($color), sprintf("%s %s".$this->getEOL(), $prefix, $text));
}
/**
* Prints a formatted message
*/
private function printMessage($message)
{
$this->_print(MigrationLib::MSG_PREFIX, $message);
}
/**
* Prints a formatted info
*/
private function printInfo($info)
{
$this->_print(MigrationLib::INFO_PREFIX, $info, MigrationLib::INFO_COLOR);
}
/**
* Prints a formatted error
*/
private function printError($error)
{
$this->_print(MigrationLib::ERROR_PREFIX, $error, MigrationLib::ERROR_COLOR);
}
/**
* Check if a column exists in a table and schema
*/
private function columnExists($name, $schema, $table)
{
$query = sprintf("SELECT %s FROM %s.%s LIMIT 1", $name, $schema, $table);
if (@$this->db->simple_query($query))
{
return true;
}
return false;
}
/**
* Print an info about the starting of method up
*/
protected function startUP()
{
$this->printInfo(
sprintf("%s Start method up of class %s %s", MigrationLib::SEPARATOR, get_called_class(), MigrationLib::SEPARATOR)
$this->eprintflib->printInfo(
sprintf("%s Start method up of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR)
);
}
/**
* Print an info about the ending of method up
*/
protected function endUP()
{
$this->printInfo(
sprintf("%s End method up of class %s %s", MigrationLib::SEPARATOR, get_called_class(), MigrationLib::SEPARATOR)
$this->eprintflib->printInfo(
sprintf("%s End method up of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR)
);
}
/**
* Print an info about the starting of method down
*/
protected function startDown()
{
$this->printInfo(
sprintf("%s Start method down of class %s %s", MigrationLib::SEPARATOR, get_called_class(), MigrationLib::SEPARATOR)
$this->eprintflib->printInfo(
sprintf("%s Start method down of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR)
);
}
/**
* Print an info about the ending of method down
*/
protected function endDown()
{
$this->printInfo(
sprintf("%s End method down of class %s %s", MigrationLib::SEPARATOR, get_called_class(), MigrationLib::SEPARATOR)
$this->eprintflib->printInfo(
sprintf("%s End method down of class %s %s", EPrintfLib::SEPARATOR, get_called_class(), EPrintfLib::SEPARATOR)
);
}
/**
* Adds a column, with attributes, to a table and schema
*/
@@ -185,20 +84,20 @@ class MigrationLib extends CI_Migration
{
if ($this->dbforge->add_column($schema.'.'.$table, array($name => $definition)))
{
$this->printMessage(sprintf("Column %s.%s.%s of type %s added", $schema, $table, $name, $definition["type"]));
$this->eprintflib->printMessage(sprintf("Column %s.%s.%s of type %s added", $schema, $table, $name, $definition["type"]));
}
else
{
$this->printError(sprintf("Error while adding column %s.%s.%s of type %s", $schema, $table, $name, $definition["type"]));
$this->eprintflib->printError(sprintf("Error while adding column %s.%s.%s of type %s", $schema, $table, $name, $definition["type"]));
}
}
else
{
$this->printInfo(sprintf("Column %s.%s.%s already exists", $schema, $table, $name));
$this->eprintflib->printInfo(sprintf("Column %s.%s.%s already exists", $schema, $table, $name));
}
}
}
/**
* Modifies a column, and its attributes, of a table and schema
*/
@@ -210,20 +109,20 @@ class MigrationLib extends CI_Migration
{
if ($this->dbforge->modify_column($schema.'.'.$table, array($name => $definition)))
{
$this->printMessage(sprintf("Column %s.%s.%s has been modified", $schema, $table, $name));
$this->eprintflib->printMessage(sprintf("Column %s.%s.%s has been modified", $schema, $table, $name));
}
else
{
$this->printError(sprintf("Error while modifying column %s.%s.%s", $schema, $table, $name));
$this->eprintflib->printError(sprintf("Error while modifying column %s.%s.%s", $schema, $table, $name));
}
}
else
{
$this->printInfo(sprintf("Column %s.%s.%s doesn't exist", $schema, $table, $name));
$this->eprintflib->printInfo(sprintf("Column %s.%s.%s doesn't exist", $schema, $table, $name));
}
}
}
/**
* Drops a column from a table and schema
*/
@@ -233,19 +132,19 @@ class MigrationLib extends CI_Migration
{
if ($this->dbforge->drop_column($schema.'.'.$table, $field))
{
$this->printMessage(sprintf("Column %s.%s.%s has been dropped", $schema, $table, $field));
$this->eprintflib->printMessage(sprintf("Column %s.%s.%s has been dropped", $schema, $table, $field));
}
else
{
$this->printError(sprintf("Error while dropping column %s.%s.%s", $schema, $table, $field));
$this->eprintflib->printError(sprintf("Error while dropping column %s.%s.%s", $schema, $table, $field));
}
}
else
{
$this->printInfo(sprintf("Column %s.%s.%s doesn't exist", $schema, $table, $field));
$this->eprintflib->printInfo(sprintf("Column %s.%s.%s doesn't exist", $schema, $table, $field));
}
}
/**
* Sets a column as primary key of a table and schema
*/
@@ -273,17 +172,17 @@ class MigrationLib extends CI_Migration
{
$query = sprintf("ALTER TABLE %s.%s ADD CONSTRAINT %s PRIMARY KEY (%s)", $schema, $table, $name, $fields);
}
if (@$this->db->simple_query($query))
{
$this->printMessage(sprintf("Added primary key %s on table %s.%s", $name, $schema, $table));
$this->eprintflib->printMessage(sprintf("Added primary key %s on table %s.%s", $name, $schema, $table));
}
else
{
$this->printError(sprintf("Adding primary key %s on table %s.%s", $name, $schema, $table));
$this->eprintflib->printError(sprintf("Adding primary key %s on table %s.%s", $name, $schema, $table));
}
}
/**
* Sets a column as foreign key of a table and schema
*/
@@ -300,17 +199,17 @@ class MigrationLib extends CI_Migration
$fieldDest,
$attributes
);
if (@$this->db->simple_query($query))
{
$this->printMessage(sprintf("Added foreign key %s on table %s.%s", $name, $schema, $table));
$this->eprintflib->printMessage(sprintf("Added foreign key %s on table %s.%s", $name, $schema, $table));
}
else
{
$this->printError(sprintf("Adding foreign key %s on table %s.%s", $name, $schema, $table));
$this->eprintflib->printError(sprintf("Adding foreign key %s on table %s.%s", $name, $schema, $table));
}
}
/**
* Sets a column as unique key of a table and schema
*/
@@ -338,17 +237,17 @@ class MigrationLib extends CI_Migration
{
$query = sprintf("CREATE UNIQUE INDEX %s ON %s.%s (%s)", $name, $schema, $table, $fields);
}
if (@$this->db->simple_query($query))
{
$this->printMessage(sprintf("Added unique key %s on table %s.%s", $name, $schema, $table));
$this->eprintflib->printMessage(sprintf("Added unique key %s on table %s.%s", $name, $schema, $table));
}
else
{
$this->printError(sprintf("Adding unique key %s on table %s.%s", $name, $schema, $table));
$this->eprintflib->printError(sprintf("Adding unique key %s on table %s.%s", $name, $schema, $table));
}
}
/**
* Grants permissions to a user on a table and schema
*/
@@ -379,7 +278,7 @@ class MigrationLib extends CI_Migration
if (@$this->db->simple_query($query))
{
$this->printMessage(
$this->eprintflib->printMessage(
sprintf(
"Granted permissions %s on table %s.%s to user %s",
is_null($stringPermission) ? $permissions : $stringPermission,
@@ -391,7 +290,7 @@ class MigrationLib extends CI_Migration
}
else
{
$this->printError(
$this->eprintflib->printError(
sprintf(
"Granting permissions %s on table %s.%s to user %s",
is_null($stringPermission) ? $permissions : $stringPermission,
@@ -402,24 +301,24 @@ class MigrationLib extends CI_Migration
);
}
}
/**
* Creates a table in a schema with columns
*/
protected function createTable($schema, $table, $fields)
{
$this->dbforge->add_field($fields);
if ($this->dbforge->create_table($schema.'.'.$table, true))
{
$this->printMessage(sprintf("Table %s.%s created or existing", $schema, $table));
$this->eprintflib->printMessage(sprintf("Table %s.%s created or existing", $schema, $table));
}
else
{
$this->printError(sprintf("Creating table %s.%s", $schema, $table));
$this->eprintflib->printError(sprintf("Creating table %s.%s", $schema, $table));
}
}
/**
* Drops a table from a schema
*/
@@ -427,62 +326,62 @@ class MigrationLib extends CI_Migration
{
if ($this->dbforge->drop_table($schema.".".$table))
{
$this->printMessage(sprintf("Table %s.%s has been dropped", $schema, $table));
$this->eprintflib->printMessage(sprintf("Table %s.%s has been dropped", $schema, $table));
}
else
{
$this->printError(sprintf("Dropping table %s.%s", $schema, $table));
$this->eprintflib->printError(sprintf("Dropping table %s.%s", $schema, $table));
}
}
/**
* Initializes a sequence with the max value of a column
*/
protected function initializeSequence($schemaSrc, $sequence, $schemaDst, $table, $field)
{
$query = sprintf("SELECT SETVAL('%s.%s', (SELECT MAX(%s) FROM %s.%s))", $schemaSrc, $sequence, $field, $schemaDst, $table);
if (@$this->db->simple_query($query))
{
$this->printMessage(sprintf("Sequence %s.%s has been initialized", $schemaSrc, $sequence));
$this->eprintflib->printMessage(sprintf("Sequence %s.%s has been initialized", $schemaSrc, $sequence));
}
else
{
$this->printError(sprintf("Initializing sequence %s.%s", $schemaSrc, $sequence));
$this->eprintflib->printError(sprintf("Initializing sequence %s.%s", $schemaSrc, $sequence));
}
}
/**
* Add comment to a column
*/
protected function addCommentToColumn($schema, $table, $field, $comment)
{
$query = sprintf("COMMENT ON COLUMN %s.%s.%s IS ?", $schema, $table, $field);
if (@$this->db->query($query, array($comment)))
{
$this->printMessage(sprintf("Comment added to %s.%s.%s", $schema, $table, $field));
$this->eprintflib->printMessage(sprintf("Comment added to %s.%s.%s", $schema, $table, $field));
}
else
{
$this->printError(sprintf("Error while adding comment to %s.%s.%s", $schema, $table, $field));
$this->eprintflib->printError(sprintf("Error while adding comment to %s.%s.%s", $schema, $table, $field));
}
}
/**
* Add comment to a table
*/
protected function addCommentToTable($schema, $table, $comment)
{
$query = sprintf("COMMENT ON TABLE %s.%s IS ?", $schema, $table, $field);
if (@$this->db->query($query, array($comment)))
{
$this->printMessage(sprintf("Comment added to %s.%s", $schema, $table));
$this->eprintflib->printMessage(sprintf("Comment added to %s.%s", $schema, $table));
}
else
{
$this->printError(sprintf("Error while adding comment to %s.%s", $schema, $table));
$this->eprintflib->printError(sprintf("Error while adding comment to %s.%s", $schema, $table));
}
}
/**
@@ -515,7 +414,7 @@ class MigrationLib extends CI_Migration
if (@$this->db->simple_query($query))
{
$this->printMessage(
$this->eprintflib->printMessage(
sprintf(
"Granted permissions %s on sequence %s.%s to user %s",
is_null($stringPermission) ? $permissions : $stringPermission,
@@ -527,7 +426,7 @@ class MigrationLib extends CI_Migration
}
else
{
$this->printError(
$this->eprintflib->printError(
sprintf(
"Granting permissions %s on sequence %s.%s to user %s",
is_null($stringPermission) ? $permissions : $stringPermission,
@@ -538,7 +437,7 @@ class MigrationLib extends CI_Migration
);
}
}
/**
* Executes the given query
*/
@@ -547,21 +446,21 @@ class MigrationLib extends CI_Migration
if (! @$this->db->simple_query($query))
{
$error = $this->db->error();
if (is_array($error) && isset($error["message"]))
{
$this->printError($error["message"]);
$this->eprintflib->printError($error["message"]);
}
else
{
$this->printError("Error while executing a query");
$this->eprintflib->printError("Error while executing a query");
}
}
$this->printInfo(
$this->eprintflib->printInfo(
"Query correctly executed: ".
substr(preg_replace("/\s+/", " ", trim($query)), 0, MigrationLib::PRINT_QUERY_LEN).
(strlen($query) > MigrationLib::PRINT_QUERY_LEN ? "..." : "")
substr(preg_replace("/\s+/", " ", trim($query)), 0, EPrintfLib::PRINT_QUERY_LEN).
(strlen($query) > EPrintfLib::PRINT_QUERY_LEN ? "..." : "")
);
}
}
@@ -0,0 +1 @@
Executable → Regular
View File
Executable → Regular
View File
@@ -0,0 +1 @@
Executable → Regular
View File
View File
@@ -0,0 +1,56 @@
<?php
class Extensions_model extends DB_Model
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dbTable = 'system.tbl_extensions';
$this->pk = 'extension_id';
}
/**
* getDependencies
*/
public function getDependencies($dependencies)
{
if (isError($ent = $this->isEntitled($this->dbTable, PermissionLib::SELECT_RIGHT, FHC_NORIGHT, FHC_MODEL_ERROR))) return $ent;
return $this->execQuery(
'SELECT *
FROM '.$this->dbTable.'
WHERE enabled = TRUE
AND name IN ?',
array('name' => $dependencies)
);
}
/**
*
*/
public function getInstalledExtensions()
{
$query = 'SELECT extension_id, e1.name, e1.version, description, license, url, core_version, dependencies, enabled
FROM system.tbl_extensions e1
INNER JOIN (
SELECT name, MAX(version) AS version
FROM system.tbl_extensions
GROUP BY name) e2
ON (e1.name = e2.name AND e1.version = e2.version)';
return $this->execQuery($query);
}
/**
*
*/
public function executeQuery($sql)
{
if (isError($ent = $this->isEntitled($this->dbTable, PermissionLib::SELECT_RIGHT, FHC_NORIGHT, FHC_MODEL_ERROR))) return $ent;
return $this->execQuery($sql);
}
}
View File
Vendored Executable → Regular
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
@@ -0,0 +1 @@
Executable → Regular
View File
@@ -0,0 +1,168 @@
<?php $this->load->view('core/templates/header', array('title' => 'Extensions manager', 'jqueryV1' => true, 'tablesort' => true)); ?>
<script type="text/javascript">
$(document).ready(function() {
$(".tablesorter").each(function(i, v) {
$("#" + v.id).tablesorter({
widgets: ["zebra"],
sortList: [[0, 0]],
headers: {7: {sorter: false}}
});
});
$(".chkbox").change(function() {
var chkId = $(this).context.name;
var checked = $(this).prop("checked");
$.ajax({
url: "<?php echo current_url(); ?>/toggleExtension",
dataType: "json",
type: "POST",
data: {
extension_id: chkId,
enabled: checked
},
error: function(jqXHR, textStatus, errorThrown) {
alert("Error while saving data");
},
success: function(response, textStatus, jqXHR) {
if (response != true)
{
alert("Error while saving data");
}
},
complete: function() {
window.location.reload();
}
});
});
$(".lnkrm").click(function() {
var lnkId = $(this).context.name;
if (window.confirm('Are you really shure???') == true)
{
$.ajax({
url: "<?php echo current_url(); ?>/delExtension",
dataType: "json",
type: "POST",
data: {
extension_id: lnkId
},
error: function(jqXHR, textStatus, errorThrown) {
alert("Error while saving data");
},
success: function(response, textStatus, jqXHR) {
if (response != true)
{
alert("Error while saving data");
}
},
complete: function() {
window.location.reload();
}
});
}
});
});
</script>
<body>
<?php
if (!hasData($extensions))
{
echo 'No extension installed!<br>';
}
elseif (isError($extensions))
{
echo 'An error occurred while retriving extenions list.';
}
elseif (hasData($extensions))
{
?>
<div>
List of installed extensions
</div>
<br>
<table class="tablesorter" id="t0">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Version</th>
<th>Licence</th>
<th>URL</th>
<th>Minimum required Core version</th>
<th>Dependes on (extensions)</th>
<th>Enabled</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<?php
$tableRow = '
<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>
<input type="checkbox" class="chkbox" name="%s" %s>
</td>
<td>
<a href="#" name="%s" class="lnkrm" >Remove</a>
</td>
</tr>';
foreach ($extensions->retval as $key => $extension)
{
echo sprintf(
$tableRow,
$extension->name,
$extension->description,
$extension->version,
$extension->license,
$extension->url,
$extension->core_version,
count($extension->dependencies) == 0 ? 'None' : json_encode($extension->dependencies),
$extension->extension_id,
$extension->enabled === true ? 'checked' : '',
$extension->extension_id
);
}
?>
</tbody>
</table>
<?php
}
?>
<br>
<?php echo form_open_multipart(current_url().'/uploadExtension'); ?>
<input type="file" name="extension" />
<input type="submit" value="Install/Update extension" />
</form>
</body>
<?php $this->load->view('core/templates/footer'); ?>
View File
View File
View File
View File
@@ -0,0 +1 @@
View File
View File
View File
View File
Executable → Regular
View File
View File
View File
View File
View File
Executable → Regular
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
Executable → Regular
View File
View File
View File
View File
View File
View File
View File
View File

Some files were not shown because too many files have changed in this diff Show More