From bfeee3358d9ef95e35d8e97eb788e6660a85883c Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Tue, 12 Dec 2017 21:32:20 +0100 Subject: [PATCH] Updated api:3.0 --- notice/api/3.0.md | 72 +++--- src/config/api/3.0/modules.json | 94 ++++++++ src/files/public_html/index.php | 16 +- src/packages/api/3.0/core/Config.php | 138 +++++++++++ src/packages/api/3.0/core/Documentation.php | 50 ++++ src/packages/api/3.0/core/ModuleFactory.php | 17 +- src/packages/api/3.0/core/Request.php | 248 ++++++++++---------- 7 files changed, 460 insertions(+), 175 deletions(-) create mode 100644 src/config/api/3.0/modules.json create mode 100644 src/packages/api/3.0/core/Config.php create mode 100644 src/packages/api/3.0/core/Documentation.php diff --git a/notice/api/3.0.md b/notice/api/3.0.md index 19e1052..d331916 100644 --- a/notice/api/3.0.md +++ b/notice/api/3.0.md @@ -42,45 +42,42 @@ Links -> # **I.** Overview +# **I.** Overview -> ## **1** Introduction & features +## **1** Introduction & features -The `api` package (v2.2) allows you to easily create and manage an API. It could be used for an HTTP API (REST, or other kind), or you can use it as an internal core for your system. +The `api` package (v3.0) allows you to easily create and manage an API for your applications. It can be used as an HTTP API (REST, or other kind), and you can use it as an internal core for your system. -The aim of this package is to make your life easier working with APIs or internal delegation. The only things you have to do is to implement your processes and edit the configuration, the package will do the rest. +The aim of this package is to make your life easier working with APIs and internal delegation. The only things you have to do is to implement your processes and write the configuration, the package will do the rest. -Things you have to do : +Things you **have** to do : - implement your processes (obviously) - implement your authentication system (cf. [AuthSystem](#1-permissions--authsystem)) -- edit the configuration file (cf. [configuration](#iii-configuration)) +- setup the configuration file (cf. [configuration](#iii-configuration)) Things you **don't have** to do : - input type check (cf. [Checker](#4-checker)) -- API multiple permission management -- optional or required inputs +- multiple permission management +- optional or required input +- multipart and file input +- URL input - before and after scripts -- catch both in-URL and `multipart/form-data` input +- and a lot more ... > ## **2** Basic knowledge -The API is based over a 2-level delegation structure : -1. `module` which is a set of methods -2. `method` which have input, output, permissions, and is bound to a function +The api is made of paths that binds to a *php class*, each `path` can manage multiple **HTTP METHODS** each will correspond to a *method* of the bound class. -So each of your functionalities must have a `method` name and be inside a `module`. +So each of your functionalities must have a `method` and a corresponding a `path`. Example: * the module `article` contains methods: - * `read` with argument `article_id` (to identify the wanted article) - * `write` with arguments `title` and `body` (data to write into the new created article) - * `edit` with arguments `article_id` and `body` (to identify and replace the body) - * `delete` with argument `article_id` (to identify which article to delete) - -If you want to delete the article of id `52`, you must request `article/delete` passing `article_id`=`52`. - - + * `GET` to get article data + * `POST` to post a new article + * `PUT` to edit an existing article + * `DELETE` to delete an exisint article +*Note that each method must be a valid HTTP METHOD*. @@ -125,11 +122,11 @@ use \error\core\Err; > ### 1) create a request ```php -// creates a request for the module {module} and its method {method} with params -$request = new Request('{module}/{method}', [ +// creates a request @path with params +$request = new \api\core\Request('some/path', [ 'param1' => 10, 'param2' => 'somevalue' -]); +], 'POST'); // wanted HTTP method to emulate ``` > ### 2) catch possible errors (optional) @@ -169,20 +166,20 @@ $specific = $response->get('someOutputName'); In order to setup an automatic bound from HTTP requests to API directly, you must use a **router**. -> ### 1) Format url so it must begin with `/{module}/{method}` +> ### 1) Format url so it must begin with `/@path` ```php -// let's suppose the url is `/api/{module}/{method}` -$url = '/api/somemodule/somemethod/1/2/'; +// let's suppose the url is `/api/@path` +$url = '/api/some/path/1/2/'; $uri = substr($url, strlen('/api')); -// $uri = /somemodule/somemethod/1/2/ +// $uri = /some/path/1/2/ ``` > ### 2) give the url to the HTTP manager ```php // create request from HTTP data -$request = Request::remote($url); +$request = \api\core\Loader::remote($uri); // execute request and catch response // note that request errors will propagate through response @@ -201,33 +198,26 @@ Then can handle various kinds of URL : - request and parameters of both URL, post data, and form-data are caught ### The following examples can work : -> 1. `http://www.host.com/{module}/{method}/` +> 1. `http://www.host.com/@path/{param3}` ```json "post-data": { "param1": "{value1}", "param2": "{value2}" } ``` -> 2. `http://www.host.com/{module}/{method}/{param1}/{param2}` + +> 2. `http://www.host.com/@path/{param1}/{param2}` ```json "post-data": {} ``` -> 3. `http://www.host.com/apiOrParentUrl/` + +> 3. `http://www.host.com/@path/1,` ```json "post-data": { - "module": "{module}", - "method": "{method}", "param1": "{value1}", "param2": "{value2}" } ``` -> 4. `http://www.host.com/apiOrParentUrl/{value1}/{value2}` -```json -"post-data": { - "module": "{module}", - "method": "{method}", -} -``` diff --git a/src/config/api/3.0/modules.json b/src/config/api/3.0/modules.json new file mode 100644 index 0000000..c79936b --- /dev/null +++ b/src/config/api/3.0/modules.json @@ -0,0 +1,94 @@ +{ + + "article": { + + "POST": { + "description": "Posts a new article", + "permissions": ["journalist"], + "parameters": { + "title": { "description": "Article's title", "type": "varchar(5,100)" }, + "content": { "description": "Article's content", "type": "text" } + }, + "output": { + "created_id": { "description": "Id of the created article", "type": "id" } + } + }, + + "GET": { + "description": "Gets all or a specific article", + "permissions": ["viewer", "journalist"], + "parameters": { + "URL0": { "description": "Article id", "type": "id", "optional": true, "rename": "id_article" } + }, + "output": { + "articles": { "description": "List of selected articles", "type": "array" } + } + }, + + "VIEW": { + "description": "Gets a specific article into a json file (download)", + "permissions": ["viewer", "journalist"], + "options": { "download": true }, + "parameters": { + "URL0": { "description": "Article id", "type": "id", "rename": "id_article" } + }, + "output": { + "article": { "description": "Selected article as JSON file", "type": "text" } + } + }, + + "PUT": { + "description": "Updates a specific article", + "permissions": ["journalist"], + "parameters": { + "URL0": { "description": "Article id", "type": "id", "rename": "id_article" }, + "content": { "description": "Article's content", "type": "text" } + }, + "output": { + "article": { "description": "Returns updated article", "type": "array" } + } + }, + + "DELETE": { + "description": "Deletes a specific article", + "permissions": ["journalist"], + "parameters": { + "URL0": { "description": "Article id", "type": "id", "rename": "id_article" } + }, + "output": {} + } + + }, + + + "encapsuled": { + "url": { + "with": { + "possible": { + "methods": { + "at": { + + "each": { + "level": { + + "GET": { + "description": "GET /encapsuled/url/with/possible/methods/at/each/level", + "permissions": [], + "parameters": {} + } + + } + }, + + "POST": { + "description": "POST /encapsuled/url/with/possible/methods/at", + "permissions": [], + "parameters": {} + } + } + } + } + } + } + } +} diff --git a/src/files/public_html/index.php b/src/files/public_html/index.php index 86c88fd..f84887e 100644 --- a/src/files/public_html/index.php +++ b/src/files/public_html/index.php @@ -1,8 +1,20 @@ run(); + /* (2) Set default Driver for Repos */ + Repo::setDriver(DatabaseDriver::get()); + + /* (3) Set default AuthSystem */ + Request::setAuthSystem(new AuthSystemDefault); + + /* (4) launch router */ + Router::launch($_SERVER['REQUEST_URI']); diff --git a/src/packages/api/3.0/core/Config.php b/src/packages/api/3.0/core/Config.php new file mode 100644 index 0000000..67a1553 --- /dev/null +++ b/src/packages/api/3.0/core/Config.php @@ -0,0 +1,138 @@ + Configuration path + * + ---------------------------------------------------------*/ + private function __construct($path=null){ + + // Set default error + $this->error = new Error(Err::Success); + + + /* (1) Access file content + ---------------------------------------------------------*/ { + + /* (1) Vérification existence fichier config */ + if( !file_exists($path) ) + return $this->error->set(Err::UnreachableResource); + + /* (2) Lecture fichier config */ + $conf = @file_get_contents($path); + + /* (3) Si erreur lecture */ + if( $conf === false ) + return $this->error->set(Err::UnreachableResource); + + /* (4) Parsage json */ + $this->raw = json_decode( $conf, true ); + + /* (5) Gestion de l'erreur de parsage */ + if( $this->raw == null ) + return $this->error->set(Err::ParsingFailed, 'json'); + + } + + + /* (2) Construction de l'index des chemins + ---------------------------------------------------------*/ { + + /* (1) Initialisation */ + $this->index = []; + $ref = [ '/' => array_merge($this->raw) ]; + + + /* (2) Tant qu'il reste des @ref à traiter */ + while( count($ref) > 0 ){ + + /* (2.1) For each ref */ + foreach($ref as $ref_path=>$ref_children){ + + /* (2.2) For each children */ + foreach($ref_children as $path=>$method_or_subpath){ + + /* (2.2.1) If is an HTTP method -> add to index */ + if( in_array($path, self::$allowed_http_methods) ){ + + /* (2.2.1.1) If no index for this path -> add it */ + if( !isset($this->index[$ref_path]) ) + $this->index[$ref_path] = []; + + /* (2.2.1.2) Add the HTTP method definition */ + $this->index[$ref_path][$path] = $method_or_subpath; + + + /* (2.2.2) If a sub path -> add it to next refs to process */ + }else{ + + if( $ref_path == '/' ) + $ref["$ref_path$path"] = $method_or_subpath; + else + $ref["$ref_path/$path"] = $method_or_subpath; + + } + + } + + /* (2.3) In all cases -> remove current from ref */ + unset($ref[$ref_path]); + + } + + } + + } + + } + + + + /* (3) Static singleton 'get-or-create' + * + * @return inst Configuration singleton + * + ---------------------------------------------------------*/ + public static function get(){ + + /* (1) If @inst already exists -> return singleton */ + if( self::$inst instanceof Config ) + return self::$inst; + + /* (2) If @inst not set -> create singleton and return it */ + self::$inst = new self( self::config_path() ); + + return self::$inst; + + } + + + + + + + + + } \ No newline at end of file diff --git a/src/packages/api/3.0/core/Documentation.php b/src/packages/api/3.0/core/Documentation.php new file mode 100644 index 0000000..693fcb1 --- /dev/null +++ b/src/packages/api/3.0/core/Documentation.php @@ -0,0 +1,50 @@ + exit */ + if( !isset(Config::get()->index[$rq->get('id')['path']]) ) + return new Response(new Error(Err::WrongPathModule)); + + /* (2) Local store: configuration for this path */ + $cfg = Config::get()->index[$rq->get('id')['path']]; + + + + $response = new Response(); + $response->append('methods', $cfg); + + return $response; + } + + + + + + + + + + } \ No newline at end of file diff --git a/src/packages/api/3.0/core/ModuleFactory.php b/src/packages/api/3.0/core/ModuleFactory.php index 1c9109d..23ab7e5 100755 --- a/src/packages/api/3.0/core/ModuleFactory.php +++ b/src/packages/api/3.0/core/ModuleFactory.php @@ -27,18 +27,21 @@ /* (1) On gère les arguments */ $arguments = is_array($arguments) ? $arguments : []; - /* (2) On transforme @module en namespace */ + /* (2) Exception: URI Racine */ + if( $module == '/' ) + $module = '/root'; + + /* (3) On transforme @module en namespace */ $module_ns = str_replace('/', '\\', $module); - - /* (1) On vérifie que la classe existe */ - if( !file_exists(__BUILD__."/api/module/$module.php") ) + /* (4) On vérifie que la classe existe */ + if( !file_exists(__BUILD__."/api/module$module.php") ) return false; - /* (2) On récupère la classe */ - $class_name = "\\api\\module\\$module_ns"; + /* (5) On récupère la classe */ + $class_name = "\\api\\module$module_ns"; - /* (3) On retourne une instance */ + /* (6) On retourne une instance */ return new $class_name($arguments); } diff --git a/src/packages/api/3.0/core/Request.php b/src/packages/api/3.0/core/Request.php index 305861b..0912e1e 100755 --- a/src/packages/api/3.0/core/Request.php +++ b/src/packages/api/3.0/core/Request.php @@ -4,6 +4,7 @@ use \database\core\DatabaseDriver; use \api\core\AuthSystem; use \api\core\ModuleFactory; + use \api\core\Config; use \error\core\Error; use \error\core\Err; @@ -11,24 +12,17 @@ class Request{ // Constantes - public static function config_path(){ return __ROOT__.'/config/modules.json'; } private static $default_options = [ 'download' => false ]; private static $authsystem = null; - // liste des methodes HTTP autorisées - private static $allowed_http_methods = [ "GET", "POST", "PUT", "DELETE" ]; // Attributs prives utiles (initialisation) - private $path; // chemin de base (uri) + private $id; // chemin extrait de l'URI private $raw_params; // paramètres reçus private $params; // paramètres donnés à la fonction - private $schema; // schema configuration private $options; // options private $http_method; // methode HTTP appelante - // Contiendra la reponse a la requete - public $answer; - // Contiendra l'etat de la requete public $error; @@ -67,18 +61,15 @@ $this->error = new Error(Err::Success); /* (2) Si pas parametre manquant, on quitte */ - if( $uri == null ) + if( is_null($uri) ) return $this->error->set(Err::MissingPath); - /* (2) On met a jour la configuration + /* (2) On vérifie la configuration ---------------------------------------------------------*/ - /* (1) Build from configuration */ - $this->buildConfig(); - - /* (2) Dispatch if error */ - if( $this->error->get() != Err::Success ) - return; + /* (1) Dispatch if error */ + if( Config::get()->error->get() != Err::Success ) + return ($this->error = Config::get()->error); /* (3) Verification des types des parametres @@ -87,45 +78,54 @@ if( !is_string($uri) ) // Si le type est incorrect return $this->error->set(Err::WrongPathModule); - /* (2) Formattage @params en tableau */ + /* (2) Add slash at the beginning of URI */ + if( !preg_match('@^\/@', $uri) ) + $uri = "/$uri"; + + /* (3) Formattage @params en tableau */ $this->raw_params = (is_array($params)) ? $params : []; - /* (3) On définit en constante la méthode HTTP */ + /* (4) On définit en constante la méthode HTTP */ if( !isset($_SERVER['REQUEST_METHOD']) && !is_string($forced_method) ) return $this->error->set(Err::UnknownHttpMethod); $this->http_method = is_string($forced_method) ? strtoupper($forced_method) : strtoupper($_SERVER['REQUEST_METHOD']); - /* (4) Verification du chemin (existence module+methode) ---------------------------------------------------------*/ if( !$this->checkURI($uri) ) // Verification de la coherence du chemin + attribution return false; // checkURI() sets the error itself - /* (5) Verification des permissions + /* (5) Si requête de documentation -> on arrête la vérification + ---------------------------------------------------------*/ + if( $this->id['doc_request'] ) + return true; + + + /* (6) Verification des permissions ---------------------------------------------------------*/ if( !$this->checkPermission() ) // Si on a pas les droits return false; // checkPermission() sets the error itself - /* (6) Verification des parametres (si @type est defini) + /* (7) Verification des parametres (si @type est defini) ---------------------------------------------------------*/ if( !$this->checkParams() ) // Verification de tous les types return false; // checkParams() sets the error itself - /* (7) Récupèration des options + /* (8) Récupèration des options ---------------------------------------------------------*/ $this->buildOptions(); - /* (8) Construction de l'objet (add http method to params) + /* (9) Construction de l'objet ---------------------------------------------------------*/ - $this->params['HTTP_METHOD'] = $this->http_method; $this->error->set(Err::Success); return true; // On retourne que tout s'est bien passe + } @@ -150,67 +150,9 @@ - /* (3) Construction du schéma à partir de la configuration + /* (3) Verification du format et de la coherence du chemin specifie * - ---------------------------------------------------------*/ - private function buildConfig(){ - - /* (1) Access file content - ---------------------------------------------------------*/ - /* (1) Vérification existence fichier config */ - if( !file_exists(self::config_path()) ) - return $this->error->set(Err::UnreachableResource); - - /* (2) Lecture fichier config */ - $conf = @file_get_contents(self::config_path()); - - /* (3) Si erreur lecture */ - if( $conf === false ) - return $this->error->set(Err::UnreachableResource); - - /* (4) Parsage json */ - $this->schema['raw'] = json_decode( $conf, true ); - - /* (5) Gestion de l'erreur de parsage */ - if( $this->schema['raw'] == null ) - return $this->error->set(Err::ParsingFailed, 'json'); - - - /* (2) Construction des outils d'accès - ---------------------------------------------------------*/ - /* (1) Initialisation */ - $this->schema['index'] = []; - - /* (2) Pour chaque chemin */ - foreach($this->schema['raw'] as $path=>$methods){ - - /* (2.1) Pour chaque méthode */ - foreach($methods as $method=>$data){ - - /* (2.1.1) Suppression si pas dans les méthodes autorisées */ - if( !in_array($method, self::$allowed_http_methods) ){ - unset($this->schema[$path][$method]); - continue; - } - - /* (2.1.2) Création de l'index pour le chemin si n'existe pas déja */ - if( !isset($this->schema['index'][$path]) ) - $this->schema['index'][$path] = []; - - /* (2.1.3) Ajout de la méthode à l'index */ - $this->schema['index'][$path][] = $method; - - } - - } - - } - - - - /* (4) Verification du format et de la coherence du chemin specifie - * - * @path String correspondant au chemin de delegation ("module/methode") + * @URI URI d'appel (commence par /) * * @return validity Retourne si oui ou non l'objet est correct * @@ -220,9 +162,14 @@ /* (1) Verification format general ---------------------------------------------------------*/ /* (1) If wrong format -> exit */ - if( !preg_match('@^\w+(\/\w+)*\/?$@', $uri, $matches) ) + if( !preg_match('@^\/[^\/]*(\/[^\/]*)*\/?$@', $uri) ) return $this->error->set(Err::WrongPathModule); + /* (2) Add ending '/' if not there */ + if( $uri[strlen($uri)-1] != '/' ) + $uri = "$uri/"; + + /* (2) Verification de l'existence du chemin (conf) ---------------------------------------------------------*/ @@ -230,12 +177,12 @@ $exists_size = 0; $path = null; - foreach($this->schema['index'] as $key=>$void){ + foreach(Config::get()->index as $key=>$void){ $match_size = strlen($key); - /* (1.1) Look for the longer match */ - if( $match_size > $exists_size && substr($uri, 0, $match_size) == $key ){ - $exists_size = $match_size; + /* (1.1) Look for the longer ( match | '/' ) */ + if( $match_size > $exists_size && substr($uri, 0, $match_size+1) == "$key/" || $key == '/' ){ + $exists_size = $key == '/' ? 0 : $match_size; $path = $key; } @@ -251,33 +198,43 @@ /* (1) Extract URI string after @path */ $uri_end = substr($uri, $exists_size); - /* (2) If invalid format, return error */ - if( !preg_match('@^((?:\/[^\/]+)*)\/?$@', $uri_end, $uri_match) ) + /* (2) Special case: add / if root uri arguments */ + if( strlen($uri_end) > 0 && $uri_end[0] != '/' ) + $uri_end = "/$uri_end"; + + /* (3) If invalid format, return error */ + if( !preg_match('@^((?:\/[^\/]*)*)\/?$@', $uri_end, $uri_match) ) return $this->error->set(Err::InvalidURI); - /* (3) Add each URI parameter to the parameter store */ + /* (4) Add each URI parameter to the parameter store */ $uri_args = array_slice( explode('/', $uri_match[1]), 1); foreach($uri_args as $index=>$value) - $this->raw_params["URL$index"] = $value; + if( strlen($value) > 0 ) // do not store '//' empty values + $this->raw_params["URL$index"] = $value; + /* (4) Verification de l'existence de la methode (conf) ---------------------------------------------------------*/ - /* (1) Check if HTTP method is in allowed methods */ - if( !in_array($this->http_method, self::$allowed_http_methods) ) + /* (1) If it is a documentation request */ + $doc_req = $this->http_method == 'OPTIONS'; + + /* (2) Check if HTTP method is in allowed methods */ + if( !in_array($this->http_method, Config::$allowed_http_methods) && !$doc_req ) return $this->error->set(Err::UnknownHttpMethod, $this->http_method); - /* (2) Check if HTTP method is defined for this @path */ - if( !in_array($this->http_method, $this->schema['index'][$path]) ) + /* (3) Check if HTTP method is defined for this @path */ + if( !isset(Config::get()->index[$path][$this->http_method]) && !$doc_req ) return $this->error->set(Err::UnknownMethod, $this->http_method); /* (5) Enregistrement du chemin et renvoi de SUCCESS ---------------------------------------------------------*/ - $this->path = [ - 'path'=> $path, - 'method'=> $this->http_method + $this->id = [ + 'path' => $path, + 'method' => $this->http_method, + 'doc_request' => $doc_req ]; return true; @@ -285,7 +242,7 @@ - /* (5) Retourne si on a la permission d'executer cette methode + /* (4) Retourne si on a la permission d'executer cette methode * * @return permission Retourne si on a les droits ou pas pour executer cette methode * @@ -295,7 +252,7 @@ /* (1) On recupere les informations utiles ---------------------------------------------------------*/ // On recupere le nom de la methode - $method = $this->schema['raw'][$this->path['path']][$this->path['method']]; + $method = Config::get()->index[$this->id['path']][$this->id['method']]; // Si aucune permission n'est definie if( !isset($method['permissions']) || !is_array($method['permissions']) || count($method['permissions']) < 1 ) @@ -332,7 +289,7 @@ - /* (6) Verification du type des parametres envoyes + /* (5) Verification du type des parametres envoyes * * @return correct Retourne si oui ou non les parametres ont le bon type * @@ -346,7 +303,7 @@ return $this->error->set(Err::MissingParam); /* (2) On récupère les données de la méthode */ - $method = $this->schema['raw'][$this->path['path']][$this->path['method']]; + $method = Config::get()->index[$this->id['path']][$this->id['method']]; /* (3) Si pas 'parameters' dans la config */ if( !isset($method['parameters']) || !is_array($method['parameters']) ) @@ -379,16 +336,32 @@ if( isset($config['rename']) && is_string($config['rename']) && preg_match('@^\w+$@', $config['rename']) ) $rename = $config['rename']; - /* (1) On récupère si le paramètre est optionnel ou pas */ + /* (2) On récupère si le paramètre est optionnel ou pas */ $optional = isset($config['optional']) && $config['optional'] === true; - /* (2) Si de type 'FILE' + fichier existe => on enregistre la ref. */ + /* (3) Gestion du paramètre DEFAULT */ + $default = null; + + /* (3.1) Check if default NOT (NULL || FILE) -> matches TYPE */ + if( isset($config['default']) ){ + + /* (3.1.1) Set default value from config */ + $default = $config['default']; + + /* (3.1.2) If FILE and not null -> Check type */ + if( $config['type'] != 'FILE' || $default != null ) + if( !Checker::run($config['type'], $default) ) + return $this->error->set(Err::WrongDefaultParam, $rename, $config['type']); + + } + + /* (4) Si de type 'FILE' + fichier existe => on enregistre la ref. */ if( $config['type'] == 'FILE' && isset($_FILES[$name]) ) $this->params[$rename] = &$_FILES[$name]; - /* (3) Si param obligatoire et manquant -> erreur */ + /* (4) Si param obligatoire et manquant -> erreur */ if( !isset($this->raw_params[$name]) && !$optional ) - return $this->error->set(Err::MissingParam, $name); + return $this->error->set(Err::MissingParam, $rename); /* (2.3) Gestion des valeurs @@ -396,15 +369,15 @@ /* (1) Si le paramètre est optionnel et manquant */ if( $optional && !isset($this->raw_params[$name]) ){ - // On le crée le param optionnel avec la valeur NULL - $this->params[$rename] = null; + // On le crée le param optionnel avec la valeur @default + $this->params[$rename] = $default; /* (2) Si le paramètre est renseigné (sauf FILE) */ - }elseif( $config['type'] != 'FILE'){ + }elseif( $config['type'] != 'FILE' ){ // Si la verification est fausse, on retourne faux if( !Checker::run($config['type'], $this->raw_params[$name]) ) - return $this->error->set(Err::WrongParam, $name, $config['type']); + return $this->error->set(Err::WrongParam, $rename, $config['type']); // Sinon, on ajoute aux params qu'on enverra à l'appel else @@ -423,7 +396,7 @@ - /* (7) Ajout des options a partir de la configuration + /* (6) Ajout des options a partir de la configuration * * @return correct Retourne FAUS en cas d'erreur * @@ -432,7 +405,7 @@ /* (1) On récupère les options de la méthode en cours ---------------------------------------------------------*/ - $method = $this->schema['raw'][$this->path['path']][$this->path['method']]; + $method = Config::get()->index[$this->id['path']][$this->id['method']]; /* (1) Si 'option' n'est pas défini (ou incorrect), on met les valeurs par défaut */ if( !isset($method['options']) || !is_array($method['options']) ) @@ -468,41 +441,45 @@ - /* (8) Execute le traitement associe et remplie la reponse + /* (7) Execute le traitement associe et remplie la reponse * * @return answer Retourne une reponse de type si tout s'est bien passe * ---------------------------------------------------------*/ public function dispatch(){ - /* (1) On verifie qu'aucune erreur n'a ete signalee + /* (1) Vérifications de niveau 0 ---------------------------------------------------------*/ - if( $this->error->get() !== Err::Success ) // si il y a une erreur - return new Response($this->error); // on la passe a la reponse + /* (1) Si erreur -> on dispatch à la réponse */ + if( $this->error->get() !== Err::Success ) + return new Response($this->error); + + /* (2) S'il requête de documentation -> on génère la documentation */ + if( $this->id['doc_request'] ) + return Documentation::generate($this); /* (2) On essaie d'instancier le module ---------------------------------------------------------*/ - $instance = ModuleFactory::getModule($this->path['path']); + $instance = ModuleFactory::getModule($this->id['path']); if( $instance instanceof Error ){ - $this->error->set(Err::UncallableModule, $this->path['path']); + $this->error->set(Err::UncallableModule, $this->id['path']); return new Response($this->error); } /* (3) On verifie que la methode est amorcable ---------------------------------------------------------*/ - if( !is_callable([$instance, $this->path['method']]) ){ - $this->error->set(Err::UncallableMethod, $this->path['method']); + if( !is_callable([$instance, $this->id['method']]) ){ + $this->error->set(Err::UncallableMethod, $this->id['method']); return new Response($this->error); } - /* (4) On amorce la methode ---------------------------------------------------------*/ /* (1) On lance la fonction */ - $returned = call_user_func( [$instance, $this->path['method']], $this->params ); + $returned = call_user_func( [$instance, $this->id['method']], $this->params ); /* (2) On appelle le destructeur (si défini) */ $instance = null; @@ -527,7 +504,7 @@ - /* EXECUTE LE TRAITEMENT ASSOCIE ET RENVOIE UN FICHIER AVEC LE HEADER ET LE BODY SPECIFIE + /* (8) Gestion d'un téléchargement HTTP * */ public function download(){ @@ -615,6 +592,27 @@ } + + /* (9) Getter générique + * + * @index Index de l'attribut + * + ---------------------------------------------------------*/ + public function get($index=null){ + + switch($index){ + + case 'id': return $this->id; break; + case 'raw_params': return $this->raw_params; break; + case 'params': return $this->params; break; + case 'options': return $this->options; break; + case 'http_method': return $this->http_method; break; + } + + return null; + } + + } ?>