├── .gitattributes ├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── aliases.php ├── composer.json ├── config ├── bootstrap.php └── routes.php ├── docs └── images │ ├── ui-index-default.png │ └── ui-quickstart-example.png ├── phpunit.xml.dist ├── src ├── Controller │ ├── AppController.php │ ├── DocsController.php │ └── UiController.php ├── Lib │ └── SwaggerTools.php ├── Plugin.php └── Shell │ └── SwaggerShell.php ├── templates ├── Docs │ └── index.php └── Ui │ └── index.php ├── tests ├── App │ ├── Application.php │ ├── config │ │ ├── bootstrap.php │ │ ├── routes.php │ │ ├── swagger.php.docs.custom_route │ │ ├── swagger.php.ui.custom_route │ │ └── swagger.php.ui.default_routes │ └── src │ │ └── Controller │ │ ├── DummyExcludeController.php │ │ └── DummyIncludeController.php ├── TestCase │ ├── Controller │ │ ├── DocsControllerTest.php │ │ ├── DocsCustomRouteIntegrationTest.php │ │ ├── UiControllerCustomUiRouteTest.php │ │ ├── UiControllerDefaultRouteTest.php │ │ └── UiControllerTest.php │ ├── Lib │ │ └── SwaggerToolsTest.php │ └── Shell │ │ └── SwaggerShellTest.php └── bootstrap.php └── webroot ├── css ├── print.css ├── reset.css ├── screen.css ├── style.css └── typography.css ├── fonts ├── DroidSans-Bold.ttf └── DroidSans.ttf ├── images ├── collapse.gif ├── expand.gif ├── explorer_icons.png ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── logo_small.png ├── pet_store_api.png ├── throbber.gif └── wordnik_api.png ├── lang ├── ca.js ├── en.js ├── es.js ├── fr.js ├── geo.js ├── it.js ├── ja.js ├── ko-kr.js ├── pl.js ├── pt.js ├── ru.js ├── tr.js ├── translator.js └── zh-cn.js ├── lib ├── backbone-min.js ├── es5-shim.js ├── handlebars-4.0.5.js ├── highlight.9.1.0.pack.js ├── highlight.9.1.0.pack_extended.js ├── jquery-1.8.0.min.js ├── jquery.ba-bbq.min.js ├── jquery.slideto.min.js ├── jquery.wiggle.min.js ├── js-yaml.min.js ├── jsoneditor.min.js ├── lodash.min.js ├── marked.js ├── object-assign-pollyfill.js ├── sanitize-html.min.js └── swagger-oauth.js ├── swagger-ui.js └── swagger-ui.min.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Define the line ending behavior of the different file extensions 2 | # Set default behaviour, in case users don't have core.autocrlf set. 3 | * text=auto 4 | * text eol=lf 5 | 6 | # Explicitly declare text files we want to always be normalized and converted 7 | # to native line endings on checkout. 8 | *.php text 9 | *.ctp text 10 | *.md text 11 | *.js text 12 | *.css text 13 | 14 | # Denote all files that are truly binary and should not be modified. 15 | *.png binary 16 | *.jpg binary 17 | *.gif binary 18 | *.ico binary 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/* 2 | /tmp/* 3 | /logs/* 4 | .idea/* 5 | composer.lock 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 7.2 5 | - 7.3 6 | - 7.4 7 | 8 | sudo: false 9 | 10 | env: 11 | global: 12 | - PHPUNIT=1 13 | 14 | matrix: 15 | fast_finish: true 16 | 17 | include: 18 | - php: 7.3 19 | env: PHPCS=1 PHPUNIT=0 20 | 21 | - php: 7.3 22 | env: CODECOVERAGE=1 PHPUNIT=0 23 | 24 | allow_failures: 25 | - php: hhvm 26 | 27 | before_script: 28 | - composer self-update 29 | - composer install --prefer-dist --no-interaction 30 | 31 | - sh -c "if [ '$PHPCS' = '1' ]; then composer require --dev cakephp/cakephp-codesniffer; fi" 32 | 33 | - phpenv rehash 34 | - set +H 35 | - cp phpunit.xml.dist phpunit.xml 36 | 37 | script: 38 | - sh -c "if [ '$PHPUNIT' = '1' ]; then vendor/bin/phpunit; fi" 39 | 40 | - sh -c "if [ '$PHPCS' = '1' ]; then vendor/bin/phpcs -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP ./src ./tests ./config --ignore=.webroot; fi" 41 | 42 | - sh -c "if [ '$CODECOVERAGE' = '1' ]; then vendor/bin/phpunit --coverage-clover=clover.xml || true; fi" 43 | - sh -c "if [ '$CODECOVERAGE' = '1' ]; then wget -O codecov.sh https://codecov.io/bash; fi" 44 | - sh -c "if [ '$CODECOVERAGE' = '1' ]; then bash codecov.sh; fi" 45 | 46 | notifications: 47 | email: false 48 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 ALT3 B.V. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cakephp-swagger 2 | 3 | [![Build Status](https://img.shields.io/travis/alt3/cakephp-swagger/master.svg?style=flat-square)](https://travis-ci.org/alt3/cakephp-swagger) 4 | [![StyleCI Status](https://styleci.io/repos/45741948/shield)](https://styleci.io/repos/45741948) 5 | [![Coverage Status](https://img.shields.io/codecov/c/github/alt3/cakephp-swagger/master.svg?style=flat-square)](https://codecov.io/github/alt3/cakephp-swagger) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/alt3/cakephp-swagger.svg?style=flat-square)](https://packagist.org/packages/alt3/cakephp-swagger) 7 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE.txt) 8 | 9 | CakePHP 4.x plugin that adds auto-generated Swagger 2.0 documentation to your projects using swagger-php and swagger-ui. 10 | 11 | ## Requirements 12 | 13 | * CakePHP 4.0+ 14 | * Some [swagger-php](https://github.com/zircote/swagger-php) annotation knowledge 15 | 16 | ## Installation 17 | 18 | Install the plugin using composer: 19 | 20 | ```bash 21 | composer require alt3/cakephp-swagger 22 | ``` 23 | 24 | ## Enabling 25 | Enable the plugin in the `bootstrap()` method found in `src/Application.php`: 26 | 27 | ```php 28 | public function bootstrap() 29 | { 30 | parent::bootstrap(); 31 | $this->addPlugin('Alt3/Swagger'); 32 | } 33 | ``` 34 | 35 | > Also make sure that AssetMiddleware is loaded inside `Application.php` or all Swagger page assets will 404. 36 | 37 | ## Installation check 38 | 39 | After enabling the plugin, browsing to `http://your.app/alt3/swagger` should now produce the 40 | [Swagger-UI](http://swagger.io/swagger-ui/) interface: 41 | 42 | ![Default UI index](/docs/images/ui-index-default.png) 43 | 44 | ## Configuration 45 | 46 | All configuration for this plugin is done through the `/config/swagger.php` 47 | configuration file. TLDR full example below. 48 | 49 | ```php 50 | [ 55 | 'ui' => [ 56 | 'title' => 'ALT3 Swagger', 57 | 'validator' => true, 58 | 'api_selector' => true, 59 | 'route' => '/swagger/', 60 | 'schemes' => ['http', 'https'] 61 | ], 62 | 'docs' => [ 63 | 'crawl' => Configure::read('debug'), 64 | 'route' => '/swagger/docs/', 65 | 'cors' => [ 66 | 'Access-Control-Allow-Origin' => '*', 67 | 'Access-Control-Allow-Methods' => 'GET, POST', 68 | 'Access-Control-Allow-Headers' => 'X-Requested-With' 69 | ] 70 | ], 71 | 'library' => [ 72 | 'api' => [ 73 | 'include' => ROOT . DS . 'src', 74 | 'exclude' => [ 75 | '/Editor/' 76 | ] 77 | ], 78 | 'editor' => [ 79 | 'include' => [ 80 | ROOT . DS . 'src' . DS . 'Controller' . DS . 'AppController.php', 81 | ROOT . DS . 'src' . DS . 'Controller' . DS . 'Editor', 82 | ROOT . DS . 'src' . DS . 'Model' 83 | ] 84 | ] 85 | ] 86 | ] 87 | ]; 88 | ``` 89 | 90 | ### UI section 91 | 92 | Use the `ui` section to customize the following Swagger-UI options: 93 | 94 | - `title`: sets the Swagger-UI page title, defaults to `cakephp-swagger` 95 | - `validator`: show/hide the validator image, defaults to `true` 96 | - `api_selector`: show/hide the api selector form fields, defaults to `true` 97 | - `route`: expose the UI using a custom route, defaults to `/alt3/swagger/` 98 | - `schemes`: array used to specify third field 99 | [used to generate the BASE URL](https://github.com/alt3/cakephp-swagger/issues/6) 100 | (`host` is fetched realtime, `basePath` is also fetched realtime if not 101 | [defined via annotations](https://github.com/alt3/cakephp-swagger/issues/29)), 102 | defaults to `null` 103 | 104 | > Please note that the UI will auto-load the first document found in the library. 105 | 106 | ### Docs section 107 | 108 | Use the `docs` section to customize the following options: 109 | 110 | - `crawl`: enable to crawl-generate new documents instead of 111 | serving from filesystem, defaults to `true` 112 | - `route`: expose the documents using a custom route, defaults to `/alt3/swagger/docs/` 113 | - `cors`: specify CORS headers to send with the json responses, defaults to `null` 114 | 115 | ### Library section 116 | 117 | Use the `library` section to specify one or multiple swagger documents so: 118 | 119 | - swagger-php will know which files and folders to parse for annotations 120 | - swagger-php can produce the swagger json 121 | - this plugin can expose the json at `http://your.app/alt3/swagger/docs/:id` 122 | (so it can be used by the UI) 123 | 124 | The following library example would result in: 125 | 126 | - swagger-php scanning all files and folders defined in `include` 127 | - swagger-php ignoring all files and folders defined in `exclude` 128 | - two endpoints serving json swagger documents: 129 | - `http://your.app/alt3/swagger/docs/api` 130 | - `http://your.app/alt3/swagger/docs/editor` 131 | 132 | ```php 133 | 'library' => [ 134 | 'api' => [ 135 | 'include' => ROOT . DS . 'src', 136 | 'exclude' => [ 137 | '/Editor/' 138 | ] 139 | ], 140 | 'editor' => [ 141 | 'include' => [ 142 | ROOT . DS . 'src' . DS . 'Controller' . DS . 'AppController.php', 143 | ROOT . DS . 'src' . DS . 'Controller' . DS . 'Editor', 144 | ROOT . DS . 'src' . DS . 'Model' 145 | ] 146 | ] 147 | ] 148 | ``` 149 | 150 | It would also make `http://your.app/alt3/swagger/docs` produce a json list 151 | with links to all available documents similar to the example below. 152 | 153 | ```json 154 | { 155 | "success": true, 156 | "data": [ 157 | { 158 | "document": "api", 159 | "link": "http://your.app/alt3/swagger/docs/api" 160 | }, 161 | { 162 | "document": "editor", 163 | "link": "http://your.app/alt3/swagger/docs/editor" 164 | } 165 | ] 166 | } 167 | ``` 168 | 169 | ## SwaggerShell 170 | 171 | This plugin comes with a shell that should simplify deployment in production 172 | environments. Simply run the following command to create `cakephp_swagger` 173 | prefixed filesystem documents in `tmp/cache` for all entities found in your 174 | library. 175 | 176 | ```bash 177 | bin/cake swagger makedocs 178 | ``` 179 | 180 | > The host argument (e.g. your.app.com) is required, should not include 181 | protocols and is used to set the `host` property inside your swagger documents. 182 | 183 | ## Quickstart Annotation Example 184 | 185 | Explaining [swagger-php](https://github.com/zircote/swagger-php) 186 | annotation voodoo is beyond this plugin but to give yourself a head start while 187 | creating your first library document you might want to copy/paste the following 188 | working example into any of your php files. 189 | 190 | > **Note**: the weird non-starred syntax ensures 191 | > compatibility with the CakePHP Code Sniffer. 192 | 193 | ```php 194 | =7.0", 8 | "cakephp/cakephp": "^4.0", 9 | "zircote/swagger-php": "^2.0" 10 | }, 11 | "require-dev": { 12 | "phpunit/phpunit": "^7.0" 13 | }, 14 | "support": { 15 | "issues": "https://github.com/alt3/cakephp-swagger/issues", 16 | "source": "https://github.com/alt3/cakephp-swagger" 17 | }, 18 | "autoload": { 19 | "psr-4": { 20 | "Alt3\\Swagger\\": "src" 21 | }, 22 | "files": [ 23 | "aliases.php" 24 | ] 25 | }, 26 | "autoload-dev": { 27 | "psr-4": { 28 | "Alt3\\Swagger\\Test\\": "tests" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /config/bootstrap.php: -------------------------------------------------------------------------------- 1 | '/', 15 | ], function (\Cake\Routing\RouteBuilder $routes) { 16 | 17 | // UI route 18 | if (Configure::read('Swagger.ui.route')) { 19 | $routes->connect( 20 | Configure::read('Swagger.ui.route'), 21 | ['plugin' => 'Alt3/Swagger', 'controller' => 'Ui', 'action' => 'index'] 22 | ); 23 | } else { 24 | $routes->connect( 25 | '/alt3/swagger/', 26 | ['plugin' => 'Alt3/Swagger', 'controller' => 'Ui', 'action' => 'index'] 27 | ); 28 | } 29 | 30 | // Documents route 31 | if (Configure::read('Swagger.docs.route')) { 32 | $routes->connect( 33 | Configure::read('Swagger.docs.route'), 34 | ['plugin' => 'Alt3/Swagger', 'controller' => 'Docs', 'action' => 'index'] 35 | ); 36 | 37 | $routes->connect( 38 | Configure::read('Swagger.docs.route') . ':id', 39 | ['plugin' => 'Alt3/Swagger', 'controller' => 'Docs', 'action' => 'index'] 40 | ) 41 | ->setPatterns(['id' => '\w+']) 42 | ->setPass(['id']); 43 | } else { 44 | $routes->connect( 45 | '/alt3/swagger/docs', 46 | ['plugin' => 'Alt3/Swagger', 'controller' => 'Docs', 'action' => 'index'] 47 | ); 48 | 49 | $routes->connect( 50 | '/alt3/swagger/docs/:id', 51 | ['plugin' => 'Alt3/Swagger', 'controller' => 'Docs', 'action' => 'index'] 52 | ) 53 | ->setPatterns(['id' => '\w+']) 54 | ->setPass(['id']); 55 | } 56 | }); 57 | -------------------------------------------------------------------------------- /docs/images/ui-index-default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/docs/images/ui-index-default.png -------------------------------------------------------------------------------- /docs/images/ui-quickstart-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/docs/images/ui-quickstart-example.png -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | ./tests/TestCase 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ./src/ 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/Controller/AppController.php: -------------------------------------------------------------------------------- 1 | [ 22 | 'crawl' => true, 23 | ], 24 | 'ui' => [ 25 | 'title' => 'cakephp-swagger', 26 | ], 27 | ]; 28 | 29 | /** 30 | * Initialization hook method. 31 | * 32 | * @return void 33 | */ 34 | public function initialize(): void 35 | { 36 | parent::initialize(); 37 | 38 | if (Configure::read('Swagger')) { 39 | $this->config = Hash::merge(static::$defaultConfig, Configure::read('Swagger')); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Controller/DocsController.php: -------------------------------------------------------------------------------- 1 | true, 16 | 'data' => [], 17 | ]; 18 | 19 | /** 20 | * Index action used to produce a JSON response containing either a swagger 21 | * document (if a valid id argument is passed) or a list with links to all 22 | * aavailable documents (if defined in the library). 23 | * 24 | * @param string $id Name of swagger document to generate/serve 25 | * @throws \InvalidArgumentException 26 | * @return void 27 | */ 28 | public function index($id = null) 29 | { 30 | if (!$id) { 31 | $this->jsonResponse($this->getJsonDocumentList()); 32 | 33 | return; 34 | } 35 | 36 | if (!isset($this->config['library'])) { 37 | throw new \InvalidArgumentException('Swagger configuration file does not contain a library section'); 38 | } 39 | 40 | if (!array_key_exists($id, $this->config['library'])) { 41 | throw new \InvalidArgumentException("Swagger configuration file does not contain a document definition for '$id'"); // phpcs:ignore 42 | } 43 | 44 | $document = SwaggerTools::getSwaggerDocument($id, $this->request->host()); 45 | $this->jsonResponse($document); 46 | } 47 | 48 | /** 49 | * Creates a json string containing fullBase links to all documents in the 50 | * library (useful for e.g. displaying on the /docs index action). 51 | * 52 | * @return string 53 | */ 54 | protected function getJsonDocumentList() 55 | { 56 | if (!isset($this->config['library'])) { 57 | return json_encode(static::$apiResponseBody, JSON_PRETTY_PRINT); 58 | } 59 | 60 | if (!count($this->config['library'])) { 61 | return json_encode(static::$apiResponseBody, JSON_PRETTY_PRINT); 62 | } 63 | 64 | foreach (array_keys($this->config['library']) as $document) { 65 | static::$apiResponseBody['data'][] = [ 66 | 'document' => $document, 67 | 'link' => Router::url([ 68 | 'plugin' => 'Alt3/Swagger', 69 | 'controller' => 'Docs', 70 | 'action' => 'index', 71 | $document, 72 | ], true), 73 | ]; 74 | } 75 | 76 | return json_encode(static::$apiResponseBody, JSON_PRETTY_PRINT + JSON_UNESCAPED_SLASHES); 77 | } 78 | 79 | /** 80 | * Set CORS headers if found in configuration. 81 | * 82 | * @return bool|void 83 | */ 84 | protected function addCorsHeaders() 85 | { 86 | // set CORS headers if specified in config 87 | if (!isset($this->config['docs']['cors'])) { 88 | return false; 89 | } 90 | 91 | if (!count($this->config['docs']['cors'])) { 92 | return false; 93 | } 94 | 95 | foreach ($this->config['docs']['cors'] as $header => $value) { 96 | $this->response = $this->response->withHeader($header, $value); 97 | } 98 | } 99 | 100 | /** 101 | * Configures the json response before calling the index view. 102 | * 103 | * @param string $json JSON encoded string 104 | * @return void 105 | */ 106 | protected function jsonResponse($json) 107 | { 108 | $this->set('json', $json); 109 | $this->viewBuilder()->disableAutoLayout(); 110 | $this->addCorsHeaders(); 111 | $this->response = $this->response->withType('json'); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Controller/UiController.php: -------------------------------------------------------------------------------- 1 | viewBuilder()->disableAutoLayout(); 21 | $this->set('uiConfig', $this->config['ui']); 22 | $this->set('url', $this->getDefaultDocumentUrl()); 23 | } 24 | 25 | /** 26 | * @return string 27 | */ 28 | public function getDefaultDocumentUrl() 29 | { 30 | // Use Swagger petstore if library contains no entries 31 | if (empty($this->config['library'])) { 32 | return 'http://petstore.swagger.io/v2/swagger.json'; 33 | } 34 | 35 | // Otherwise generate URL using first document in the library 36 | $defaultDocument = key($this->config['library']); 37 | 38 | return Router::url([ 39 | 'plugin' => 'Alt3/Swagger', 40 | 'controller' => 'Docs', 41 | 'action' => 'index', 42 | $defaultDocument, 43 | ], true); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Lib/SwaggerTools.php: -------------------------------------------------------------------------------- 1 | read(); 38 | } 39 | 40 | // otherwise crawl-generate a fresh document 41 | $swaggerOptions = []; 42 | if (Configure::read("Swagger.library.$id.exclude")) { 43 | $swaggerOptions = [ 44 | 'exclude' => Configure::read("Swagger.library.$id.exclude"), 45 | ]; 46 | } 47 | if (Configure::read('Swagger.analyser')) { 48 | $swaggerOptions['analyser'] = Configure::read('Swagger.analyser'); 49 | } 50 | $swagger = \Swagger\scan(Configure::read("Swagger.library.$id.include"), $swaggerOptions); 51 | 52 | // set object properties required by UI to generate the BASE URL 53 | $swagger->host = $host; 54 | if (empty($swagger->basePath)) { 55 | $swagger->basePath = '/' . Configure::read('App.base'); 56 | } 57 | $swagger->schemes = Configure::read('Swagger.ui.schemes'); 58 | 59 | // write document to filesystem 60 | self::writeSwaggerDocumentToFile($filePath, $swagger); 61 | 62 | return $swagger; 63 | } 64 | 65 | /** 66 | * Write swagger document to filesystem. 67 | * 68 | * @param string $path Full path to the json document including filename 69 | * @param object $content Swagger content 70 | * @throws \Cake\Http\Exception\InternalErrorException 71 | * @return bool 72 | */ 73 | protected static function writeSwaggerDocumentToFile($path, $content) 74 | { 75 | // we need to silence the warning so we can satisfy our Test by throwing without a warning interfering 76 | $fh = @fopen($path, 'w'); // phpcs:ignore 77 | if (!$fh || !fwrite($fh, $content->__toString())) { 78 | throw new InternalErrorException('Error writing Swagger json document to filesystem'); 79 | } 80 | 81 | return true; 82 | } 83 | 84 | /** 85 | * Convenience function used by the shell to create filesystem documents 86 | * for all entries found in the library. 87 | * 88 | * @param string $host Hostname of system serving swagger documents (without protocol) 89 | * @throws \InvalidArgumentException 90 | * @return bool true if successful, false on all errors 91 | */ 92 | public static function makeDocs($host) 93 | { 94 | if (!Configure::read('Swagger.library')) { 95 | throw new \InvalidArgumentException('Swagger configuration file does not contain a library section'); 96 | } 97 | 98 | // make sure documents will be crawled and not read from filesystem 99 | Configure::write('Swagger.docs.crawl', true); 100 | 101 | // generate docs 102 | foreach (array_keys(Configure::read('Swagger.library')) as $doc) { 103 | self::getSwaggerDocument($doc, $host); 104 | } 105 | 106 | return true; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Plugin.php: -------------------------------------------------------------------------------- 1 | addSubcommand('makedocs', [ 28 | 'description' => __('Crawl-generate fresh swagger file system documents for all entries found in the library.'), //phpcs:ignore 29 | ]) 30 | ->addArgument('host', [ 31 | 'help' => __("Swagger host FQDN (without protocol) as to be inserted into the swagger doc property 'host'"), 32 | 'required' => true, 33 | ]); 34 | 35 | return $parser; 36 | } 37 | 38 | /** 39 | * Generate fresh filesystem documents for all entries found in the library. 40 | * 41 | * @param string $host Hostname of system serving swagger documents (without protocol) 42 | * @return void 43 | */ 44 | public function makedocs($host) 45 | { 46 | // make same configuration as used by the API availble inside the lib 47 | if (Configure::read('Swagger')) { 48 | $this->config = Hash::merge(AppController::$defaultConfig, Configure::read('Swagger')); 49 | } 50 | 51 | $this->out('Crawl-generating swagger documents...'); 52 | SwaggerTools::makeDocs($host); 53 | $this->out('Command completed successfully.'); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /templates/Docs/index.php: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | <?= $uiConfig['title'] ?> 24 | Html->meta([ 28 | 'link' => $this->Url->assetUrl('Alt3/Swagger./images/favicon-32x32.png', ['fullBase' => true]), 29 | 'rel' => 'icon', 30 | 'sizes' => '32x32', 31 | 'type' => 'image/png', 32 | ]); 33 | echo $this->Html->meta([ 34 | 'link' => $this->Url->assetUrl('Alt3/Swagger./images/favicon-16x16.png', ['fullBase' => true]), 35 | 'rel' => 'icon', 36 | 'sizes' => '16x16', 37 | 'type' => 'image/png' 38 | ]); 39 | 40 | // screen stylesheets 41 | echo $this->Html->css([ 42 | 'Alt3/Swagger.typography.css', 43 | 'Alt3/Swagger.reset.css', 44 | 'Alt3/Swagger.screen.css', 45 | ], ['media' => 'screen', 'once' => false, 'fullBase' => true]); 46 | 47 | // print stylesheet 48 | echo $this->Html->css([ 49 | 'Alt3/Swagger.reset.css', 50 | 'Alt3/Swagger.print.css', 51 | ], ['media' => 'print', 'once' => false, 'fullBase' => true]); 52 | 53 | // javascript libraries 54 | echo $this->Html->script([ 55 | 'Alt3/Swagger./lib/object-assign-pollyfill.js', 56 | 'Alt3/Swagger./lib/jquery-1.8.0.min.js', 57 | 'Alt3/Swagger./lib/jquery.slideto.min.js', 58 | 'Alt3/Swagger./lib/jquery.wiggle.min.js', 59 | 'Alt3/Swagger./lib/jquery.ba-bbq.min.js', 60 | 'Alt3/Swagger./lib/handlebars-4.0.5.js', 61 | 'Alt3/Swagger./lib/lodash.min.js', 62 | 'Alt3/Swagger./lib/backbone-min.js', 63 | 'Alt3/Swagger./swagger-ui.js', 64 | 'Alt3/Swagger./lib/highlight.9.1.0.pack.js', 65 | 'Alt3/Swagger./lib/highlight.9.1.0.pack_extended.js', 66 | 'Alt3/Swagger./lib/jsoneditor.min.js', 67 | 'Alt3/Swagger./lib/marked.js', 68 | 'Alt3/Swagger./lib/swagger-oauth.js' 69 | ], ['fullBase' => true]); 70 | 71 | ?> 72 | 73 | 74 | 75 | 76 | 77 | 78 | 135 | 136 | 137 | 138 | 150 | 151 |
 
