Exporter management + can list modules + enable/disable modules according to dependencies

This commit is contained in:
xdrm-brackets 2016-10-19 10:16:21 +02:00
parent f40dcd4ade
commit bfe071685e
9 changed files with 444 additions and 43 deletions

218
exporter/Exporter.php Normal file
View File

@ -0,0 +1,218 @@
<?php if( !defined('__ROOT__') ) define('__ROOT__', dirname(dirname(__FILE__)) );
class Exporter{
private $modules; // will contain modules (config)
public static function config_path(){ return __ROOT__.'/exporter/modules.json'; }
/* CONSTRUCTOR -> LOADS CONFIG
*
*/
public function __construct(){
$this->modules = json_decode( file_get_contents(self::config_path()), true);
}
/* RETURNS AVAILABLE MODULE LIST
*
* @return modules<Array> Set containing modules and their versions
*
*/
public function available(){
$modules = [];
foreach($this->modules['available'] as $module=>$versions){
$modules[$module] = [];
foreach($versions as $version=>$dependencies)
$modules[$module][] = $version;
}
return $modules;
}
/* ENABLES A MODULE'S VERSION
*
* @pModule<String> Module's name
* @pVersion<String> Module's version
* @pDep<Boolean> TRUE if dependency
*
* @return err_msg<String> Error message | TRUE (if all is ok)
*
*/
public function enable($pModule=null, $pVersion=null, $pDep=false){
/* [1] Module management
=========================================================*/
/* (1) If @module not given, exit */
if( is_null($pModule) )
return "Missing @moduleName.\n";
/* (2) Checking module existence */
if( !isset($this->modules['available'][$pModule]) )
return "Module `$pModule` unknown.\n";
/* (3) Set module name & content */
$mname = $pModule;
$module = $this->modules['available'][$mname];
/* [2] Version management
=========================================================*/
/* (1) Set default version name & content */
$vname = array_slice(array_keys($module), -1)[0];
$version = $module[$vname];
/* (2) If wrong version given, set to default */
if( is_null($pVersion) || !isset($module[$pVersion]) )
echo "chosing latest $vname version.\n";
/* (2) Else, we get given @version */
else
$version = $module[( $vname = $pVersion )];
/* [3] Enables module & version
=========================================================*/
/* (1) If module disabled -> enables it */
if( !isset($this->modules['enabled'][$mname]) )
$this->modules['enabled'][$mname] = '0';
/* (2) If not dependency or version lower -> Set version */
if( !$pDep || $this->lower($module, $this->modules['enabled'][$mname], $vname) ){
if( $pDep ) echo "- $mname-$vname ($vname+ required)\n";
$this->modules['enabled'][$mname] = $vname;
} else if( $pDep ) echo "- $mname-".$this->modules['enabled'][$mname]." ($vname+ required)\n";
/* [4] Loading dependencies
=========================================================*/
/* (1) Loading each dependency */
if( count($version) > 0 ){
echo "dependencies:\n";
foreach($version as $depMod=>$depVer)
$enabled = $this->enable($depMod, $depVer, true);
}
/* [5] Storing data
=========================================================*/
$this->store();
return true;
}
/* DISABLES A MODULE'S VERSION
*
* @pModule<String> Module's name
*
* @return err_msg<String> Error message || TRUE if success
*
*/
public function disable($pModule=null){
/* [1] Module management (existence)
=========================================================*/
/* (1) If @module not given, exit */
if( is_null($pModule) )
return "Missing @moduleName.\n";
/* (2) Checking if module is enabled */
$enabled_modules = array_keys($this->modules['enabled']);
if( !in_array($pModule, $enabled_modules) )
return "Module `$pModule` not enabled.\n";
/* (3) Set module name & content */
$mname = $pModule;
$module = $this->modules['enabled'][$mname];
/* [2] Dependency verification (not needed)
=========================================================*/
$dependency = false; // if it's a dependency of another enabled module
$callers = []; // list of enabled modules that needs current one
/* (1) For each enabled module (excepted itself) */
foreach($enabled_modules as $module){
// except current module
if( $module == $mname ) continue;
/* (2) For each version of its module (and its dependencies) */
foreach($this->modules['available'][$module] as $version=>$dependencies){
// if not the current enabled module's version
if( $version != $this->modules['enabled'][$module] )
continue;
/* (3) If current module in dependencies -> can't disable */
isset($dependencies[$mname]) && ($dependency = true) && ($callers[] = "`$module`");
}
}
/* (4) If a dependency, explain */
if( $dependency )
return "Cannot disable module $mname because ".implode(',',$callers)." needs it.\n";
/* [3] Disabling module
=========================================================*/
/* (1) Disabling module */
unset($this->modules['enabled'][$mname]);
/* (2) Storing changes */
$this->store();
/* (3) Return success */
return true;
}
/* CHECKS IF @pFirst IS LOWER THAN @pSecond VERSION
*
* @pModule<Array> Module's content
* @pFirst<String> First version
* @pSecond<String> Second version
*
* @return lower<Boolean> Returns if @pFirst is lower
*
* Note: Supposing that @pFirst and @pSecond are keys of @pModule (no check)
*
*/
public function lower($pModule, $pFirst, $pSecond){
/* (1) Get @pModule keys */
$keys = array_keys($pModule);
/* (1) Get @pFirst index */
$pf_index = array_search($pFirst, $keys);
/* (2) Get @pSecond index */
$ps_index = array_search($pSecond, $keys);
return $pf_index < $ps_index;
}
/* STORES DATA
*
*/
public function store(){
file_put_contents(self::config_path(), json_encode($this->modules, JSON_PRETTY_PRINT));
}
}
?>

