From d65860a78c902181100e8feb0f22f63f4a8d8b5c Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Mon, 5 Dec 2016 19:54:19 +0100 Subject: [PATCH] conflicts management + README.md update --- README.md | 100 +++++++++------- exporter/Builder.php | 24 ++-- exporter/Exporter.php | 252 +++++++++++++++++++---------------------- exporter/main.php | 32 +++--- exporter/modules.json | 45 -------- exporter/packages.json | 58 ++++++++++ xdrm-framework => xfw | 0 7 files changed, 260 insertions(+), 251 deletions(-) delete mode 100644 exporter/modules.json create mode 100644 exporter/packages.json rename xdrm-framework => xfw (100%) diff --git a/README.md b/README.md index cbc0c60..c2d4572 100644 --- a/README.md +++ b/README.md @@ -6,36 +6,36 @@ xdrm-framework is a tool that wraps my framework and all it's component's versio #### 1. Build a project To use the xdrm-framework's project builder, just open a linux terminal and type : -1. `xdrm-framework modules` - to display the available modules -2. `xdrm-framework install {moduleName} 1.2` - to enable a module and its version (1.2 here) -3. `xdrm-framework remove {moduleName}` - to disable a module -4. `xdrm-framework build {projectRoot}` - will create your project in the folder `{projectRoot}` -5. `xdrm-framework init` - to remove all enabled modules +1. `./xfw packages` - to display the available modules +2. `./xfw install {packageName}:1.2` - to install a package and its version (1.2 here) +3. `./xfw remove {packageName}` - to disable a module +4. `./xfw build {projectRoot}` - will create your project in the folder `{projectRoot}` +5. `./xfw init` - to remove all enabled modules #### 2. Project's file structure -xdrm-framework is based on `all is in config` so you will have this structure : -- folder `build` which contains framework's modules (core + data). -- folder `public_html` which contains visible content (html, css, js). -- folder `config` which contains the modules' config files (mainly json). -- file `autoloader.php` which will auto-load the components. +xdrm-framework is based on `all in config` so you will have this structure : +- folder `/build` which contains framework's modules (core + data). +- folder `/public_html` which contains visible content (html, css, js). +- folder `/config` which contains the modules' config files (mainly json). +- file `/autoloader.php` which will auto-load the components. **Note:** In every php file you want to use framework's classes, you have to begin your file by : ```php 10]); - $response = $request->dispatch(); - - if( $response->error->get() === Err::Success ) - echo "All is going right!\n"; + /* [1] load the autoloader with correct path */ + require_once '../autoloader.php'; + + /* [2] then you can load your classes */ + use api\core\Request; // ex1: api request manager + use error\core\Error; // ex2: error manager + use error\core\Err; // ex3: error codes + + /* [3] and use them as long as you want without namespace */ + $request = new Request('module/method', ['id_user' => 10]); + $response = $request->dispatch(); + + if( $response->error->get() === Err::Success ) + echo "All is going right!\n"; ``` **Note:** Some global constants are created into the autoloader so they are accessible from any file which loads the autoloader: @@ -47,37 +47,53 @@ xdrm-framework is based on `all is in config` so you will have this structure : ### 3. Modules -#### [3.1] API - self-managed API +#### 3.1 API - self-managed API ###### How to use In order to use the API, you must begin by writting your _"methods"_ in the configuration file located at `/config/modules.json`. In order to be understood, lets call `module` a group of methods, and `method` a function which outputs data from input parameters. - **Configuration format** ```json { - "{module_name}": { - - "{http_method}::{method_name}": { - "description": "{method_description}", - "permissions": ["{perm}"], - "options": { "download": {is_download} }, - "parameters: { - "{name_param}": { "description": "{desc_param}", "type": "{type_param}", "optional": {is_optional} } - }, - "output": { - "{name_output}": { "description": "{desc_output}", "type": "{type_output}" } - } - } - - - } + "{module_name}": { + + "{http_method}::{method_name}": { + "description": "{method_description}", + "permissions": ["{method_perm}"], + "options": { "download": "{is_downloadable}" }, + "parameters": { + "{name_param}": { "description": "{desc_param}", "type": "{type_param}", "optional": "{is_optional}" } + }, + "output": { + "{name_output}": { "description": "{desc_output}", "type": "{type_output}" } + } + } + + } } ``` +|variable|description|exemple| +|-------|-------|------| +|`{module_name}`|alphanumeric module name|"publications"| +|`{http_method}`|uppercase HTTP method|"POST"| +|`{method_name}`|alphanumeric method name|"article"| +|`{method_description}`|textual description|"Returns a specific article"| +|`{method_perm}`|permission array|`["poster", "admin", "user"]`| +|`{is_downloadable}`|If you want this method to return a file|`true`, `false`| +|`{name_param}`|Your param's name|"id_article"| +|`{desc_param}`|Your param's description|"Wanted article's id"| +|`{type_param}`|Your param's type (cf. Checker)|"Wanted article's type"| +|`{is_optional}`|Whether to make your param _required_|`true`, `false`| +|`{name_output}`|Your output's name|"article"| +|`{desc_output}`|Your output's description|"Article content"| + +**Implementation** +TODO + ###### Classes (advanced) The API is managed through 5 classes : diff --git a/exporter/Builder.php b/exporter/Builder.php index 849d4cb..358a919 100644 --- a/exporter/Builder.php +++ b/exporter/Builder.php @@ -5,7 +5,7 @@ private static function src(){ return __ROOT__.'/src'; } - private $modules = null; + private $packages = null; private $root = null; @@ -13,17 +13,17 @@ /* BUILDS A BUILDER WITH SPECIFIC LOCATION AND CONFIG * * @pRoot Path to project root - * @pModules Modules to load + * @pPackages Packages to load * */ - public function __construct($pRoot, $pModules){ + public function __construct($pRoot, $pPackages){ /* [1] Stores the path =========================================================*/ $this->root = $pRoot; - /* [2] Stores the modules + /* [2] Stores the packages =========================================================*/ - $this->modules = $pModules; + $this->packages = $pPackages; } @@ -37,16 +37,16 @@ - /* [2] Browse each module to load + /* [2] Browse each package to load =========================================================*/ - foreach($this->modules as $module=>$version){ - $path = "/$module/$version"; + foreach($this->packages as $package=>$version){ + $path = "/$package/$version"; - /* (1) Copy module folder if it exists */ - if( file_exists(__ROOT__."/src/modules$path/") && is_dir(__ROOT__."/src/modules$path/") && count(scandir(__ROOT__."/src/modules$path/")) > 2 ) - shell_exec("cp -r ".__ROOT__."/src/modules$path ".$this->root."/build/$module"); + /* (1) Copy package folder if it exists */ + if( file_exists(__ROOT__."/src/packages$path/") && is_dir(__ROOT__."/src/packages$path/") && count(scandir(__ROOT__."/src/packages$path/")) > 2 ) + shell_exec("cp -r ".__ROOT__."/src/packages$path ".$this->root."/build/$package"); - /* (2) Copy module config if it exists */ + /* (2) Copy package config if it exists */ if( file_exists(__ROOT__."/src/config$path/") && is_dir(__ROOT__."/src/config$path/") && count(scandir(__ROOT__."/src/config$path/")) > 2 ) shell_exec("cp -r ".__ROOT__."/src/config$path/* ".$this->root."/config/"); diff --git a/exporter/Exporter.php b/exporter/Exporter.php index 482759f..466d1bc 100644 --- a/exporter/Exporter.php +++ b/exporter/Exporter.php @@ -5,9 +5,9 @@ class Exporter{ - private $modules; // will contain modules (config) + private $packages; // will contain packages (config) - public static function config_path(){ return __ROOT__.'/exporter/modules.json'; } + public static function config_path(){ return __ROOT__.'/exporter/packages.json'; } @@ -17,7 +17,7 @@ */ public function __construct(){ - $this->modules = json_decode( file_get_contents(self::config_path()), true); + $this->packages = json_decode( file_get_contents(self::config_path()), true); } @@ -29,7 +29,7 @@ * */ public function init(){ - $this->modules['enabled'] = []; + $this->packages['installed'] = []; $this->store(); return true; @@ -37,135 +37,113 @@ /* RETURNS AVAILABLE MODULE LIST * - * @return modules Set containing modules and their versions + * @return packages Set containing packages and their versions * */ public function available(){ - $modules = []; + $packages = []; - foreach($this->modules['available'] as $module=>$versions){ - $modules[$module] = []; + foreach($this->packages['available'] as $package=>$versions){ + $packages[$package] = []; 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 ]; + // if version of package enabled + if( isset($this->packages['installed'][$package]) && $version == $this->packages['installed'][$package] ) + $packages[$package][] = [ 'version' => $version, 'enabled' => true ]; else - $modules[$module][] = [ 'version' => $version, 'enabled' => false ]; + $packages[$package][] = [ 'version' => $version, 'enabled' => false ]; } - return $modules; + return $packages; } /* ENABLES A MODULE'S VERSION * - * @pModule Module's name - * @pVersion Module's version + * @pPackage Package's name + * @pVersion Package's version * @pDep dependency level * * @return err_msg Error message | TRUE (if all is ok) * */ - public function enable($pModule=null, $pVersion=null, $pDep=0){ + public function install($pPackage=null, $pVersion=null, $pDep=0){ - /* [1] Module management + /* [1] Package management =========================================================*/ - /* (1) If @module not given, exit */ - if( is_null($pModule) ) - return "Missing @moduleName.\n"; + /* (1) If @package not given, exit */ + if( is_null($pPackage) ) + return "Missing @packageName.\n"; - /* (2) Checking module existence */ - if( !isset($this->modules['available'][$pModule]) ) - return "Module `$pModule` unknown.\n"; + /* (2) Checking package existence */ + if( !isset($this->packages['available'][$pPackage]) ) + return "Package `$pPackage` unknown.\n"; - /* (3) Set module name & content */ - $mname = $pModule; - $module = $this->modules['available'][$mname]; + /* (3) Set package name & content */ + $mname = $pPackage; + $package = $this->packages['available'][$mname]; /* [2] Version management =========================================================*/ - /* (1) Set default version name & content */ - $vname = array_slice( array_keys($module), -1 )[0]; - $version = $module[$vname]; + /* (1) Set default latest version name & content */ + $vname = array_slice( array_keys($package), -1 )[0]; + $dependencies = $package[$vname]; + $flag = '#latest'; - /* (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 )]; + /* (2) Existing version set it */ + if( !is_null($pVersion) && isset($package[$pVersion]) ){ + $dependencies = $package[( $vname = $pVersion )]; + $flag = ''; + } - /* [3] Enables module & version + + /* [3] Enables package & version =========================================================*/ - /* (1) If module disabled -> enables it */ - if( !isset($this->modules['enabled'][$mname]) ) - $this->modules['enabled'][$mname] = '0'; + /* (1) If package disabled -> enables it */ + if( !isset($this->packages['installed'][$mname]) ) + $this->packages['installed'][$mname] = '0'; - /* (3) Checks cross version dependency -> trying to enable lower-than-required version of a module*/ - $crossDep = false; + /* (2) Checks cross version dependency -> if another installed package needs another version */ + foreach($this->packages['installed'] as $xPackage=>$xVersion){ - // For each available module - foreach($this->modules['enabled'] as $xModule=>$xVersion){ + // {2.1} Loads each installed package's dependencies // + $xDependencies = $this->getDependencies($xPackage,$xVersion); - // Loads each module's dependencies - if( !isset($this->modules['available'][$xModule][$xVersion]) ) + // if not found -> next + if( $xDependencies === false ) 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; - } + // {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"; } - /* (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 == 0 || $this->lower($module, $this->modules['enabled'][$mname], $vname) ){ - - // if a dependency, set new params - if( $pDep > 0 ) - echo str_repeat(" ", $pDep)."[x] $mname:$vname ($mname:$vname+ required)\n"; - else - echo str_repeat(" ", $pDep)."[x] $mname:$vname\n"; - - // in any case -> store new module's version - $this->modules['enabled'][$mname] = $vname; - - }else if( $pDep > 0 ) - echo str_repeat(" ", $pDep)."[x] $mname:".$this->modules['enabled'][$mname]." ($mname:$vname+ required)\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($version) > 0 ){ + if( count($dependencies) > 0 ){ - echo "\n".str_repeat(" ", $pDep); - echo "dependencies:\n"; + foreach($dependencies as $depMod=>$depVersions){ - foreach($version as $depMod=>$depVer) - $enabled = $this->enable($depMod, $depVer, $pDep+1); + // Only load last version + foreach($depVersions as $version) + $installed = $this->install($depMod, $version, $pDep+1); + + // error propagation + if( $installed !== true ) + return $installed; + } } @@ -179,48 +157,48 @@ /* DISABLES A MODULE'S VERSION * - * @pModule Module's name + * @pPackage Package's name * * @return err_msg Error message || TRUE if success * */ - public function disable($pModule=null){ - /* [1] Module management (existence) + public function remove($pPackage=null){ + /* [1] Package management (existence) =========================================================*/ - /* (1) If @module not given, exit */ - if( is_null($pModule) ) - return "Missing @moduleName.\n"; + /* (1) If @package not given, exit */ + if( is_null($pPackage) ) + return "Missing @packageName.\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"; + /* (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 module name & content */ - $mname = $pModule; - $module = $this->modules['enabled'][$mname]; + /* (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 module - $callers = []; // list of enabled modules that needs current one + $dependency = false; // if it's a dependency of another enabled package + $callers = []; // list of enabled packages that needs current one - /* (1) For each enabled module (excepted itself) */ - foreach($enabled_modules as $module){ + /* (1) For each enabled package (excepted itself) */ + foreach($enabled_packages as $package){ - // except current module - if( $module == $mname ) continue; + // except current package + if( $package == $mname ) continue; - /* (2) For each version of its module (and its dependencies) */ - foreach($this->modules['available'][$module] as $version=>$dependencies){ + /* (2) For each version of its package (and its dependencies) */ + foreach($this->packages['available'][$package] as $version=>$dependencies){ - // if not the current enabled module's version - if( $version != $this->modules['enabled'][$module] ) + // if not the current enabled package's version + if( $version != $this->packages['installed'][$package] ) continue; - /* (3) If current module in dependencies -> can't disable */ - isset($dependencies[$mname]) && ($dependency = true) && ($callers[] = "`$module`"); + /* (3) If current package in dependencies -> can't disable */ + isset($dependencies[$mname]) && ($dependency = true) && ($callers[] = "`$package`"); } @@ -228,13 +206,13 @@ /* (4) If a dependency, explain */ if( $dependency ) - return "Cannot disable module $mname because ".implode(',',$callers)." needs it.\n"; + return "Cannot disable package $mname because ".implode(',',$callers)." needs it.\n"; - /* [3] Disabling module + /* [3] Disabling package =========================================================*/ - /* (1) Disabling module */ - unset($this->modules['enabled'][$mname]); + /* (1) Disabling package */ + unset($this->packages['installed'][$mname]); /* (2) Storing changes */ $this->store(); @@ -254,7 +232,7 @@ * */ public function build($pPath){ - $builder = new Builder($pPath, $this->modules['enabled']); + $builder = new Builder($pPath, $this->packages['installed']); $builder->build(); } @@ -263,41 +241,43 @@ - - - /* CHECKS IF @pFirst IS LOWER THAN @pSecond VERSION + /* RETURNS THE LIST OF THE DEPENDENCIES OF A MODULE * - * @pModule Module's content - * @pFirst First version - * @pSecond Second version + * @package Package's label + * @version Package's version * - * @return lower Returns if @pFirst is lower - * - * Note: Supposing that @pFirst and @pSecond are keys of @pModule (no check) + * @return dependencies List of dependencies + * FALSE if error * */ - public function lower($pModule, $pFirst, $pSecond){ - /* (1) Get @pModule keys */ - $keys = array_keys($pModule); + private function getDependencies($package=null, $version=null){ + /* [1] Search for package + =========================================================*/ + /* (1) Checks package */ + if( !isset($this->packages['available'][$package]) ) + return false; - /* (1) Get @pFirst index */ - $pf_index = array_search($pFirst, $keys); + /* (2) Checks version */ + if( !isset($this->packages['available'][$package][$version]) ) + return false; - /* (2) Get @pSecond index */ - $ps_index = array_search($pSecond, $keys); + /* [2] Returns dependencies + =========================================================*/ + /* (1) If not an array */ + if( !is_array($this->packages['available'][$package][$version]) ) + return []; - if( $pf_index === false ) - return true; - - return $pf_index < $ps_index; + /* (2) If all right */ + return $this->packages['available'][$package][$version]; } + /* STORES DATA * */ public function store(){ - file_put_contents(self::config_path(), json_encode($this->modules, JSON_PRETTY_PRINT)); + file_put_contents(self::config_path(), json_encode($this->packages, JSON_PRETTY_PRINT)); } } diff --git a/exporter/main.php b/exporter/main.php index 8170edc..930c8fd 100644 --- a/exporter/main.php +++ b/exporter/main.php @@ -15,14 +15,14 @@ return; } - /* (2) Load module's config */ + /* (2) Load package's config */ $exporter = new Exporter(); /* [2] Commands =========================================================*/ switch($arguments[0]){ - /* (0) Reset enabled modules + /* (0) Reset enabled packages ---------------------------------------------------------*/ case 'init': { @@ -32,37 +32,37 @@ } break; - /* (1) Modules listing + /* (1) Packages listing ---------------------------------------------------------*/ - case 'modules': { + case 'packages': { - echo "available modules:\n"; - $modules = $exporter->available(); + echo "available packages:\n"; + $packages = $exporter->available(); - foreach($modules as $module=>$versions){ + foreach($packages as $package=>$versions){ foreach($versions as $version) // if enabled if( $version['enabled'] ) - echo " [x] $module (version ".$version['version'].")\n"; + echo " [*] $package:".$version['version']."\n"; else - echo " [ ] $module (version ".$version['version'].")\n"; + echo " [ ] $package:".$version['version']."\n"; echo "\n"; } } break; - /* (2) Enables a module and its version + /* (2) Enables a package and its version ---------------------------------------------------------*/ case 'install': { - if( $arglen < 2 || !preg_match("/^(.+):([0-9\.-]+)$/i", $arguments[1], $matches) ){ - echo "You must specify @module:@version.\n"; + if( $arglen < 2 || !preg_match("/^([^:]+)(:(?:[0-9\.-]+))?$/i", $arguments[1], $matches) ){ + echo "You must specify @package:@version.\n"; return; } - $err = $exporter->enable($matches[1], $matches[2]); + $err = $exporter->install($matches[1], count($matches) > 2 ? substr($matches[2], 1) : null); /* (1) Managing state */ if( $err === true ) echo "\n\n** success **\n"; @@ -70,16 +70,16 @@ } break; - /* (3) Disabled a module + /* (3) Disabled a package ---------------------------------------------------------*/ case 'remove': { if( $arglen < 2 ){ - echo "You must specify @module.\n"; + echo "You must specify @package.\n"; return; } - $err = $exporter->disable($arguments[1]); + $err = $exporter->remove($arguments[1]); /* (1) Managing state */ if( $err === true ) echo "\n\n** success **\n"; diff --git a/exporter/modules.json b/exporter/modules.json deleted file mode 100644 index 94ac98f..0000000 --- a/exporter/modules.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "available": { - "error": { - "1.0": [], - "2.0": [] - }, - "api": { - "1.0": { - "error": "1.0" - }, - "2.0": { - "error": "2.0" - } - }, - "orm": { - "0.8.1": { - "database": "1.0" - }, - "0.8.2": { - "database": "2.0" - } - }, - "database": { - "1.0": { - "error": "1.0" - }, - "2.0": { - "error": "2.0" - } - }, - "lightdb": { - "1.0": [] - }, - "router": { - "1.0": [] - } - }, - "enabled": { - "orm": "0.8.2", - "database": "2.0", - "error": "2.0", - "api": "2.0", - "router": "1.0" - } -} \ No newline at end of file diff --git a/exporter/packages.json b/exporter/packages.json new file mode 100644 index 0000000..d26f577 --- /dev/null +++ b/exporter/packages.json @@ -0,0 +1,58 @@ +{ + "available": { + "error": { + "1.0": [], + "2.0": [] + }, + "api": { + "1.0": { + "error": [ + "1.0" + ] + }, + "2.0": { + "error": [ + "2.0" + ] + } + }, + "orm": { + "0.8.1": { + "database": [ + "1.0" + ] + }, + "0.8.2": { + "database": [ + "2.0" + ] + } + }, + "database": { + "1.0": { + "error": [ + "1.0" + ] + }, + "2.0": { + "error": [ + "2.0" + ] + } + }, + "lightdb": { + "1.0": [] + }, + "router": { + "1.0": [] + } + }, + "installed": { + "api": "2.0", + "error": "2.0", + "database": "2.0", + "orm": "0.8.2", + "lightdb": "1.0", + "router": "1.0" + } +} diff --git a/xdrm-framework b/xfw similarity index 100% rename from xdrm-framework rename to xfw