diff --git a/.gitignore b/.gitignore index 2875e03..2734a16 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ vendor composer.lock nbproject/* .idea +/node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b89657..ae8279d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ # CHANGELOG +## v 2.0.3 18/05/2020 + * Agrega template para un recurso que de información de la API (sirve como healthcheck) + * Agrega posibilidad de especificar un logo para la documentacion + * Agrega mecanismo para hacer univoco el campo operationId + * Agrega parametrización de info básica para armado documentación en JSON + ## v 2.0.2 06/10/2017 * Fix encoding mensaje error en respuesta diff --git a/src/SIUToba/rest/docs/anotaciones_docs.php b/src/SIUToba/rest/docs/anotaciones_docs.php index cfc6979..e8db355 100644 --- a/src/SIUToba/rest/docs/anotaciones_docs.php +++ b/src/SIUToba/rest/docs/anotaciones_docs.php @@ -31,6 +31,15 @@ public function __construct($archivo) $this->get_annotations($this->reflexion); } + /** + * Devuelve el nombre (con Namespace) de la clase + * @return string + */ + public function get_nombre_clase() + { + return $this->reflexion->getNamespaceName() .'/'. $this->reflexion->getName(); + } + /** * Parsea una reflexion (metodo, clase) y devuelve las anotaciones en un arreglo. * @@ -227,7 +236,7 @@ public function get_respuestas_metodo($metodo) $matches = array(); //200 [array] $tipo descripcion $resultado = preg_match("/(\d{3})?\s*([ary]*)\s*(\{[\":\w\$\s]+\})?\s*(.*)/i", $respuesta, $matches); - if (0 === $resultado || false === $resultado) { + if (0 === $resultado || false === $resultado) { continue; } @@ -273,16 +282,16 @@ protected function get_tipo_datos($tipo) return; } - $refs = explode(':', $tipo); + $refs = explode(':', $tipo); if (false === $refs) { $tipoRef = array('type' => trim($tipo)); //Basic type - no name } else { if (substr($refs[0], 0, 1) == '$') { $tipoRef = array('$ref' => "#/definitions/". trim($refs[1])); //Referred type {"$ref": "Defined@Model"} } else { - $tipoRef = array('type' => trim($refs[1])); //Basic type - named {"id" : "integer"} - } - } - return $tipoRef; + $tipoRef = array('type' => trim($refs[1])); //Basic type - named {"id" : "integer"} + } + } + return $tipoRef; } } diff --git a/src/SIUToba/rest/docs/controlador_docs.php b/src/SIUToba/rest/docs/controlador_docs.php index af4bf13..60f1c45 100644 --- a/src/SIUToba/rest/docs/controlador_docs.php +++ b/src/SIUToba/rest/docs/controlador_docs.php @@ -20,6 +20,7 @@ class controlador_docs protected $api_url; protected $list; + protected $settings = array('titulo' => 'Api Title', 'version' => '1.0'); public function __construct($api_root, $api_url) { @@ -39,6 +40,16 @@ public function add_punto_partida($path) } } + /** + * Permite fijar las opciones para la generacion de documentacion + * + * @param array $settings Array asociativo conteniendo las opciones + * ['titulo' => '', 'version' => '', 'url_logo' => '',..] + */ + public function set_config($settings=array()) + { + $this->settings = \array_merge($this->settings, $settings); + } /** * Retorna la documentacion en formato swagger para el path. Si el path @@ -59,9 +70,10 @@ protected function getResourceList() $list = array(); $this->list = & $list; $list['swagger'] = "2.0"; - $list['info'] = array('title' => 'API Title', 'version' => '1.0'); //TODO: Read from settings + $list['info'] = array('title' => $this->settings['titulo'], 'version' => $this->settings['version']); $list['basePath'] = $this->api_url; $list['produces'] = array("application/json"); + $list = $this->add_extension_logo($list); $this->list['paths'] = array(); $this->list['definitions'] = array(); @@ -116,6 +128,7 @@ protected function add_apis($path) /** @var $reflexion anotaciones_docs */ $reflexion = $this->get_annotaciones_de_path($path); $metodos = $reflexion->get_metodos(); + $nombre_clase = $reflexion->get_nombre_clase(); $montaje = $this->get_montaje_de_path($path); $prefijo_montaje = $montaje ? '/' . $montaje : ''; @@ -177,7 +190,7 @@ protected function add_apis($path) $operation['summary'] = $reflexion->get_summary_metodo($metodo); $operation['description'] = $reflexion->get_notes_metodo($metodo); - $operation['operationId'] = $nombre_metodo; + $operation['operationId'] = "$nombre_clase:{$metodo['nombre']}"; $operation['parameters'] = array_merge($params_path, $params_body, $params_query); $operation['responses'] = $reflexion->get_respuestas_metodo($metodo); @@ -312,7 +325,7 @@ protected function add_modelos($path) * @param $params List of body params * @return array List of body params with schema definitions */ - protected function add_tipos_en_modelo($params) + protected function add_tipos_en_modelo($params) { $non_predefined_types = array_keys($this->list['definitions']); $param_keys = array_keys($params); @@ -321,7 +334,7 @@ protected function add_tipos_en_modelo($params) $params[$key]['schema'] = array('$ref' => "#/definitions/". trim($params[$key]['type'])); } } - + return $params; } @@ -346,4 +359,16 @@ protected function empieza_con($prefijo, $string) { return substr($string, 0, strlen($prefijo)) === $prefijo; } + + protected function add_extension_logo($list) + { + //Agrega el logo si esta presente + if (isset($this->settings['url_logo'])) { + $valid = (false !== filter_var($this->settings['url_logo'], FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED)); + if ($valid) { + $list['info']['x-logo'] = array('url' => $this->settings['api_logo']); + } + } + return $list; + } } diff --git a/src/SIUToba/rest/rest.php b/src/SIUToba/rest/rest.php index 3db1414..e9b9df5 100644 --- a/src/SIUToba/rest/rest.php +++ b/src/SIUToba/rest/rest.php @@ -101,6 +101,7 @@ public static function get_default_settings() 'http.version' => '1.1', // API version 'api_version' => '1.0.0', + 'api_titulo' => 'Api Reference', ); } @@ -366,8 +367,17 @@ protected function loggear_acceso_ok($usuario) */ protected function mostrar_documentacion($url) { + $config = [ + 'titulo' => $this->container['settings']['api_titulo'], + 'version' => $this->container['settings']['api_version'], + ]; + if (isset($this->container['settings']['logo'])) { + $config['url_logo'] = $this->container['settings']['logo']; + } + $this->logger->debug("Iniciando documentacion"); $controlador = $this->controlador_documentacion; + $controlador->set_config($config); $url = strstr($url, '/'); $controlador->get_documentacion($url); } diff --git a/src/SIUToba/rest/templates/template_info.php b/src/SIUToba/rest/templates/template_info.php new file mode 100644 index 0000000..2ad6376 --- /dev/null +++ b/src/SIUToba/rest/templates/template_info.php @@ -0,0 +1,40 @@ + [ + 'version' => array('type' => 'string'), + 'api_version' => array('type' => 'string'), + 'api_major' => array('type'=> 'string'), + 'api_minor' => array('type' => 'string') + ]); + } + + /** + * Devuelve informacion acerca de la API + * + * @responses 200 {$ref:info} OK + */ + public function get() + { + $version = rest::app()->config('version'); + $api = rest::app()->config('api_version'); + $api_major = rest::app()->config('api_major'); + $api_minor = rest::app()->config('api_minor'); + + if (is_null($version) || is_null($api) || is_null($api_major) || is_null($api_minor)) { + rest::response()->error_negocio(['La información solicitada no esta disponible'], 500); + } else { + $datos = array( 'version' => $version,'api_version' => $api, + 'api_major' => $api_major,'api_minor' => $api_minor); + rest::response()->get_list(array($datos)); + } + } +} \ No newline at end of file