79
exporter/main.php Normal file
View File

@ -0,0 +1,79 @@
<?php define('__ROOT__', dirname(dirname(__FILE__)) );
require_once 'Exporter.php';
/* [1] Initialisation
=========================================================*/
/* (1) Get arguments (excepted file) */
$arguments = array_slice($argv, 1);
$arglen = $argc - 1;
// si aucun argument
if( count($arguments) === 0 ){
echo "Missing arguments.\n";
return;
}
/* (2) Load module's config */
$exporter = new Exporter();
/* [2] Commands
=========================================================*/
switch($arguments[0]){
/* (1) Modules listing
---------------------------------------------------------*/
case 'modules': {
echo "available modules:\n";
$modules = $exporter->available();
foreach($modules as $module=>$versions){
foreach($versions as $version)
echo " - $module-$version\n";
echo "\n";
}
} break;
/* (2) Enables a module and its version
---------------------------------------------------------*/
case 'enable': {
if( $arglen < 2 || !preg_match("/^(.+)-([0-9\.]+)$/i", $arguments[1], $matches) ){
echo "You must specify @module-@version.\n";
return;
}
$err = $exporter->enable($matches[1], $matches[2]);
/* (1) Managing state */
if( $err === true ) echo "success.\n";
else echo $err;
} break;
/* (3) Disabled a module
---------------------------------------------------------*/
case 'disable': {
if( $arglen < 2 ){
echo "You must specify @module.\n";
return;
}
$err = $exporter->disable($arguments[1]);
/* (1) Managing state */
if( $err === true ) echo "success.\n";
else echo $err;
} break;
}
?>

View File

@ -1,44 +1,35 @@
{
"available": {
"error": {
"versions": [1]
"1": [],
"1.2": [],
"1.5": []
},
"api": {
"versions": [1],
"dependencies": [
["error", 1]
]
"0.8": [],
"1": {
"error": "1.2"
}
},
"orm": {
"versions": [0.8],
"dependencies": [
["database", 1]
]
"0.8": {
"database": "1"
}
},
"database": {
"versions": [1],
"dependencies": [
["error", 1]
]
"1": {
"error": "1"
}
},
"lightdb": {
"versions": [1]
"1": []
},
"router": {
"versions": [1]
"1": []
}
},
"enabled": {
"api": "1",
"error": "1.2"
}
}

3
src/files/.htaccess Normal file
View File

@ -0,0 +1,3 @@
RewriteEngine on
RewriteRule ^(.*)$ public_html/$1 [QSA,L]

46
src/files/autoloader.php Normal file
View File

@ -0,0 +1,46 @@
<?php
/* [1] On definit les chemins absolus si c'est pas deja fait
=========================================================*/
if( !defined('__ROOT__') ) define('__ROOT__', dirname(__FILE__) );
if( !defined('__CONFIG__') ) define('__CONFIG__', __ROOT__.'/config' );
if( !defined('__BUILD__') ) define('__BUILD__', __ROOT__.'/build' );
if( !defined('__PUBLIC__') ) define('__PUBLIC__', __ROOT__.'/public_html' );
/* ACTIVE LE DEBUGGAGE (WARNING + EXCEPTION)
*
*/
function debug(){
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);
}
/* AUTOLOADER
*
* @className<String> Nom de la classe appelee
*
*/
function autoloader($className){
$path = '';
/* [1] On utilise le namespace pour localiser
===============================================*/
// On remplace les '\' par des '/'
$path = str_replace('\\', '/', $className) . '.php';
$path = __BUILD__.'/'.$path;
// Si le fichier existe
if( file_exists($path) )
require_once $path; // on inclue le fichier
}
// On definit l'autoloader comme autoloader (obvious)
spl_autoload_register('autoloader', false, true);
?>

View File

@ -0,0 +1,2 @@
Order deny,allow
Deny from all

View File

@ -0,0 +1,2 @@
Order deny,allow
Deny from all

View File

@ -0,0 +1,4 @@
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]

View File

@ -0,0 +1,56 @@
<?php define('__ROOT__', dirname(dirname(__FILE__)) );
require_once __ROOT__.'/autoloader.php';
use \router\core\Router;
use \api\core\ModuleRequest;
use \api\core\ModuleResponse;
/* [0] On initialise le routeur
===================================================*/
$R = new Router( $_GET['url'] );
/* [1] On cree les regles de routage
===================================================*/
// Racine -> page d'accueil
$R->get('/?', function(){ header('Location: /homepage/'); });
/* [2] On recupere la liste des pages du site
=========================================================*/
// inclusion de la page
$R->get('([a-z+])/?', function($pagename){ include __PUBLIC__."/$pagename.php"; });
// http://host/api/module/method -> ModuleRequest
$R->post('api(?:/(.*))?', function($url){
$request = ModuleRequest::fromPost($url, $_POST);
$answer = $request->dispatch();
// Si c'est une réponse
if( $answer instanceof ModuleResponse )
echo $answer->serialize();
});
// N'importe -> page d'accueil
$R->get('.+', function(){ header('Location: /homepage/'); });
$R->post('.+', function(){ header('Location: /homepage/'); });
/* [3] On lance le routeur
===================================================*/
$R->run();
?>