LOADS CONFIG * */ public function __construct(){ $this->modules = json_decode( file_get_contents(self::config_path()), true); } /* REMOVES ENABLED MODULES * */ public function init(){ $this->modules['enabled'] = []; $this->store(); return true; } /* RETURNS AVAILABLE MODULE LIST * * @return modules Set containing modules and their versions * */ public function available(){ $modules = []; foreach($this->modules['available'] as $module=>$versions){ $modules[$module] = []; foreach($versions as $version=>$dependencies) // if version of module enabled if( isset($this->modules['enabled'][$module]) && $version == $this->modules['enabled'][$module] ) $modules[$module][] = [ 'version' => $version, 'enabled' => true ]; else $modules[$module][] = [ 'version' => $version, 'enabled' => false ]; } return $modules; } /* ENABLES A MODULE'S VERSION * * @pModule Module's name * @pVersion Module's version * @pDep TRUE if dependency * * @return err_msg 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 version:\n-----------------------\n [x] $mname:$vname (can throw errors)\n\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'; /* (3) Checks cross version dependency -> trying to enable lower-than-required version of a module*/ $crossDep = false; // For each available module foreach($this->modules['enabled'] as $xModule=>$xVersion){ // Loads each module's dependencies if( !isset($this->modules['available'][$xModule][$xVersion]) ) continue; $xDependencies = $this->modules['available'][$xModule][$xVersion]; // if module needs a higher version of current module if( isset($xDependencies[$mname]) && $this->lower($this->modules['available'][$mname], $vname, $xDependencies[$mname]) ){ $crossDep = true; break; } } /* (4) If trying to load lower than required version -> error */ if( $crossDep ){ // Update module's version if( $this->lower($this->modules['available'][$mname], $this->modules['enabled'][$mname], $xDependencies[$mname]) ) $this->modules['enabled'][$mname] = $xDependencies[$mname]; $this->store(); return "module `$xModule:$xVersion` needs `$mname:".$xDependencies[$mname]."`\n\naborted.\n"; } /* (5) If not a dependency or higher version -> set/update version */ if( !$pDep || $this->lower($module, $this->modules['enabled'][$mname], $vname) ){ // if a dependency, set new params if( $pDep ) echo " [x] $mname:$vname (version $vname+ required)\n"; // else, store new module $this->modules['enabled'][$mname] = $vname; }else if( $pDep ) echo " [x] $mname:".$this->modules['enabled'][$mname]." (version $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 Module's name * * @return err_msg 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; } /* BUILDS A PROJECT * * @pPath Path to project root * */ public function build($pPath){ $builder = new Builder($pPath, $this->modules['enabled']); $builder->build(); } /* CHECKS IF @pFirst IS LOWER THAN @pSecond VERSION * * @pModule Module's content * @pFirst First version * @pSecond Second version * * @return lower 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); if( $pf_index === false ) return true; return $pf_index < $ps_index; } /* STORES DATA * */ public function store(){ file_put_contents(self::config_path(), json_encode($this->modules, JSON_PRETTY_PRINT)); } } ?>