152 |
153 | 154 | 155 | -------------------------------------------------------------------------------- /tests/App/Application.php: -------------------------------------------------------------------------------- 1 | add(AssetMiddleware::class) 25 | // Add routing middleware. 26 | ->add(new RoutingMiddleware($this, null)); 27 | 28 | return $middlewareQueue; 29 | } 30 | 31 | public function bootstrap(): void 32 | { 33 | $this->addPlugin(Plugin::class, ['routes' => true, 'bootstrap' => true]); 34 | parent::bootstrap(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/App/config/bootstrap.php: -------------------------------------------------------------------------------- 1 | [ 9 | 'docs' => [ 10 | 'crawl' => true, 11 | 'route' => '/custom-docs-route/', 12 | 'cors' => [ 13 | 'Access-Control-Allow-Origin' => '*', 14 | 'Access-Control-Allow-Methods' => 'GET, POST', 15 | 'Access-Control-Allow-Headers' => 'X-Requested-With' 16 | ] 17 | ], 18 | 'library' => [ 19 | 'testdoc' => [ 20 | 'include' => APP 21 | ] 22 | ] 23 | ] 24 | ]; 25 | -------------------------------------------------------------------------------- /tests/App/config/swagger.php.ui.custom_route: -------------------------------------------------------------------------------- 1 | [ 9 | 'ui' => [ 10 | 'route' => '/custom-ui-route/' 11 | ] 12 | ] 13 | ]; 14 | -------------------------------------------------------------------------------- /tests/App/config/swagger.php.ui.default_routes: -------------------------------------------------------------------------------- 1 | [ 9 | 'ui' => [ 10 | 'route' => '/alt3/swagger/' 11 | ] 12 | ] 13 | ]; 14 | -------------------------------------------------------------------------------- /tests/App/src/Controller/DummyExcludeController.php: -------------------------------------------------------------------------------- 1 | [ 24 | 'crawl' => true, 25 | ], 26 | 'ui' => [ 27 | 'title' => 'cakephp-swagger', 28 | ], 29 | ]; 30 | 31 | /** 32 | * @var array Default CakePHP API success response structure. 33 | */ 34 | protected static $apiResponseBody = [ 35 | 'success' => true, 36 | 'data' => [], 37 | ]; 38 | 39 | /** 40 | * setUp method executed before every testMethod. 41 | */ 42 | public function setUp(): void 43 | { 44 | parent::setUp(); 45 | $this->controller = new DocsController(); 46 | 47 | $app = new Application(CONFIG); 48 | $app->bootstrap(); 49 | $builder = Router::createRouteBuilder('/'); 50 | $app->routes($builder); 51 | $app->pluginRoutes($builder); 52 | } 53 | 54 | /** 55 | * tearDown method executed after every testMethod. 56 | */ 57 | public function tearDown(): void 58 | { 59 | parent::tearDownAfterClass(); 60 | $testDoc = CACHE . 'cakephp_swagger_testdoc.json'; 61 | if (file_exists($testDoc)) { 62 | unlink($testDoc); 63 | } 64 | } 65 | 66 | /** 67 | * Make sure our tests are using the expected configuration settings. 68 | */ 69 | public function testDefaultSettings() 70 | { 71 | $this->assertSame(self::$defaultConfig, DocsController::$defaultConfig); 72 | $this->assertSame(self::$apiResponseBody, DocsController::$apiResponseBody); 73 | } 74 | 75 | /** 76 | * Make sure the function responsible for generating the json list with 77 | * documents (index action, no argument) returns the expected json. 78 | */ 79 | public function testMethodGetJsonDocumentList() 80 | { 81 | $reflection = self::getReflection($this->controller); 82 | 83 | // no library should return empty json success response 84 | $result = $reflection->methods->getJsonDocumentList->invokeArgs($this->controller, []); 85 | $expected = json_encode(self::$apiResponseBody, JSON_PRETTY_PRINT); 86 | $this->assertSame($expected, $result); 87 | 88 | // no documents in library should return empty json success response 89 | $reflection->properties->config->setValue($this->controller, array_merge(self::$defaultConfig, [ 90 | 'library' => [], 91 | ])); 92 | $result = $reflection->methods->getJsonDocumentList->invokeArgs($this->controller, []); 93 | $expected = json_encode(self::$apiResponseBody, JSON_PRETTY_PRINT); 94 | $this->assertSame($expected, $result); 95 | 96 | // filled library should return json data body with links 97 | $reflection->properties->config->setValue($this->controller, array_merge(self::$defaultConfig, [ 98 | 'library' => [ 99 | 'testdoc1' => [], 100 | 'testdoc2' => [], 101 | ], 102 | ])); 103 | 104 | $expected = <<<'EOF' 105 | { 106 | "success": true, 107 | "data": [ 108 | { 109 | "document": "testdoc1", 110 | "link": "http://localhost/alt3/swagger/docs/testdoc1" 111 | }, 112 | { 113 | "document": "testdoc2", 114 | "link": "http://localhost/alt3/swagger/docs/testdoc2" 115 | } 116 | ] 117 | } 118 | EOF; 119 | $result = $reflection->methods->getJsonDocumentList->invokeArgs($this->controller, []); 120 | $this->assertSame($expected, $result); 121 | 122 | // index action should return null when no document id is passed 123 | $result = $reflection->methods->index->invokeArgs($this->controller, []); 124 | $this->assertSame(null, $result); 125 | } 126 | 127 | /** 128 | * Make sure missing that a missing library section in the configuration 129 | * file will throw an exception when a document is being requested. 130 | * 131 | * @expectedException \InvalidArgumentException 132 | * @expectedExceptionMessage Swagger configuration file does not contain a library section 133 | */ 134 | public function testMissingLibrarySection() 135 | { 136 | $reflection = self::getReflection($this->controller); 137 | $reflection->methods->index->invokeArgs($this->controller, ['testdoc']); 138 | } 139 | 140 | /** 141 | * Make sure that an empty library in the configuration file will throw 142 | * an exception when a document is being requested. 143 | * 144 | * @expectedException \InvalidArgumentException 145 | * @expectedExceptionMessageRegExp #Swagger configuration file does not contain a document definition for *# 146 | */ 147 | public function testEmptyLibrary() 148 | { 149 | $reflection = self::getReflection($this->controller); 150 | $reflection->properties->config->setValue($this->controller, array_merge(self::$defaultConfig, [ 151 | 'library' => [], 152 | ])); 153 | $reflection->methods->index->invokeArgs($this->controller, ['testdoc']); 154 | } 155 | 156 | /** 157 | * Make sure missing or empty CORS headers definition in the configuration 158 | * file will not trigger adding headers to the json response. 159 | * 160 | * @return void 161 | */ 162 | public function testAddingCorsHeaders() 163 | { 164 | $reflection = self::getReflection($this->controller); 165 | 166 | // cors headers not in configuration 167 | $result = $reflection->methods->addCorsHeaders->invokeArgs($this->controller, []); 168 | $this->assertFalse($result); 169 | 170 | // cors headers section in configuration but no entries 171 | $reflection->properties->config->setValue($this->controller, array_merge(self::$defaultConfig, [ 172 | 'docs' => [ 173 | 'cors' => [], 174 | ], 175 | ])); 176 | $result = $reflection->methods->addCorsHeaders->invokeArgs($this->controller, []); 177 | $this->assertFalse($result); 178 | } 179 | 180 | /** 181 | * Convenience function to return an object with reflection class, 182 | * accessible protected methods and accessible protected properties. 183 | */ 184 | protected static function getReflection($object) 185 | { 186 | $obj = new stdClass(); 187 | $obj->class = new \ReflectionClass(get_class($object)); 188 | 189 | // make all methods accessible 190 | $obj->methods = new stdClass(); 191 | $classMethods = $obj->class->getMethods(); 192 | foreach ($classMethods as $method) { 193 | $methodName = $method->name; 194 | $obj->methods->{$methodName} = $obj->class->getMethod($methodName); 195 | $obj->methods->{$methodName}->setAccessible(true); 196 | } 197 | 198 | // make all properties accessible 199 | $obj->properties = new stdClass(); 200 | $classProperties = $obj->class->getProperties(); 201 | foreach ($classProperties as $property) { 202 | $propertyName = $property->name; 203 | $obj->properties->{$propertyName} = $obj->class->getProperty($propertyName); 204 | $obj->properties->{$propertyName}->setAccessible(true); 205 | } 206 | 207 | return $obj; 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /tests/TestCase/Controller/DocsCustomRouteIntegrationTest.php: -------------------------------------------------------------------------------- 1 | useHttpServer(true); 23 | $configTemplate = APP . 'config' . DS . 'swagger.php.docs.custom_route'; 24 | $this->tempConfig = APP . 'config' . DS . 'swagger.php'; 25 | copy($configTemplate, $this->tempConfig); 26 | } 27 | 28 | /** 29 | * tearDown method executed after every test method. 30 | */ 31 | public function tearDown(): void 32 | { 33 | parent::tearDown(); 34 | unlink($this->tempConfig); 35 | 36 | $testDoc = CACHE . 'cakephp_swagger_testdoc.json'; 37 | if (file_exists($testDoc)) { 38 | unlink($testDoc); 39 | } 40 | } 41 | 42 | /** 43 | * Make sure the custom document route is connected and serves 44 | * crawl-generated json with swagger body and CORS headers. 45 | * 46 | * @return void 47 | * 48 | * @throws \PHPUnit\Exception 49 | */ 50 | public function testCustomRouteSuccess() 51 | { 52 | $this->get('/custom-docs-route/testdoc'); 53 | $this->assertResponseOk(); 54 | $this->assertContentType('application/json'); 55 | $this->assertResponseContains('"swagger": "2.0"'); 56 | $this->assertHeader('Access-Control-Allow-Origin', '*'); 57 | $this->assertHeader('Access-Control-Allow-Headers', 'X-Requested-With'); 58 | } 59 | 60 | /** 61 | * Make sure the default document route no longer functions. 62 | * @throws \PHPUnit\Exception 63 | */ 64 | public function testDefaultRouteFail() 65 | { 66 | $this->get('/alt3/swagger/docs'); 67 | $this->assertResponseError(); 68 | $this->assertResponseContains('Error: Missing Route'); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tests/TestCase/Controller/UiControllerCustomUiRouteTest.php: -------------------------------------------------------------------------------- 1 | useHttpServer(true); 22 | $configTemplate = APP . 'config' . DS . 'swagger.php.ui.custom_route'; 23 | $this->tempConfig = APP . 'config' . DS . 'swagger.php'; 24 | copy($configTemplate, $this->tempConfig); 25 | } 26 | 27 | /** 28 | * tearDown method. 29 | */ 30 | public function tearDown(): void 31 | { 32 | parent::tearDown(); 33 | unlink($this->tempConfig); 34 | } 35 | 36 | /** 37 | * Make sure the custom UI route is connected and serves Petstore document. 38 | * 39 | * @return void 40 | * 41 | * @throws \PHPUnit\Exception 42 | */ 43 | public function testCustomRouteSuccess() 44 | { 45 | // default route 46 | $this->get('/custom-ui-route'); 47 | $this->assertResponseOk(); 48 | $this->assertResponseContains(''); 49 | $this->assertResponseContains('http://petstore.swagger.io/v2/swagger.json'); 50 | } 51 | 52 | /** 53 | * Make sure the default UI route is no longer connected. 54 | * 55 | * @return void 56 | * @throws \PHPUnit\Exception 57 | */ 58 | public function testDefaultRouteFail() 59 | { 60 | // default route should no longer function 61 | $this->get('/alt3/swagger'); 62 | $this->assertResponseError(); 63 | $this->assertResponseContains('Error: Missing Route'); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/TestCase/Controller/UiControllerDefaultRouteTest.php: -------------------------------------------------------------------------------- 1 | useHttpServer(true); 22 | $configTemplate = APP . 'config' . DS . 'swagger.php.ui.default_routes'; 23 | $this->tempConfig = APP . 'config' . DS . 'swagger.php'; 24 | copy($configTemplate, $this->tempConfig); 25 | } 26 | 27 | /** 28 | * tearDown method. 29 | */ 30 | public function tearDown(): void 31 | { 32 | parent::tearDown(); 33 | unlink($this->tempConfig); 34 | } 35 | 36 | /** 37 | * Make sure the default UI route is connected and serves Petstore document. 38 | * 39 | * @return void 40 | * 41 | * @throws \PHPUnit\Exception 42 | */ 43 | public function testDefaultRouteSuccess() 44 | { 45 | $this->get('/alt3/swagger'); 46 | $this->assertResponseOk(); 47 | $this->assertResponseContains(''); 48 | $this->assertResponseContains('http://petstore.swagger.io/v2/swagger.json'); 49 | } 50 | 51 | /** 52 | * Make sure the custom UI route is not connected. 53 | * 54 | * @return void 55 | * 56 | * @throws \PHPUnit\Exception 57 | */ 58 | public function testCustomRouteFail() 59 | { 60 | $this->get('/alt3/custom-ui-route'); 61 | $this->assertResponseError(); 62 | $this->assertResponseContains('Error: Missing Route'); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tests/TestCase/Controller/UiControllerTest.php: -------------------------------------------------------------------------------- 1 | [ 24 | 'crawl' => true, 25 | ], 26 | 'ui' => [ 27 | 'title' => 'cakephp-swagger', 28 | ], 29 | ]; 30 | 31 | /** 32 | * setUp method executed before every testMethod. 33 | */ 34 | public function setUp(): void 35 | { 36 | parent::setUp(); 37 | $this->controller = new UiController(); 38 | 39 | $app = new Application(CONFIG); 40 | $app->bootstrap(); 41 | $builder = Router::createRouteBuilder('/'); 42 | $app->routes($builder); 43 | $app->pluginRoutes($builder); 44 | } 45 | 46 | /** 47 | * Make sure our tests are using the expected configuration settings. 48 | */ 49 | public function testDefaultSettings() 50 | { 51 | $this->assertSame(self::$defaultConfig, UiController::$defaultConfig); 52 | } 53 | 54 | /** 55 | * Make sure the UI will auto-load the correct default document URL. 56 | * 57 | * @return void 58 | **/ 59 | public function testMethodGetDefaultDocumentUrl() 60 | { 61 | $reflection = self::getReflection($this->controller); 62 | 63 | // test without library documents 64 | $reflection->properties->config->setValue($this->controller, array_merge(self::$defaultConfig, [ 65 | 'library' => [], 66 | ])); 67 | $result = $reflection->methods->getDefaultDocumentUrl->invokeArgs($this->controller, []); 68 | $this->assertSame($result, 'http://petstore.swagger.io/v2/swagger.json'); 69 | 70 | // test with library document 71 | $reflection->properties->config->setValue($this->controller, [ 72 | 'library' => [ 73 | 'testdoc' => [], 74 | ], 75 | ]); 76 | $result = $reflection->methods->getDefaultDocumentUrl->invokeArgs($this->controller, []); 77 | $this->assertSame($result, 'http://localhost/alt3/swagger/docs/testdoc'); 78 | } 79 | 80 | /** 81 | * Convenience function to return an object with reflection class, 82 | * accessible protected methods and accessible protected properties. 83 | */ 84 | protected static function getReflection($object) 85 | { 86 | $obj = new stdClass(); 87 | $obj->class = new \ReflectionClass(get_class($object)); 88 | 89 | // make all methods accessible 90 | $obj->methods = new stdClass(); 91 | $classMethods = $obj->class->getMethods(); 92 | foreach ($classMethods as $method) { 93 | $methodName = $method->name; 94 | $obj->methods->{$methodName} = $obj->class->getMethod($methodName); 95 | $obj->methods->{$methodName}->setAccessible(true); 96 | } 97 | 98 | // make all properties accessible 99 | $obj->properties = new stdClass(); 100 | $classProperties = $obj->class->getProperties(); 101 | foreach ($classProperties as $property) { 102 | $propertyName = $property->name; 103 | $obj->properties->{$propertyName} = $obj->class->getProperty($propertyName); 104 | $obj->properties->{$propertyName}->setAccessible(true); 105 | } 106 | 107 | return $obj; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /tests/TestCase/Lib/SwaggerToolsTest.php: -------------------------------------------------------------------------------- 1 | [ 25 | 'crawl' => true, 26 | ], 27 | 'ui' => [ 28 | 'title' => 'cakephp-swagger', 29 | ], 30 | ]; 31 | 32 | /** 33 | * setUp method executed before every testMethod. 34 | */ 35 | public function setUp(): void 36 | { 37 | parent::setUp(); 38 | $this->lib = new SwaggerTools(); 39 | } 40 | 41 | /** 42 | * tearDown method executed after every testMethod. 43 | */ 44 | public function tearDown(): void 45 | { 46 | parent::tearDownAfterClass(); 47 | $testDoc = CACHE . 'cakephp_swagger_testdoc.json'; 48 | if (file_exists($testDoc)) { 49 | unlink($testDoc); 50 | } 51 | } 52 | 53 | /** 54 | * Make sure our tests are using the expected configuration settings. 55 | */ 56 | public function testDefaultSettings() 57 | { 58 | $this->assertSame(self::$defaultConfig, AppController::$defaultConfig); 59 | } 60 | 61 | /** 62 | * Make sure swagger documents can be crawl-generated successfully. 63 | */ 64 | public function testMethodGetSwaggerDocumentCrawlSuccess() 65 | { 66 | $reflection = self::getReflection($this->lib); 67 | Configure::write('Swagger', array_merge(self::$defaultConfig, [ 68 | 'docs' => [ 69 | 'crawl' => true, 70 | ], 71 | 'library' => [ 72 | 'testdoc' => [ 73 | 'include' => APP, // all files in dir 74 | ], 75 | ], 76 | ])); 77 | 78 | // make sure all files are being crawled 79 | $result = $reflection->methods->getSwaggerDocument->invokeArgs($this->lib, ['testdoc', 'www.test.app']); 80 | $this->assertSame($result->info->description, 'cakephp-swagger test document'); // IncludeController 81 | $this->assertSame($result->paths[0]->path, '/taxis'); // ExcludeController 82 | 83 | // make sure exclusions are actually being excluded from crawling. 84 | Configure::write('Swagger', array_merge(self::$defaultConfig, [ 85 | 'docs' => [ 86 | 'crawl' => true, 87 | ], 88 | 'library' => [ 89 | 'testdoc' => [ 90 | 'include' => APP, 91 | 'exclude' => APP . DS . 'Controller' . DS . 'DummyExcludeController', 92 | ], 93 | ], 94 | 'analyser' => new \Swagger\StaticAnalyser(), 95 | ])); 96 | 97 | $result = $reflection->methods->getSwaggerDocument->invokeArgs($this->lib, ['testdoc', 'www.test.app']); 98 | $this->assertSame($result->info->description, 'cakephp-swagger test document'); // IncludeController 99 | $this->assertNotSame($result->paths[0]->path, '/taxis'); // In ExcludeController so should not be present 100 | } 101 | 102 | /** 103 | * Make sure an exception is thrown when swagger document cannot be 104 | * written to the filesystem. 105 | * 106 | * @expectedException \Cake\Http\Exception\InternalErrorException 107 | * @expectedExceptionMessage Error writing Swagger json document to filesystem 108 | */ 109 | public function testMethodWriteSwaggerDocumentToFileFail() 110 | { 111 | $reflection = self::getReflection($this->lib); 112 | $reflection->methods->writeSwaggerDocumentToFile->invokeArgs($this->lib, ['////failing-doc-path', 'dummy-file-content']); 113 | } 114 | 115 | /** 116 | * Make sure requesting a document that does not exist on the filesystem 117 | * throws an exception in non-development mode. 118 | * 119 | * @expectedException \Cake\Http\Exception\NotFoundException 120 | * @expectedExceptionMessageRegExp #Swagger json document was not found on filesystem: *# 121 | */ 122 | public function testMethodGetSwaggerDocumentFromFileFail() 123 | { 124 | $reflection = self::getReflection($this->lib); 125 | Configure::write('Swagger', array_merge(self::$defaultConfig, [ 126 | 'docs' => [ 127 | 'crawl' => false, // force loading doc from filesystem 128 | ], 129 | 'library' => [ 130 | 'nonexisting' => [], 131 | ], 132 | ])); 133 | $reflection->methods->getSwaggerDocument->invokeArgs($this->lib, ['nonexisting', 'www.test.app']); 134 | } 135 | 136 | /** 137 | * Make sure swagger documents are successfully served from filesystem. 138 | */ 139 | public function testMethodGetSwaggerDocumentFromFileSuccess() 140 | { 141 | // make sure test file does not exist 142 | $filePath = CACHE . 'cakephp_swagger_testdoc.json'; 143 | $this->assertFileNotExists($filePath); 144 | 145 | // successfully crawl-generate a fresh json file 146 | $reflection = self::getReflection($this->lib); 147 | Configure::write('Swagger', array_merge(self::$defaultConfig, [ 148 | 'docs' => [ 149 | 'crawl' => true, 150 | ], 151 | 'library' => [ 152 | 'testdoc' => [ 153 | 'include' => APP, // all files in dir 154 | ], 155 | ], 156 | ])); 157 | 158 | $result = $reflection->methods->getSwaggerDocument->invokeArgs($this->lib, ['testdoc', 'www.test.app']); 159 | $this->assertFileExists($filePath); 160 | $this->assertSame($result->info->description, 'cakephp-swagger test document'); 161 | 162 | // generated file should load from from filesystem when disabling crawl 163 | Configure::write('Swagger', array_merge(self::$defaultConfig, [ 164 | 'docs' => [ 165 | 'crawl' => false, 166 | ], 167 | 'library' => [ 168 | 'testdoc' => [ 169 | 'include' => APP, // crawl all files in this directory 170 | ], 171 | ], 172 | ])); 173 | 174 | $reflection->methods->getSwaggerDocument->invokeArgs($this->lib, ['testdoc', 'www.test.app']); 175 | $fh = new File($filePath); 176 | $fileContent = $fh->read(); 177 | $this->assertContains('cakephp-swagger test document', $fileContent); // Annotation found in IncludeController 178 | } 179 | 180 | /** 181 | * Make sure missing library in the configuration throws an exception 182 | * when running the shell `makedocs` command. 183 | * 184 | * @expectedException \InvalidArgumentException 185 | * @expectedExceptionMessage Swagger configuration file does not contain a library section 186 | */ 187 | public function testMakeDocsWithMissingLibrary() 188 | { 189 | $reflection = self::getReflection($this->lib); 190 | Configure::delete('Swagger.library'); 191 | $reflection->methods->makeDocs->invokeArgs($this->lib, ['www.test.app']); 192 | } 193 | 194 | /** 195 | * Make sure library without docs in the configuration throws an exception 196 | * when running the shell `makedocs` command. 197 | * 198 | * @expectedException \InvalidArgumentException 199 | * @expectedExceptionMessage Swagger configuration file does not contain a library section 200 | */ 201 | public function testMakeDocsWithEmptyLibrary() 202 | { 203 | $reflection = self::getReflection($this->lib); 204 | Configure::write('Swagger.library', [ 205 | 206 | ]); 207 | $reflection->methods->makeDocs->invokeArgs($this->lib, ['www.test.app']); 208 | } 209 | 210 | /** 211 | * Make sure makedocs foreach loop is reached with doc-filled library. 212 | */ 213 | public function testMakeDocsWithFilledLibrary() 214 | { 215 | $reflection = self::getReflection($this->lib); 216 | Configure::write('Swagger.library', [ 217 | 'testdoc' => [ 218 | 'include' => APP, // crawl all files in this directory 219 | ], 220 | ]); 221 | $result = $reflection->methods->makeDocs->invokeArgs($this->lib, ['www.test.app']); 222 | $this->assertTrue($result); 223 | } 224 | 225 | /** 226 | * Convenience function to return an object with reflection class, 227 | * accessible protected methods and accessible protected properties. 228 | */ 229 | protected static function getReflection($object) 230 | { 231 | $obj = new stdClass(); 232 | $obj->class = new \ReflectionClass(get_class($object)); 233 | 234 | // make all methods accessible 235 | $obj->methods = new stdClass(); 236 | $classMethods = $obj->class->getMethods(); 237 | foreach ($classMethods as $method) { 238 | $methodName = $method->name; 239 | $obj->methods->{$methodName} = $obj->class->getMethod($methodName); 240 | $obj->methods->{$methodName}->setAccessible(true); 241 | } 242 | 243 | // make all properties accessible 244 | $obj->properties = new stdClass(); 245 | $classProperties = $obj->class->getProperties(); 246 | foreach ($classProperties as $property) { 247 | $propertyName = $property->name; 248 | $obj->properties->{$propertyName} = $obj->class->getProperty($propertyName); 249 | $obj->properties->{$propertyName}->setAccessible(true); 250 | } 251 | 252 | return $obj; 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /tests/TestCase/Shell/SwaggerShellTest.php: -------------------------------------------------------------------------------- 1 | io = $this->createMock('Cake\Console\ConsoleIo'); 26 | $this->shell = new SwaggerShell($this->io); 27 | } 28 | 29 | /** 30 | * tearDown method. 31 | * 32 | * @return void 33 | */ 34 | public function tearDown(): void 35 | { 36 | unset($this->shell); 37 | parent::tearDown(); 38 | } 39 | 40 | /** 41 | * Test the parser. 42 | */ 43 | public function testParser() 44 | { 45 | $reflection = self::getReflection($this->shell); 46 | $result = $reflection->methods->getOptionParser->invokeArgs($this->shell, []); 47 | $this->assertInstanceOf('\Cake\Console\ConsoleOptionParser', $result); 48 | } 49 | 50 | /** 51 | * Test the makedocs command. 52 | * 53 | * @return bool 54 | */ 55 | public function testMakeDocs() 56 | { 57 | $reflection = self::getReflection($this->shell); 58 | $result = $reflection->methods->makedocs->invokeArgs($this->shell, ['www.test.api']); 59 | $this->assertSame(null, $result); 60 | } 61 | 62 | /** 63 | * Convenience function to return an object with reflection class, 64 | * accessible protected methods and accessible protected properties. 65 | */ 66 | protected static function getReflection($object) 67 | { 68 | $obj = new stdClass(); 69 | $obj->class = new \ReflectionClass(get_class($object)); 70 | 71 | // make all methods accessible 72 | $obj->methods = new stdClass(); 73 | $classMethods = $obj->class->getMethods(); 74 | foreach ($classMethods as $method) { 75 | $methodName = $method->name; 76 | $obj->methods->{$methodName} = $obj->class->getMethod($methodName); 77 | $obj->methods->{$methodName}->setAccessible(true); 78 | } 79 | 80 | // make all properties accessible 81 | $obj->properties = new stdClass(); 82 | $classProperties = $obj->class->getProperties(); 83 | foreach ($classProperties as $property) { 84 | $propertyName = $property->name; 85 | $obj->properties->{$propertyName} = $obj->class->getProperty($propertyName); 86 | $obj->properties->{$propertyName}->setAccessible(true); 87 | } 88 | 89 | return $obj; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | register(); 39 | 40 | $loader->addNamespace('TestApp', APP); 41 | $loader->addNamespace('DebugkitTestPlugin', APP . 'Plugin' . DS . 'TestPlugin' . DS . 'src'); 42 | 43 | require_once CORE_PATH . 'config/bootstrap.php'; 44 | 45 | date_default_timezone_set('UTC'); 46 | mb_internal_encoding('UTF-8'); 47 | 48 | Configure::write('debug', true); 49 | Configure::write('App', [ 50 | 'namespace' => 'Alt3\Swagger\Test\App', 51 | 'encoding' => 'UTF-8', 52 | 'base' => false, 53 | 'baseUrl' => false, 54 | 'dir' => 'src', 55 | 'webroot' => 'webroot', 56 | 'www_root' => APP . 'webroot', 57 | 'fullBaseUrl' => 'http://localhost', 58 | 'imageBaseUrl' => 'img/', 59 | 'jsBaseUrl' => 'js/', 60 | 'cssBaseUrl' => 'css/', 61 | 'paths' => [ 62 | 'plugins' => [APP . 'Plugin' . DS], 63 | 'templates' => [APP . 'Template' . DS], 64 | ], 65 | ]); 66 | Configure::write('Session', [ 67 | 'defaults' => 'php', 68 | ]); 69 | 70 | Cache::setConfig([ 71 | '_cake_core_' => [ 72 | 'engine' => 'File', 73 | 'prefix' => 'cake_core_', 74 | 'serialize' => true, 75 | ], 76 | '_cake_model_' => [ 77 | 'engine' => 'File', 78 | 'prefix' => 'cake_model_', 79 | 'serialize' => true, 80 | ], 81 | 'default' => [ 82 | 'engine' => 'File', 83 | 'prefix' => 'default_', 84 | 'serialize' => true, 85 | ], 86 | ]); 87 | 88 | // Ensure default test connection is defined 89 | if (!getenv('db_dsn')) { 90 | putenv('db_dsn=sqlite:/' . TMP . 'debug_kit_test.sqlite'); 91 | } 92 | 93 | $config = [ 94 | 'url' => getenv('db_dsn'), 95 | 'timezone' => 'UTC', 96 | ]; 97 | 98 | // Use the test connection for 'debug_kit' as well. 99 | ConnectionManager::setConfig('test', $config); 100 | ConnectionManager::setConfig('test_debug_kit', $config); 101 | 102 | Log::setConfig([ 103 | 'debug' => [ 104 | 'engine' => 'Cake\Log\Engine\FileLog', 105 | 'levels' => ['notice', 'info', 'debug'], 106 | 'file' => 'debug', 107 | ], 108 | 'error' => [ 109 | 'engine' => 'Cake\Log\Engine\FileLog', 110 | 'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'], 111 | 'file' => 'error', 112 | ], 113 | ]); 114 | -------------------------------------------------------------------------------- /webroot/css/reset.css: -------------------------------------------------------------------------------- 1 | /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 */ 2 | html, 3 | body, 4 | div, 5 | span, 6 | applet, 7 | object, 8 | iframe, 9 | h1, 10 | h2, 11 | h3, 12 | h4, 13 | h5, 14 | h6, 15 | p, 16 | blockquote, 17 | pre, 18 | a, 19 | abbr, 20 | acronym, 21 | address, 22 | big, 23 | cite, 24 | code, 25 | del, 26 | dfn, 27 | em, 28 | img, 29 | ins, 30 | kbd, 31 | q, 32 | s, 33 | samp, 34 | small, 35 | strike, 36 | strong, 37 | sub, 38 | sup, 39 | tt, 40 | var, 41 | b, 42 | u, 43 | i, 44 | center, 45 | dl, 46 | dt, 47 | dd, 48 | ol, 49 | ul, 50 | li, 51 | fieldset, 52 | form, 53 | label, 54 | legend, 55 | table, 56 | caption, 57 | tbody, 58 | tfoot, 59 | thead, 60 | tr, 61 | th, 62 | td, 63 | article, 64 | aside, 65 | canvas, 66 | details, 67 | embed, 68 | figure, 69 | figcaption, 70 | footer, 71 | header, 72 | hgroup, 73 | menu, 74 | nav, 75 | output, 76 | ruby, 77 | section, 78 | summary, 79 | time, 80 | mark, 81 | audio, 82 | video { 83 | margin: 0; 84 | padding: 0; 85 | border: 0; 86 | font-size: 100%; 87 | font: inherit; 88 | vertical-align: baseline; 89 | } 90 | /* HTML5 display-role reset for older browsers */ 91 | article, 92 | aside, 93 | details, 94 | figcaption, 95 | figure, 96 | footer, 97 | header, 98 | hgroup, 99 | menu, 100 | nav, 101 | section { 102 | display: block; 103 | } 104 | body { 105 | line-height: 1; 106 | } 107 | ol, 108 | ul { 109 | list-style: none; 110 | } 111 | blockquote, 112 | q { 113 | quotes: none; 114 | } 115 | blockquote:before, 116 | blockquote:after, 117 | q:before, 118 | q:after { 119 | content: ''; 120 | content: none; 121 | } 122 | table { 123 | border-collapse: collapse; 124 | border-spacing: 0; 125 | } 126 | -------------------------------------------------------------------------------- /webroot/css/style.css: -------------------------------------------------------------------------------- 1 | .swagger-section #header a#logo { 2 | font-size: 1.5em; 3 | font-weight: bold; 4 | text-decoration: none; 5 | background: transparent url(../images/logo.png) no-repeat left center; 6 | padding: 20px 0 20px 40px; 7 | } 8 | #text-head { 9 | font-size: 80px; 10 | font-family: 'Roboto', sans-serif; 11 | color: #ffffff; 12 | float: right; 13 | margin-right: 20%; 14 | } 15 | .navbar-fixed-top .navbar-nav { 16 | height: auto; 17 | } 18 | .navbar-fixed-top .navbar-brand { 19 | height: auto; 20 | } 21 | .navbar-header { 22 | height: auto; 23 | } 24 | .navbar-inverse { 25 | background-color: #000; 26 | border-color: #000; 27 | } 28 | #navbar-brand { 29 | margin-left: 20%; 30 | } 31 | .navtext { 32 | font-size: 10px; 33 | } 34 | .h1, 35 | h1 { 36 | font-size: 60px; 37 | } 38 | .navbar-default .navbar-header .navbar-brand { 39 | color: #a2dfee; 40 | } 41 | /* tag titles */ 42 | .swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { 43 | color: #393939; 44 | font-family: 'Arvo', serif; 45 | font-size: 1.5em; 46 | } 47 | .swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { 48 | color: black; 49 | } 50 | .swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { 51 | color: #525252; 52 | padding-left: 0px; 53 | display: block; 54 | clear: none; 55 | float: left; 56 | font-family: 'Arvo', serif; 57 | font-weight: bold; 58 | } 59 | .navbar-default .navbar-collapse, 60 | .navbar-default .navbar-form { 61 | border-color: #0A0A0A; 62 | } 63 | .container1 { 64 | width: 1500px; 65 | margin: auto; 66 | margin-top: 0; 67 | background-image: url('../images/shield.png'); 68 | background-repeat: no-repeat; 69 | background-position: -40px -20px; 70 | margin-bottom: 210px; 71 | } 72 | .container-inner { 73 | width: 1200px; 74 | margin: auto; 75 | background-color: rgba(223, 227, 228, 0.75); 76 | padding-bottom: 40px; 77 | padding-top: 40px; 78 | border-radius: 15px; 79 | } 80 | .header-content { 81 | padding: 0; 82 | width: 1000px; 83 | } 84 | .title1 { 85 | font-size: 80px; 86 | font-family: 'Vollkorn', serif; 87 | color: #404040; 88 | text-align: center; 89 | padding-top: 40px; 90 | padding-bottom: 100px; 91 | } 92 | #icon { 93 | margin-top: -18px; 94 | } 95 | .subtext { 96 | font-size: 25px; 97 | font-style: italic; 98 | color: #08b; 99 | text-align: right; 100 | padding-right: 250px; 101 | } 102 | .bg-primary { 103 | background-color: #00468b; 104 | } 105 | .navbar-default .nav > li > a, 106 | .navbar-default .nav > li > a:focus { 107 | color: #08b; 108 | } 109 | .navbar-default .nav > li > a, 110 | .navbar-default .nav > li > a:hover { 111 | color: #08b; 112 | } 113 | .navbar-default .nav > li > a, 114 | .navbar-default .nav > li > a:focus:hover { 115 | color: #08b; 116 | } 117 | .text-faded { 118 | font-size: 25px; 119 | font-family: 'Vollkorn', serif; 120 | } 121 | .section-heading { 122 | font-family: 'Vollkorn', serif; 123 | font-size: 45px; 124 | padding-bottom: 10px; 125 | } 126 | hr { 127 | border-color: #00468b; 128 | padding-bottom: 10px; 129 | } 130 | .description { 131 | margin-top: 20px; 132 | padding-bottom: 200px; 133 | } 134 | .description li { 135 | font-family: 'Vollkorn', serif; 136 | font-size: 25px; 137 | color: #525252; 138 | margin-left: 28%; 139 | padding-top: 5px; 140 | } 141 | .gap { 142 | margin-top: 200px; 143 | } 144 | .troubleshootingtext { 145 | color: rgba(255, 255, 255, 0.7); 146 | padding-left: 30%; 147 | } 148 | .troubleshootingtext li { 149 | list-style-type: circle; 150 | font-size: 25px; 151 | padding-bottom: 5px; 152 | } 153 | .overlay { 154 | position: absolute; 155 | top: 0; 156 | left: 0; 157 | width: 100%; 158 | height: 100%; 159 | z-index: 1000; 160 | } 161 | .block.response_body.json:hover { 162 | cursor: pointer; 163 | } 164 | .backdrop { 165 | color: blue; 166 | } 167 | #myModal { 168 | height: 100%; 169 | } 170 | .modal-backdrop { 171 | bottom: 0; 172 | position: fixed; 173 | } 174 | .curl { 175 | padding: 10px; 176 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; 177 | font-size: 0.9em; 178 | max-height: 400px; 179 | margin-top: 5px; 180 | overflow-y: auto; 181 | background-color: #fcf6db; 182 | border: 1px solid #e5e0c6; 183 | border-radius: 4px; 184 | } 185 | .curl_title { 186 | font-size: 1.1em; 187 | margin: 0; 188 | padding: 15px 0 5px; 189 | font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif; 190 | font-weight: 500; 191 | line-height: 1.1; 192 | } 193 | .footer { 194 | display: none; 195 | } 196 | .swagger-section .swagger-ui-wrap h2 { 197 | padding: 0; 198 | } 199 | h2 { 200 | margin: 0; 201 | margin-bottom: 5px; 202 | } 203 | .markdown p { 204 | font-size: 15px; 205 | font-family: 'Arvo', serif; 206 | } 207 | .swagger-section .swagger-ui-wrap .code { 208 | font-size: 15px; 209 | font-family: 'Arvo', serif; 210 | } 211 | .swagger-section .swagger-ui-wrap b { 212 | font-family: 'Arvo', serif; 213 | } 214 | #signin:hover { 215 | cursor: pointer; 216 | } 217 | .dropdown-menu { 218 | padding: 15px; 219 | } 220 | .navbar-right .dropdown-menu { 221 | left: 0; 222 | right: auto; 223 | } 224 | #signinbutton { 225 | width: 100%; 226 | height: 32px; 227 | font-size: 13px; 228 | font-weight: bold; 229 | color: #08b; 230 | } 231 | .navbar-default .nav > li .details { 232 | color: #000000; 233 | text-transform: none; 234 | font-size: 15px; 235 | font-weight: normal; 236 | font-family: 'Open Sans', sans-serif; 237 | font-style: italic; 238 | line-height: 20px; 239 | top: -2px; 240 | } 241 | .navbar-default .nav > li .details:hover { 242 | color: black; 243 | } 244 | #signout { 245 | width: 100%; 246 | height: 32px; 247 | font-size: 13px; 248 | font-weight: bold; 249 | color: #08b; 250 | } 251 | -------------------------------------------------------------------------------- /webroot/css/typography.css: -------------------------------------------------------------------------------- 1 | /* Google Font's Droid Sans */ 2 | @font-face { 3 | font-family: 'Droid Sans'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: local('Droid Sans'), local('DroidSans'), url('../fonts/DroidSans.ttf'), format('truetype'); 7 | } 8 | /* Google Font's Droid Sans Bold */ 9 | @font-face { 10 | font-family: 'Droid Sans'; 11 | font-style: normal; 12 | font-weight: 700; 13 | src: local('Droid Sans Bold'), local('DroidSans-Bold'), url('../fonts/DroidSans-Bold.ttf'), format('truetype'); 14 | } 15 | -------------------------------------------------------------------------------- /webroot/fonts/DroidSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/fonts/DroidSans-Bold.ttf -------------------------------------------------------------------------------- /webroot/fonts/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/fonts/DroidSans.ttf -------------------------------------------------------------------------------- /webroot/images/collapse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/collapse.gif -------------------------------------------------------------------------------- /webroot/images/expand.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/expand.gif -------------------------------------------------------------------------------- /webroot/images/explorer_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/explorer_icons.png -------------------------------------------------------------------------------- /webroot/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/favicon-16x16.png -------------------------------------------------------------------------------- /webroot/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/favicon-32x32.png -------------------------------------------------------------------------------- /webroot/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/favicon.ico -------------------------------------------------------------------------------- /webroot/images/logo_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/logo_small.png -------------------------------------------------------------------------------- /webroot/images/pet_store_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/pet_store_api.png -------------------------------------------------------------------------------- /webroot/images/throbber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/throbber.gif -------------------------------------------------------------------------------- /webroot/images/wordnik_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alt3/cakephp-swagger/4d1a3afb807c291581154389fc928b17b9558c81/webroot/images/wordnik_api.png -------------------------------------------------------------------------------- /webroot/lang/ca.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Advertència: Obsolet", 6 | "Implementation Notes":"Notes d'implementació", 7 | "Response Class":"Classe de la Resposta", 8 | "Status":"Estatus", 9 | "Parameters":"Paràmetres", 10 | "Parameter":"Paràmetre", 11 | "Value":"Valor", 12 | "Description":"Descripció", 13 | "Parameter Type":"Tipus del Paràmetre", 14 | "Data Type":"Tipus de la Dada", 15 | "Response Messages":"Missatges de la Resposta", 16 | "HTTP Status Code":"Codi d'Estatus HTTP", 17 | "Reason":"Raó", 18 | "Response Model":"Model de la Resposta", 19 | "Request URL":"URL de la Sol·licitud", 20 | "Response Body":"Cos de la Resposta", 21 | "Response Code":"Codi de la Resposta", 22 | "Response Headers":"Capçaleres de la Resposta", 23 | "Hide Response":"Amagar Resposta", 24 | "Try it out!":"Prova-ho!", 25 | "Show/Hide":"Mostrar/Amagar", 26 | "List Operations":"Llista Operacions", 27 | "Expand Operations":"Expandir Operacions", 28 | "Raw":"Cru", 29 | "can't parse JSON. Raw result":"no puc analitzar el JSON. Resultat cru", 30 | "Example Value":"Valor d'Exemple", 31 | "Model Schema":"Esquema del Model", 32 | "Model":"Model", 33 | "apply":"aplicar", 34 | "Username":"Nom d'usuari", 35 | "Password":"Contrasenya", 36 | "Terms of service":"Termes del servei", 37 | "Created by":"Creat per", 38 | "See more at":"Veure més en", 39 | "Contact the developer":"Contactar amb el desenvolupador", 40 | "api version":"versió de la api", 41 | "Response Content Type":"Tipus de Contingut de la Resposta", 42 | "fetching resource":"recollint recurs", 43 | "fetching resource list":"recollins llista de recursos", 44 | "Explore":"Explorant", 45 | "Show Swagger Petstore Example Apis":"Mostrar API d'Exemple Swagger Petstore", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"No es pot llegir del servidor. Potser no teniu la configuració de control d'accés apropiada.", 47 | "Please specify the protocol for":"Si us plau, especifiqueu el protocol per a", 48 | "Can't read swagger JSON from":"No es pot llegir el JSON de swagger des de", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Finalitzada la càrrega del recurs informatiu. Renderitzant Swagger UI", 50 | "Unable to read api":"No es pot llegir l'api", 51 | "from path":"des de la ruta", 52 | "server returned":"el servidor ha retornat" 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lang/en.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Warning: Deprecated", 6 | "Implementation Notes":"Implementation Notes", 7 | "Response Class":"Response Class", 8 | "Status":"Status", 9 | "Parameters":"Parameters", 10 | "Parameter":"Parameter", 11 | "Value":"Value", 12 | "Description":"Description", 13 | "Parameter Type":"Parameter Type", 14 | "Data Type":"Data Type", 15 | "Response Messages":"Response Messages", 16 | "HTTP Status Code":"HTTP Status Code", 17 | "Reason":"Reason", 18 | "Response Model":"Response Model", 19 | "Request URL":"Request URL", 20 | "Response Body":"Response Body", 21 | "Response Code":"Response Code", 22 | "Response Headers":"Response Headers", 23 | "Hide Response":"Hide Response", 24 | "Headers":"Headers", 25 | "Try it out!":"Try it out!", 26 | "Show/Hide":"Show/Hide", 27 | "List Operations":"List Operations", 28 | "Expand Operations":"Expand Operations", 29 | "Raw":"Raw", 30 | "can't parse JSON. Raw result":"can't parse JSON. Raw result", 31 | "Example Value":"Example Value", 32 | "Model Schema":"Model Schema", 33 | "Model":"Model", 34 | "Click to set as parameter value":"Click to set as parameter value", 35 | "apply":"apply", 36 | "Username":"Username", 37 | "Password":"Password", 38 | "Terms of service":"Terms of service", 39 | "Created by":"Created by", 40 | "See more at":"See more at", 41 | "Contact the developer":"Contact the developer", 42 | "api version":"api version", 43 | "Response Content Type":"Response Content Type", 44 | "Parameter content type:":"Parameter content type:", 45 | "fetching resource":"fetching resource", 46 | "fetching resource list":"fetching resource list", 47 | "Explore":"Explore", 48 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 49 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.", 50 | "Please specify the protocol for":"Please specify the protocol for", 51 | "Can't read swagger JSON from":"Can't read swagger JSON from", 52 | "Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI", 53 | "Unable to read api":"Unable to read api", 54 | "from path":"from path", 55 | "server returned":"server returned" 56 | }); 57 | -------------------------------------------------------------------------------- /webroot/lang/es.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Advertencia: Obsoleto", 6 | "Implementation Notes":"Notas de implementación", 7 | "Response Class":"Clase de la Respuesta", 8 | "Status":"Status", 9 | "Parameters":"Parámetros", 10 | "Parameter":"Parámetro", 11 | "Value":"Valor", 12 | "Description":"Descripción", 13 | "Parameter Type":"Tipo del Parámetro", 14 | "Data Type":"Tipo del Dato", 15 | "Response Messages":"Mensajes de la Respuesta", 16 | "HTTP Status Code":"Código de Status HTTP", 17 | "Reason":"Razón", 18 | "Response Model":"Modelo de la Respuesta", 19 | "Request URL":"URL de la Solicitud", 20 | "Response Body":"Cuerpo de la Respuesta", 21 | "Response Code":"Código de la Respuesta", 22 | "Response Headers":"Encabezados de la Respuesta", 23 | "Hide Response":"Ocultar Respuesta", 24 | "Try it out!":"Pruébalo!", 25 | "Show/Hide":"Mostrar/Ocultar", 26 | "List Operations":"Listar Operaciones", 27 | "Expand Operations":"Expandir Operaciones", 28 | "Raw":"Crudo", 29 | "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", 30 | "Example Value":"Valor de Ejemplo", 31 | "Model Schema":"Esquema del Modelo", 32 | "Model":"Modelo", 33 | "apply":"aplicar", 34 | "Username":"Nombre de usuario", 35 | "Password":"Contraseña", 36 | "Terms of service":"Términos de Servicio", 37 | "Created by":"Creado por", 38 | "See more at":"Ver más en", 39 | "Contact the developer":"Contactar al desarrollador", 40 | "api version":"versión de la api", 41 | "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", 42 | "fetching resource":"buscando recurso", 43 | "fetching resource list":"buscando lista del recurso", 44 | "Explore":"Explorar", 45 | "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", 47 | "Please specify the protocol for":"Por favor, especificar el protocola para", 48 | "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", 50 | "Unable to read api":"No se puede leer la api", 51 | "from path":"desde ruta", 52 | "server returned":"el servidor retornó" 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lang/fr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Avertissement : Obsolète", 6 | "Implementation Notes":"Notes d'implémentation", 7 | "Response Class":"Classe de la réponse", 8 | "Status":"Statut", 9 | "Parameters":"Paramètres", 10 | "Parameter":"Paramètre", 11 | "Value":"Valeur", 12 | "Description":"Description", 13 | "Parameter Type":"Type du paramètre", 14 | "Data Type":"Type de données", 15 | "Response Messages":"Messages de la réponse", 16 | "HTTP Status Code":"Code de statut HTTP", 17 | "Reason":"Raison", 18 | "Response Model":"Modèle de réponse", 19 | "Request URL":"URL appelée", 20 | "Response Body":"Corps de la réponse", 21 | "Response Code":"Code de la réponse", 22 | "Response Headers":"En-têtes de la réponse", 23 | "Hide Response":"Cacher la réponse", 24 | "Headers":"En-têtes", 25 | "Try it out!":"Testez !", 26 | "Show/Hide":"Afficher/Masquer", 27 | "List Operations":"Liste des opérations", 28 | "Expand Operations":"Développer les opérations", 29 | "Raw":"Brut", 30 | "can't parse JSON. Raw result":"impossible de décoder le JSON. Résultat brut", 31 | "Example Value":"Exemple la valeur", 32 | "Model Schema":"Définition du modèle", 33 | "Model":"Modèle", 34 | "apply":"appliquer", 35 | "Username":"Nom d'utilisateur", 36 | "Password":"Mot de passe", 37 | "Terms of service":"Conditions de service", 38 | "Created by":"Créé par", 39 | "See more at":"Voir plus sur", 40 | "Contact the developer":"Contacter le développeur", 41 | "api version":"version de l'api", 42 | "Response Content Type":"Content Type de la réponse", 43 | "fetching resource":"récupération de la ressource", 44 | "fetching resource list":"récupération de la liste de ressources", 45 | "Explore":"Explorer", 46 | "Show Swagger Petstore Example Apis":"Montrer les Apis de l'exemple Petstore de Swagger", 47 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Impossible de lire à partir du serveur. Il se peut que les réglages access-control-origin ne soient pas appropriés.", 48 | "Please specify the protocol for":"Veuillez spécifier un protocole pour", 49 | "Can't read swagger JSON from":"Impossible de lire le JSON swagger à partir de", 50 | "Finished Loading Resource Information. Rendering Swagger UI":"Chargement des informations terminé. Affichage de Swagger UI", 51 | "Unable to read api":"Impossible de lire l'api", 52 | "from path":"à partir du chemin", 53 | "server returned":"réponse du serveur" 54 | }); 55 | -------------------------------------------------------------------------------- /webroot/lang/geo.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"ყურადღება: აღარ გამოიყენება", 6 | "Implementation Notes":"იმპლემენტაციის აღწერა", 7 | "Response Class":"რესპონს კლასი", 8 | "Status":"სტატუსი", 9 | "Parameters":"პარამეტრები", 10 | "Parameter":"პარამეტრი", 11 | "Value":"მნიშვნელობა", 12 | "Description":"აღწერა", 13 | "Parameter Type":"პარამეტრის ტიპი", 14 | "Data Type":"მონაცემის ტიპი", 15 | "Response Messages":"პასუხი", 16 | "HTTP Status Code":"HTTP სტატუსი", 17 | "Reason":"მიზეზი", 18 | "Response Model":"რესპონს მოდელი", 19 | "Request URL":"მოთხოვნის URL", 20 | "Response Body":"პასუხის სხეული", 21 | "Response Code":"პასუხის კოდი", 22 | "Response Headers":"პასუხის ჰედერები", 23 | "Hide Response":"დამალე პასუხი", 24 | "Headers":"ჰედერები", 25 | "Try it out!":"ცადე !", 26 | "Show/Hide":"გამოჩენა/დამალვა", 27 | "List Operations":"ოპერაციების სია", 28 | "Expand Operations":"ოპერაციები ვრცლად", 29 | "Raw":"ნედლი", 30 | "can't parse JSON. Raw result":"JSON-ის დამუშავება ვერ მოხერხდა. ნედლი პასუხი", 31 | "Example Value":"მაგალითი", 32 | "Model Schema":"მოდელის სტრუქტურა", 33 | "Model":"მოდელი", 34 | "Click to set as parameter value":"პარამეტრისთვის მნიშვნელობის მისანიჭებლად, დააკლიკე", 35 | "apply":"გამოყენება", 36 | "Username":"მოხმარებელი", 37 | "Password":"პაროლი", 38 | "Terms of service":"მომსახურების პირობები", 39 | "Created by":"შექმნა", 40 | "See more at":"ნახე ვრცლად", 41 | "Contact the developer":"დაუკავშირდი დეველოპერს", 42 | "api version":"api ვერსია", 43 | "Response Content Type":"პასუხის კონტენტის ტიპი", 44 | "Parameter content type:":"პარამეტრის კონტენტის ტიპი:", 45 | "fetching resource":"რესურსების მიღება", 46 | "fetching resource list":"რესურსების სიის მიღება", 47 | "Explore":"ნახვა", 48 | "Show Swagger Petstore Example Apis":"ნახე Swagger Petstore სამაგალითო Api", 49 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"სერვერთან დაკავშირება ვერ ხერხდება. შეამოწმეთ access-control-origin.", 50 | "Please specify the protocol for":"მიუთითეთ პროტოკოლი", 51 | "Can't read swagger JSON from":"swagger JSON წაკითხვა ვერ მოხერხდა", 52 | "Finished Loading Resource Information. Rendering Swagger UI":"რესურსების ჩატვირთვა სრულდება. Swagger UI რენდერდება", 53 | "Unable to read api":"api წაკითხვა ვერ მოხერხდა", 54 | "from path":"მისამართიდან", 55 | "server returned":"სერვერმა დააბრუნა" 56 | }); 57 | -------------------------------------------------------------------------------- /webroot/lang/it.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Attenzione: Deprecato", 6 | "Implementation Notes":"Note di implementazione", 7 | "Response Class":"Classe della risposta", 8 | "Status":"Stato", 9 | "Parameters":"Parametri", 10 | "Parameter":"Parametro", 11 | "Value":"Valore", 12 | "Description":"Descrizione", 13 | "Parameter Type":"Tipo di parametro", 14 | "Data Type":"Tipo di dato", 15 | "Response Messages":"Messaggi della risposta", 16 | "HTTP Status Code":"Codice stato HTTP", 17 | "Reason":"Motivo", 18 | "Response Model":"Modello di risposta", 19 | "Request URL":"URL della richiesta", 20 | "Response Body":"Corpo della risposta", 21 | "Response Code":"Oggetto della risposta", 22 | "Response Headers":"Intestazioni della risposta", 23 | "Hide Response":"Nascondi risposta", 24 | "Try it out!":"Provalo!", 25 | "Show/Hide":"Mostra/Nascondi", 26 | "List Operations":"Mostra operazioni", 27 | "Expand Operations":"Espandi operazioni", 28 | "Raw":"Grezzo (raw)", 29 | "can't parse JSON. Raw result":"non è possibile parsare il JSON. Risultato grezzo (raw).", 30 | "Model Schema":"Schema del modello", 31 | "Model":"Modello", 32 | "apply":"applica", 33 | "Username":"Nome utente", 34 | "Password":"Password", 35 | "Terms of service":"Condizioni del servizio", 36 | "Created by":"Creato da", 37 | "See more at":"Informazioni aggiuntive:", 38 | "Contact the developer":"Contatta lo sviluppatore", 39 | "api version":"versione api", 40 | "Response Content Type":"Tipo di contenuto (content type) della risposta", 41 | "fetching resource":"recuperando la risorsa", 42 | "fetching resource list":"recuperando lista risorse", 43 | "Explore":"Esplora", 44 | "Show Swagger Petstore Example Apis":"Mostra le api di esempio di Swagger Petstore", 45 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Non è possibile leggere dal server. Potrebbe non avere le impostazioni di controllo accesso origine (access-control-origin) appropriate.", 46 | "Please specify the protocol for":"Si prega di specificare il protocollo per", 47 | "Can't read swagger JSON from":"Impossibile leggere JSON swagger da:", 48 | "Finished Loading Resource Information. Rendering Swagger UI":"Lettura informazioni risorse termianta. Swagger UI viene mostrata", 49 | "Unable to read api":"Impossibile leggere la api", 50 | "from path":"da cartella", 51 | "server returned":"il server ha restituito" 52 | }); 53 | -------------------------------------------------------------------------------- /webroot/lang/ja.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"警告: 廃止予定", 6 | "Implementation Notes":"実装メモ", 7 | "Response Class":"レスポンスクラス", 8 | "Status":"ステータス", 9 | "Parameters":"パラメータ群", 10 | "Parameter":"パラメータ", 11 | "Value":"値", 12 | "Description":"説明", 13 | "Parameter Type":"パラメータタイプ", 14 | "Data Type":"データタイプ", 15 | "Response Messages":"レスポンスメッセージ", 16 | "HTTP Status Code":"HTTPステータスコード", 17 | "Reason":"理由", 18 | "Response Model":"レスポンスモデル", 19 | "Request URL":"リクエストURL", 20 | "Response Body":"レスポンスボディ", 21 | "Response Code":"レスポンスコード", 22 | "Response Headers":"レスポンスヘッダ", 23 | "Hide Response":"レスポンスを隠す", 24 | "Headers":"ヘッダ", 25 | "Try it out!":"実際に実行!", 26 | "Show/Hide":"表示/非表示", 27 | "List Operations":"操作一覧", 28 | "Expand Operations":"操作の展開", 29 | "Raw":"Raw", 30 | "can't parse JSON. Raw result":"JSONへ解釈できません. 未加工の結果", 31 | "Model Schema":"モデルスキーマ", 32 | "Model":"モデル", 33 | "apply":"実行", 34 | "Username":"ユーザ名", 35 | "Password":"パスワード", 36 | "Terms of service":"サービス利用規約", 37 | "Created by":"Created by", 38 | "See more at":"See more at", 39 | "Contact the developer":"開発者に連絡", 40 | "api version":"APIバージョン", 41 | "Response Content Type":"レスポンス コンテンツタイプ", 42 | "fetching resource":"リソースの取得", 43 | "fetching resource list":"リソース一覧の取得", 44 | "Explore":"Explore", 45 | "Show Swagger Petstore Example Apis":"SwaggerペットストアAPIの表示", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"サーバから読み込めません. 適切なaccess-control-origin設定を持っていない可能性があります.", 47 | "Please specify the protocol for":"プロトコルを指定してください", 48 | "Can't read swagger JSON from":"次からswagger JSONを読み込めません", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"リソース情報の読み込みが完了しました. Swagger UIを描画しています", 50 | "Unable to read api":"APIを読み込めません", 51 | "from path":"次のパスから", 52 | "server returned":"サーバからの返答" 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lang/ko-kr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"경고:폐기예정됨", 6 | "Implementation Notes":"구현 노트", 7 | "Response Class":"응답 클래스", 8 | "Status":"상태", 9 | "Parameters":"매개변수들", 10 | "Parameter":"매개변수", 11 | "Value":"값", 12 | "Description":"설명", 13 | "Parameter Type":"매개변수 타입", 14 | "Data Type":"데이터 타입", 15 | "Response Messages":"응답 메세지", 16 | "HTTP Status Code":"HTTP 상태 코드", 17 | "Reason":"원인", 18 | "Response Model":"응답 모델", 19 | "Request URL":"요청 URL", 20 | "Response Body":"응답 본문", 21 | "Response Code":"응답 코드", 22 | "Response Headers":"응답 헤더", 23 | "Hide Response":"응답 숨기기", 24 | "Headers":"헤더", 25 | "Try it out!":"써보기!", 26 | "Show/Hide":"보이기/숨기기", 27 | "List Operations":"목록 작업", 28 | "Expand Operations":"전개 작업", 29 | "Raw":"원본", 30 | "can't parse JSON. Raw result":"JSON을 파싱할수 없음. 원본결과:", 31 | "Model Schema":"모델 스키마", 32 | "Model":"모델", 33 | "apply":"적용", 34 | "Username":"사용자 이름", 35 | "Password":"암호", 36 | "Terms of service":"이용약관", 37 | "Created by":"작성자", 38 | "See more at":"추가정보:", 39 | "Contact the developer":"개발자에게 문의", 40 | "api version":"api버전", 41 | "Response Content Type":"응답Content Type", 42 | "fetching resource":"리소스 가져오기", 43 | "fetching resource list":"리소스 목록 가져오기", 44 | "Explore":"탐색", 45 | "Show Swagger Petstore Example Apis":"Swagger Petstore 예제 보기", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"서버로부터 읽어들일수 없습니다. access-control-origin 설정이 올바르지 않을수 있습니다.", 47 | "Please specify the protocol for":"다음을 위한 프로토콜을 정하세요", 48 | "Can't read swagger JSON from":"swagger JSON 을 다음으로 부터 읽을수 없습니다", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"리소스 정보 불러오기 완료. Swagger UI 랜더링", 50 | "Unable to read api":"api를 읽을 수 없습니다.", 51 | "from path":"다음 경로로 부터", 52 | "server returned":"서버 응답함." 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lang/pl.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Uwaga: Wycofane", 6 | "Implementation Notes":"Uwagi Implementacji", 7 | "Response Class":"Klasa Odpowiedzi", 8 | "Status":"Status", 9 | "Parameters":"Parametry", 10 | "Parameter":"Parametr", 11 | "Value":"Wartość", 12 | "Description":"Opis", 13 | "Parameter Type":"Typ Parametru", 14 | "Data Type":"Typ Danych", 15 | "Response Messages":"Wiadomości Odpowiedzi", 16 | "HTTP Status Code":"Kod Statusu HTTP", 17 | "Reason":"Przyczyna", 18 | "Response Model":"Model Odpowiedzi", 19 | "Request URL":"URL Wywołania", 20 | "Response Body":"Treść Odpowiedzi", 21 | "Response Code":"Kod Odpowiedzi", 22 | "Response Headers":"Nagłówki Odpowiedzi", 23 | "Hide Response":"Ukryj Odpowiedź", 24 | "Headers":"Nagłówki", 25 | "Try it out!":"Wypróbuj!", 26 | "Show/Hide":"Pokaż/Ukryj", 27 | "List Operations":"Lista Operacji", 28 | "Expand Operations":"Rozwiń Operacje", 29 | "Raw":"Nieprzetworzone", 30 | "can't parse JSON. Raw result":"nie można przetworzyć pliku JSON. Nieprzetworzone dane", 31 | "Model Schema":"Schemat Modelu", 32 | "Model":"Model", 33 | "apply":"użyj", 34 | "Username":"Nazwa użytkownika", 35 | "Password":"Hasło", 36 | "Terms of service":"Warunki używania", 37 | "Created by":"Utworzone przez", 38 | "See more at":"Zobacz więcej na", 39 | "Contact the developer":"Kontakt z deweloperem", 40 | "api version":"wersja api", 41 | "Response Content Type":"Typ Zasobu Odpowiedzi", 42 | "fetching resource":"ładowanie zasobu", 43 | "fetching resource list":"ładowanie listy zasobów", 44 | "Explore":"Eksploruj", 45 | "Show Swagger Petstore Example Apis":"Pokaż Przykładowe Api Swagger Petstore", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Brak połączenia z serwerem. Może on nie mieć odpowiednich ustawień access-control-origin.", 47 | "Please specify the protocol for":"Proszę podać protokół dla", 48 | "Can't read swagger JSON from":"Nie można odczytać swagger JSON z", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Ukończono Ładowanie Informacji o Zasobie. Renderowanie Swagger UI", 50 | "Unable to read api":"Nie można odczytać api", 51 | "from path":"ze ścieżki", 52 | "server returned":"serwer zwrócił" 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lang/pt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Aviso: Depreciado", 6 | "Implementation Notes":"Notas de Implementação", 7 | "Response Class":"Classe de resposta", 8 | "Status":"Status", 9 | "Parameters":"Parâmetros", 10 | "Parameter":"Parâmetro", 11 | "Value":"Valor", 12 | "Description":"Descrição", 13 | "Parameter Type":"Tipo de parâmetro", 14 | "Data Type":"Tipo de dados", 15 | "Response Messages":"Mensagens de resposta", 16 | "HTTP Status Code":"Código de status HTTP", 17 | "Reason":"Razão", 18 | "Response Model":"Modelo resposta", 19 | "Request URL":"URL requisição", 20 | "Response Body":"Corpo da resposta", 21 | "Response Code":"Código da resposta", 22 | "Response Headers":"Cabeçalho da resposta", 23 | "Headers":"Cabeçalhos", 24 | "Hide Response":"Esconder resposta", 25 | "Try it out!":"Tente agora!", 26 | "Show/Hide":"Mostrar/Esconder", 27 | "List Operations":"Listar operações", 28 | "Expand Operations":"Expandir operações", 29 | "Raw":"Cru", 30 | "can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru", 31 | "Model Schema":"Modelo esquema", 32 | "Model":"Modelo", 33 | "apply":"Aplicar", 34 | "Username":"Usuário", 35 | "Password":"Senha", 36 | "Terms of service":"Termos do serviço", 37 | "Created by":"Criado por", 38 | "See more at":"Veja mais em", 39 | "Contact the developer":"Contate o desenvolvedor", 40 | "api version":"Versão api", 41 | "Response Content Type":"Tipo de conteúdo da resposta", 42 | "fetching resource":"busca recurso", 43 | "fetching resource list":"buscando lista de recursos", 44 | "Explore":"Explorar", 45 | "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", 47 | "Please specify the protocol for":"Por favor especifique o protocolo", 48 | "Can't read swagger JSON from":"Não é possível ler o JSON Swagger de", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI", 50 | "Unable to read api":"Não foi possível ler api", 51 | "from path":"do caminho", 52 | "server returned":"servidor retornou" 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lang/ru.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Предупреждение: Устарело", 6 | "Implementation Notes":"Заметки", 7 | "Response Class":"Пример ответа", 8 | "Status":"Статус", 9 | "Parameters":"Параметры", 10 | "Parameter":"Параметр", 11 | "Value":"Значение", 12 | "Description":"Описание", 13 | "Parameter Type":"Тип параметра", 14 | "Data Type":"Тип данных", 15 | "HTTP Status Code":"HTTP код", 16 | "Reason":"Причина", 17 | "Response Model":"Структура ответа", 18 | "Request URL":"URL запроса", 19 | "Response Body":"Тело ответа", 20 | "Response Code":"HTTP код ответа", 21 | "Response Headers":"Заголовки ответа", 22 | "Hide Response":"Спрятать ответ", 23 | "Headers":"Заголовки", 24 | "Response Messages":"Что может прийти в ответ", 25 | "Try it out!":"Попробовать!", 26 | "Show/Hide":"Показать/Скрыть", 27 | "List Operations":"Операции кратко", 28 | "Expand Operations":"Операции подробно", 29 | "Raw":"В сыром виде", 30 | "can't parse JSON. Raw result":"Не удается распарсить ответ:", 31 | "Example Value":"Пример", 32 | "Model Schema":"Структура", 33 | "Model":"Описание", 34 | "Click to set as parameter value":"Нажмите, чтобы испльзовать в качестве значения параметра", 35 | "apply":"применить", 36 | "Username":"Имя пользователя", 37 | "Password":"Пароль", 38 | "Terms of service":"Условия использования", 39 | "Created by":"Разработано", 40 | "See more at":"Еще тут", 41 | "Contact the developer":"Связаться с разработчиком", 42 | "api version":"Версия API", 43 | "Response Content Type":"Content Type ответа", 44 | "Parameter content type:":"Content Type параметра:", 45 | "fetching resource":"Получение ресурса", 46 | "fetching resource list":"Получение ресурсов", 47 | "Explore":"Показать", 48 | "Show Swagger Petstore Example Apis":"Показать примеры АПИ", 49 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, проблема с настройками доступа", 50 | "Please specify the protocol for":"Пожалуйста, укажите протокол для", 51 | "Can't read swagger JSON from":"Не получается прочитать swagger json из", 52 | "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", 53 | "Unable to read api":"Не удалось прочитать api", 54 | "from path":"по адресу", 55 | "server returned":"сервер сказал" 56 | }); 57 | -------------------------------------------------------------------------------- /webroot/lang/tr.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"Uyarı: Deprecated", 6 | "Implementation Notes":"Gerçekleştirim Notları", 7 | "Response Class":"Dönen Sınıf", 8 | "Status":"Statü", 9 | "Parameters":"Parametreler", 10 | "Parameter":"Parametre", 11 | "Value":"Değer", 12 | "Description":"Açıklama", 13 | "Parameter Type":"Parametre Tipi", 14 | "Data Type":"Veri Tipi", 15 | "Response Messages":"Dönüş Mesajı", 16 | "HTTP Status Code":"HTTP Statü Kodu", 17 | "Reason":"Gerekçe", 18 | "Response Model":"Dönüş Modeli", 19 | "Request URL":"İstek URL", 20 | "Response Body":"Dönüş İçeriği", 21 | "Response Code":"Dönüş Kodu", 22 | "Response Headers":"Dönüş Üst Bilgileri", 23 | "Hide Response":"Dönüşü Gizle", 24 | "Headers":"Üst Bilgiler", 25 | "Try it out!":"Dene!", 26 | "Show/Hide":"Göster/Gizle", 27 | "List Operations":"Operasyonları Listele", 28 | "Expand Operations":"Operasyonları Aç", 29 | "Raw":"Ham", 30 | "can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç", 31 | "Model Schema":"Model Şema", 32 | "Model":"Model", 33 | "apply":"uygula", 34 | "Username":"Kullanıcı Adı", 35 | "Password":"Parola", 36 | "Terms of service":"Servis şartları", 37 | "Created by":"Oluşturan", 38 | "See more at":"Daha fazlası için", 39 | "Contact the developer":"Geliştirici ile İletişime Geçin", 40 | "api version":"api versiyon", 41 | "Response Content Type":"Dönüş İçerik Tipi", 42 | "fetching resource":"kaynak getiriliyor", 43 | "fetching resource list":"kaynak listesi getiriliyor", 44 | "Explore":"Keşfet", 45 | "Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", 47 | "Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz", 48 | "Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", 50 | "Unable to read api":"api okunamadı", 51 | "from path":"yoldan", 52 | "server returned":"sunucuya dönüldü" 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lang/translator.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Translator for documentation pages. 5 | * 6 | * To enable translation you should include one of language-files in your index.html 7 | * after . 8 | * For example - 9 | * 10 | * If you wish to translate some new texts you should do two things: 11 | * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. 12 | * 2. Mark that text it templates this way New Phrase or . 13 | * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. 14 | * 15 | */ 16 | window.SwaggerTranslator = { 17 | 18 | _words:[], 19 | 20 | translate: function(sel) { 21 | var $this = this; 22 | sel = sel || '[data-sw-translate]'; 23 | 24 | $(sel).each(function() { 25 | $(this).html($this._tryTranslate($(this).html())); 26 | 27 | $(this).val($this._tryTranslate($(this).val())); 28 | $(this).attr('title', $this._tryTranslate($(this).attr('title'))); 29 | }); 30 | }, 31 | 32 | _tryTranslate: function(word) { 33 | return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; 34 | }, 35 | 36 | learn: function(wordsMap) { 37 | this._words = wordsMap; 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /webroot/lang/zh-cn.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* jshint quotmark: double */ 4 | window.SwaggerTranslator.learn({ 5 | "Warning: Deprecated":"警告:已过时", 6 | "Implementation Notes":"实现备注", 7 | "Response Class":"响应类", 8 | "Status":"状态", 9 | "Parameters":"参数", 10 | "Parameter":"参数", 11 | "Value":"值", 12 | "Description":"描述", 13 | "Parameter Type":"参数类型", 14 | "Data Type":"数据类型", 15 | "Response Messages":"响应消息", 16 | "HTTP Status Code":"HTTP状态码", 17 | "Reason":"原因", 18 | "Response Model":"响应模型", 19 | "Request URL":"请求URL", 20 | "Response Body":"响应体", 21 | "Response Code":"响应码", 22 | "Response Headers":"响应头", 23 | "Hide Response":"隐藏响应", 24 | "Headers":"头", 25 | "Try it out!":"试一下!", 26 | "Show/Hide":"显示/隐藏", 27 | "List Operations":"显示操作", 28 | "Expand Operations":"展开操作", 29 | "Raw":"原始", 30 | "can't parse JSON. Raw result":"无法解析JSON. 原始结果", 31 | "Model Schema":"模型架构", 32 | "Model":"模型", 33 | "apply":"应用", 34 | "Username":"用户名", 35 | "Password":"密码", 36 | "Terms of service":"服务条款", 37 | "Created by":"创建者", 38 | "See more at":"查看更多:", 39 | "Contact the developer":"联系开发者", 40 | "api version":"api版本", 41 | "Response Content Type":"响应Content Type", 42 | "fetching resource":"正在获取资源", 43 | "fetching resource list":"正在获取资源列表", 44 | "Explore":"浏览", 45 | "Show Swagger Petstore Example Apis":"显示 Swagger Petstore 示例 Apis", 46 | "Can't read from server. It may not have the appropriate access-control-origin settings.":"无法从服务器读取。可能没有正确设置access-control-origin。", 47 | "Please specify the protocol for":"请指定协议:", 48 | "Can't read swagger JSON from":"无法读取swagger JSON于", 49 | "Finished Loading Resource Information. Rendering Swagger UI":"已加载资源信息。正在渲染Swagger UI", 50 | "Unable to read api":"无法读取api", 51 | "from path":"从路径", 52 | "server returned":"服务器返回" 53 | }); 54 | -------------------------------------------------------------------------------- /webroot/lib/backbone-min.js: -------------------------------------------------------------------------------- 1 | // Backbone.js 1.1.2 2 | 3 | (function(t,e){if(typeof define==="function"&&define.amd){define(["underscore","jquery","exports"],function(i,r,s){t.Backbone=e(t,s,i,r)})}else if(typeof exports!=="undefined"){var i=require("underscore");e(t,exports,i)}else{t.Backbone=e(t,{},t._,t.jQuery||t.Zepto||t.ender||t.$)}})(this,function(t,e,i,r){var s=t.Backbone;var n=[];var a=n.push;var o=n.slice;var h=n.splice;e.VERSION="1.1.2";e.$=r;e.noConflict=function(){t.Backbone=s;return this};e.emulateHTTP=false;e.emulateJSON=false;var u=e.Events={on:function(t,e,i){if(!c(this,"on",t,[e,i])||!e)return this;this._events||(this._events={});var r=this._events[t]||(this._events[t]=[]);r.push({callback:e,context:i,ctx:i||this});return this},once:function(t,e,r){if(!c(this,"once",t,[e,r])||!e)return this;var s=this;var n=i.once(function(){s.off(t,n);e.apply(this,arguments)});n._callback=e;return this.on(t,n,r)},off:function(t,e,r){var s,n,a,o,h,u,l,f;if(!this._events||!c(this,"off",t,[e,r]))return this;if(!t&&!e&&!r){this._events=void 0;return this}o=t?[t]:i.keys(this._events);for(h=0,u=o.length;h").attr(t);this.setElement(r,false)}else{this.setElement(i.result(this,"el"),false)}}});e.sync=function(t,r,s){var n=T[t];i.defaults(s||(s={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:n,dataType:"json"};if(!s.url){a.url=i.result(r,"url")||M()}if(s.data==null&&r&&(t==="create"||t==="update"||t==="patch")){a.contentType="application/json";a.data=JSON.stringify(s.attrs||r.toJSON(s))}if(s.emulateJSON){a.contentType="application/x-www-form-urlencoded";a.data=a.data?{model:a.data}:{}}if(s.emulateHTTP&&(n==="PUT"||n==="DELETE"||n==="PATCH")){a.type="POST";if(s.emulateJSON)a.data._method=n;var o=s.beforeSend;s.beforeSend=function(t){t.setRequestHeader("X-HTTP-Method-Override",n);if(o)return o.apply(this,arguments)}}if(a.type!=="GET"&&!s.emulateJSON){a.processData=false}if(a.type==="PATCH"&&k){a.xhr=function(){return new ActiveXObject("Microsoft.XMLHTTP")}}var h=s.xhr=e.ajax(i.extend(a,s));r.trigger("request",r,h,s);return h};var k=typeof window!=="undefined"&&!!window.ActiveXObject&&!(window.XMLHttpRequest&&(new XMLHttpRequest).dispatchEvent);var T={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var $=e.Router=function(t){t||(t={});if(t.routes)this.routes=t.routes;this._bindRoutes();this.initialize.apply(this,arguments)};var S=/\((.*?)\)/g;var H=/(\(\?)?:\w+/g;var A=/\*\w+/g;var I=/[\-{}\[\]+?.,\\\^$|#\s]/g;i.extend($.prototype,u,{initialize:function(){},route:function(t,r,s){if(!i.isRegExp(t))t=this._routeToRegExp(t);if(i.isFunction(r)){s=r;r=""}if(!s)s=this[r];var n=this;e.history.route(t,function(i){var a=n._extractParameters(t,i);n.execute(s,a);n.trigger.apply(n,["route:"+r].concat(a));n.trigger("route",r,a);e.history.trigger("route",n,r,a)});return this},execute:function(t,e){if(t)t.apply(this,e)},navigate:function(t,i){e.history.navigate(t,i);return this},_bindRoutes:function(){if(!this.routes)return;this.routes=i.result(this,"routes");var t,e=i.keys(this.routes);while((t=e.pop())!=null){this.route(t,this.routes[t])}},_routeToRegExp:function(t){t=t.replace(I,"\\$&").replace(S,"(?:$1)?").replace(H,function(t,e){return e?t:"([^/?]+)"}).replace(A,"([^?]*?)");return new RegExp("^"+t+"(?:\\?([\\s\\S]*))?$")},_extractParameters:function(t,e){var r=t.exec(e).slice(1);return i.map(r,function(t,e){if(e===r.length-1)return t||null;return t?decodeURIComponent(t):null})}});var N=e.History=function(){this.handlers=[];i.bindAll(this,"checkUrl");if(typeof window!=="undefined"){this.location=window.location;this.history=window.history}};var R=/^[#\/]|\s+$/g;var O=/^\/+|\/+$/g;var P=/msie [\w.]+/;var C=/\/$/;var j=/#.*$/;N.started=false;i.extend(N.prototype,u,{interval:50,atRoot:function(){return this.location.pathname.replace(/[^\/]$/,"$&/")===this.root},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:""},getFragment:function(t,e){if(t==null){if(this._hasPushState||!this._wantsHashChange||e){t=decodeURI(this.location.pathname+this.location.search);var i=this.root.replace(C,"");if(!t.indexOf(i))t=t.slice(i.length)}else{t=this.getHash()}}return t.replace(R,"")},start:function(t){if(N.started)throw new Error("Backbone.history has already been started");N.started=true;this.options=i.extend({root:"/"},this.options,t);this.root=this.options.root;this._wantsHashChange=this.options.hashChange!==false;this._wantsPushState=!!this.options.pushState;this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var r=this.getFragment();var s=document.documentMode;var n=P.exec(navigator.userAgent.toLowerCase())&&(!s||s<=7);this.root=("/"+this.root+"/").replace(O,"/");if(n&&this._wantsHashChange){var a=e.$('