xdrm-framework/exporter/Exporter.php

286 lines
7.4 KiB
PHP

<?php if( !defined('__ROOT__') ) define('__ROOT__', dirname(dirname(__FILE__)) );
require_once 'Builder.php';
class Exporter{
private $packages; // will contain packages (config)
public static function config_path(){ return __ROOT__.'/exporter/packages.json'; }
/* CONSTRUCTOR -> LOADS CONFIG
*
*/
public function __construct(){
$this->packages = json_decode( file_get_contents(self::config_path()), true);
}
/* REMOVES ENABLED MODULES
*
*/
public function init(){
$this->packages['installed'] = [];
$this->store();
return true;
}
/* RETURNS AVAILABLE MODULE LIST
*
* @return packages<Array> Set containing packages and their versions
*
*/
public function available(){
$packages = [];
foreach($this->packages['available'] as $package=>$versions){
$packages[$package] = [];
foreach($versions as $version=>$dependencies)
// if version of package enabled
if( isset($this->packages['installed'][$package]) && $version == $this->packages['installed'][$package] )
$packages[$package][] = [ 'version' => $version, 'enabled' => true ];
else
$packages[$package][] = [ 'version' => $version, 'enabled' => false ];
}
return $packages;
}
/* ENABLES A MODULE'S VERSION
*
* @pPackage<String> Package's name
* @pVersion<String> Package's version
* @pDep<Boolean> dependency level
*
* @return err_msg<String> Error message | TRUE (if all is ok)
*
*/
public function install($pPackage=null, $pVersion=null, $pDep=0){
/* [1] Package management
=========================================================*/
/* (1) If @package not given, exit */
if( is_null($pPackage) )
return "Missing @packageName.\n";
/* (2) Checking package existence */
if( !isset($this->packages['available'][$pPackage]) )
return "Package `$pPackage` unknown.\n";
/* (3) Set package name & content */
$mname = $pPackage;
$package = $this->packages['available'][$mname];
/* [2] Version management
=========================================================*/
/* (1) Set default latest version name & content */
$vname = array_slice( array_keys($package), -1 )[0];
$dependencies = $package[$vname];
$flag = '#latest';
/* (2) Existing version set it */
if( !is_null($pVersion) && isset($package[$pVersion]) ){
$dependencies = $package[( $vname = $pVersion )];
$flag = '';
}
/* [3] Enables package & version
=========================================================*/
/* (1) If package disabled -> enables it */
if( !isset($this->packages['installed'][$mname]) )
$this->packages['installed'][$mname] = '0';
/* (2) Checks cross version dependency -> if another installed package needs another version */
foreach($this->packages['installed'] as $xPackage=>$xVersion){
// {2.1} Loads each installed package's dependencies //
$xDependencies = $this->getDependencies($xPackage,$xVersion);
// if not found -> next
if( $xDependencies === false )
continue;
// {2.2} if package can't have version of current package //
if( isset($xDependencies[$mname]) && !in_array($vname, $xDependencies[$mname]) )
return str_repeat(" ", $pDep)."$xPackage:$xVersion doesn't support $mname:$vname\n\n** aborted **\n";
}
/* (5) If no conflict -> set version */
echo str_repeat(" ", $pDep)."[$mname:$vname] $flag\n";
// in any case -> store new package's version
$this->packages['installed'][$mname] = $vname;
/* [4] Loading dependencies
=========================================================*/
/* (1) Loading each dependency */
if( count($dependencies) > 0 ){
foreach($dependencies as $depMod=>$depVersions){
// Only load last version
foreach($depVersions as $version)
$installed = $this->install($depMod, $version, $pDep+1);
// error propagation
if( $installed !== true )
return $installed;
}
}
/* [5] Storing data
=========================================================*/
$this->store();
return true;
}
/* DISABLES A MODULE'S VERSION
*
* @pPackage<String> Package's name
*
* @return err_msg<String> Error message || TRUE if success
*
*/
public function remove($pPackage=null){
/* [1] Package management (existence)
=========================================================*/
/* (1) If @package not given, exit */
if( is_null($pPackage) )
return "Missing @packageName.\n";
/* (2) Checking if package is enabled */
$enabled_packages = array_keys($this->packages['installed']);
if( !in_array($pPackage, $enabled_packages) )
return "Package `$pPackage` not enabled.\n";
/* (3) Set package name & content */
$mname = $pPackage;
$package = $this->packages['installed'][$mname];
/* [2] Dependency verification (not needed)
=========================================================*/
$dependency = false; // if it's a dependency of another enabled package
$callers = []; // list of enabled packages that needs current one
/* (1) For each enabled package (excepted itself) */
foreach($enabled_packages as $package){
// except current package
if( $package == $mname ) continue;
/* (2) For each version of its package (and its dependencies) */
foreach($this->packages['available'][$package] as $version=>$dependencies){
// if not the current enabled package's version
if( $version != $this->packages['installed'][$package] )
continue;
/* (3) If current package in dependencies -> can't disable */
isset($dependencies[$mname]) && ($dependency = true) && ($callers[] = "`$package`");
}
}
/* (4) If a dependency, explain */
if( $dependency )
return "Cannot disable package $mname because ".implode(',',$callers)." needs it.\n";
/* [3] Disabling package
=========================================================*/
/* (1) Disabling package */
unset($this->packages['installed'][$mname]);
/* (2) Storing changes */
$this->store();
/* (3) Return success */
return true;
}
/* BUILDS A PROJECT
*
* @pPath<String> Path to project root
*
*/
public function build($pPath){
$builder = new Builder($pPath, $this->packages['installed']);
$builder->build();
}
/* RETURNS THE LIST OF THE DEPENDENCIES OF A MODULE
*
* @package<String> Package's label
* @version<String> Package's version
*
* @return dependencies<Array> List of dependencies
* FALSE if error
*
*/
private function getDependencies($package=null, $version=null){
/* [1] Search for package
=========================================================*/
/* (1) Checks package */
if( !isset($this->packages['available'][$package]) )
return false;
/* (2) Checks version */
if( !isset($this->packages['available'][$package][$version]) )
return false;
/* [2] Returns dependencies
=========================================================*/
/* (1) If not an array */
if( !is_array($this->packages['available'][$package][$version]) )
return [];
/* (2) If all right */
return $this->packages['available'][$package][$version];
}
/* STORES DATA
*
*/
public function store(){
file_put_contents(self::config_path(), json_encode($this->packages, JSON_PRETTY_PRINT));
}
}
?>