├── src
├── SwaggerUIAsset.php
├── index.php
├── SwaggerApiAction.php
└── SwaggerAction.php
├── composer.json
├── LICENSE
├── README.md
└── README_ZH.md
/src/SwaggerUIAsset.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace light\swagger;
13 |
14 | use yii\web\AssetBundle;
15 |
16 | /**
17 | * Assets bundle for swagger-ui.
18 | */
19 | class SwaggerUIAsset extends AssetBundle
20 | {
21 | public $sourcePath = '@bower/swagger-ui/dist';
22 | public $baseUrl = '@web';
23 |
24 | public $js = [
25 | 'swagger-ui-bundle.js',
26 | 'swagger-ui-standalone-preset.js',
27 | ];
28 |
29 | public $css = [
30 | 'swagger-ui.css'
31 | ];
32 |
33 | public $depends = [];
34 | }
35 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "light/yii2-swagger",
3 | "description": "swagger intergation with yii2",
4 | "type": "library",
5 | "keywords": ["yii2","extension","swagger","Restful","document"],
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "lichunqiang",
10 | "email": "light-li@hotmail.com"
11 | }
12 | ],
13 | "require": {
14 | "yiisoft/yii2": "^2.0.0",
15 | "zircote/swagger-php": "^5.0",
16 | "bower-asset/swagger-ui": "^5.0"
17 | },
18 | "minimum-stability": "stable",
19 | "autoload": {
20 | "psr-4": {
21 | "light\\swagger\\": "src"
22 | }
23 | },
24 | "extra": {
25 | "branch-alias": {
26 | "dev-master": "2.0.x-dev"
27 | }
28 | },
29 | "config": {
30 | "process-timeout": 1800,
31 | "fxp-asset": {
32 | "enabled": false
33 | }
34 | },
35 | "repositories": [
36 | {
37 | "type": "composer",
38 | "url": "https://asset-packagist.org"
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 lichunqiang
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Yii2 Swagger Extension
6 |
7 |
8 |
9 | [](https://packagist.org/packages/light/yii2-swagger)
10 | [](https://packagist.org/packages/light/yii2-swagger)
11 | [](https://github.com/lichunqiang/yii2-swagger/issues)
12 |
13 | [swagger-php](https://github.com/zircote/swagger-php) integration with yii2.
14 |
15 |
16 | Integration [swagger-ui](https://github.com/swagger-api/swagger-ui) with [swagger-php](https://github.com/zircote/swagger-php).
17 |
18 |
19 | Installation
20 | ------------
21 |
22 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
23 |
24 | Either run
25 |
26 | ```
27 | php composer.phar require --prefer-dist light/yii2-swagger "~3.0" --dev
28 | ```
29 |
30 | or add
31 |
32 | ```
33 | "light/yii2-swagger": "~3.0"
34 | ```
35 |
36 | to the require section of your `composer.json` file.
37 |
38 |
39 | Usage
40 | -----
41 |
42 | Configure two action as below:
43 |
44 | ```
45 | public function actions()
46 | {
47 | return [
48 | //The document preview addesss:http://api.yourhost.com/site/doc
49 | 'doc' => [
50 | 'class' => 'light\swagger\SwaggerAction',
51 | 'restUrl' => \yii\helpers\Url::to(['/site/api'], true),
52 | ],
53 | //The resultUrl action.
54 | 'api' => [
55 | 'class' => 'light\swagger\SwaggerApiAction',
56 | //The scan directories, you should use real path there.
57 | 'scanDir' => [
58 | Yii::getAlias('@api/modules/v1/swagger'),
59 | Yii::getAlias('@api/modules/v1/controllers'),
60 | Yii::getAlias('@api/modules/v1/models'),
61 | Yii::getAlias('@api/models'),
62 | ],
63 | //The security key
64 | 'api_key' => 'balbalbal',
65 | ],
66 | ];
67 | }
68 | ```
69 |
70 | > For security, you can config api key for protection.
71 |
72 | Caching
73 | -------
74 |
75 | ```
76 | public function actions()
77 | {
78 | return [
79 | // ...
80 | 'api' => [
81 | // ...
82 | 'cache' => 'cache',
83 | 'cacheKey' => 'api-swagger-cache', // default is 'api-swagger-cache'
84 | ],
85 | ];
86 | }
87 | ```
88 |
89 | #### Clear cache
90 |
91 | Access clear cache url `YOUR_API_URL?clear-cache` or `YOUR_API_URL?api_key=YOUR_API_KEY&clear-cache`
92 |
93 | Example: `curl 'http://localhost/v1/swagger/api?clear-cache'`
94 |
95 | you will see: `Succeed clear swagger api cache.`
96 |
97 |
98 | Finally
99 | ----
100 | __If there also some confused, you can refer the [Demo](https://github.com/lichunqiang/yii2-swagger-demo).__
101 |
102 |
103 | License
104 | -------
105 | 
106 |
--------------------------------------------------------------------------------
/README_ZH.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Yii2 Swagger Extension
6 |
7 |
8 |
9 | [](https://packagist.org/packages/light/yii2-swagger)
10 | [](https://packagist.org/packages/light/yii2-swagger)
11 | [](https://github.com/lichunqiang/yii2-swagger/issues)
12 |
13 | [swagger-php](https://github.com/zircote/swagger-php) intergation with yii2.
14 |
15 | 写在前面
16 | --------
17 |
18 | * 这玩意是干什么的呢?
19 |
20 | 没啥黑科技,只是集成了[swagger-ui](https://github.com/swagger-api/swagger-ui)然后配合[swagger-php](https://github.com/zircote/swagger-php)扫描你的代码目录来生成在Restful文档.
21 |
22 |
23 | Installation
24 | ------------
25 |
26 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
27 |
28 | Either run
29 |
30 | ```
31 | php composer.phar require --prefer-dist light/yii2-swagger "~1.0.0" --dev
32 | ```
33 |
34 | or add
35 |
36 | ```
37 | "light/yii2-swagger": "~1.0.0"
38 | ```
39 |
40 | to the require section of your `composer.json` file.
41 |
42 |
43 | Usage
44 | -----
45 |
46 | 只要配置两个Action就可以了:
47 |
48 | ```
49 | public function actions()
50 | {
51 | return [
52 | //文档预览地址,配置好后可以直接访问:http://api.yourhost.com/site/doc
53 | 'doc' => [
54 | 'class' => 'light\swagger\SwaggerAction',
55 | 'restUrl' => \yii\helpers\Url::to(['/site/api'], true),
56 | ],
57 | //看到上面配置的*restUrl*了么,没错, 它就是指向这个地址
58 | 'api' => [
59 | 'class' => 'light\swagger\SwaggerApiAction',
60 | //这里配置需要扫描的目录,不支持yii的alias,所以需要这里直接获取到真实地址
61 | 'scanDir' => [
62 | Yii::getAlias('@api/modules/v1/swagger'),
63 | Yii::getAlias('@api/modules/v1/controllers'),
64 | Yii::getAlias('@api/modules/v1/models'),
65 | Yii::getAlias('@api/models'),
66 | ],
67 | //这个下面讲
68 | 'api_key' => 'balbalbal',
69 | ],
70 | ];
71 | }
72 | ```
73 |
74 | `api_key` 是文档浏览key,文档放到线上,我们并不需要让每个人都能看到,所以可以通过设置这项来实现。配置后浏览文档时需要在右上角的`api_key`输入框中输入配置的值,才能正常访问文档.
75 |
76 | > 默认情况下,没有配置的话,可以直接浏览文档
77 |
78 |
79 | **靠!写了这么多我自己都乱了!怎么用??**
80 |
81 | 别担心, **Talk is cheap, show me the code**.
82 |
83 |
84 | 上[Demo](https://github.com/lichunqiang/yii2-swagger-demo)
85 |
86 |
87 | Caching
88 | -------
89 |
90 | ```
91 | public function actions()
92 | {
93 | return [
94 | // ...
95 | 'api' => [
96 | // ...
97 | 'cache' => 'cache',
98 | 'cacheKey' => 'api-swagger-cache', // default is 'api-swagger-cache'
99 | ],
100 | ];
101 | }
102 | ```
103 |
104 | #### Clear cache
105 |
106 | Access clear cache url `YOUR_API_URL?clear-cache` or `YOUR_API_URL?api_key=YOUR_API_KEY&clear-cache`
107 |
108 | Example: `curl 'http://localhost/v1/swagger/api?clear-cache'`
109 |
110 | you will see: `Succeed clear swagger api cache.`
111 |
112 | License
113 | -------
114 | 
115 |
--------------------------------------------------------------------------------
/src/index.php:
--------------------------------------------------------------------------------
1 |
14 | beginPage() ?>
15 |
16 |
17 |
18 |
19 | = $title ?>
20 |
21 |
22 |
23 |
42 | head() ?>
43 |
44 |
45 |
46 | beginBody() ?>
47 |
80 |
81 |
82 | endBody() ?>
83 | registerJs(<<
94 |
95 |
96 |
97 | endPage() ?>
98 |
--------------------------------------------------------------------------------
/src/SwaggerApiAction.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace light\swagger;
13 |
14 | use OpenApi\Generator;
15 | use OpenApi\Util;
16 | use Symfony\Component\Finder\Finder;
17 | use Yii;
18 | use yii\base\Action;
19 | use yii\base\ExitException;
20 | use yii\base\InvalidConfigException;
21 | use yii\caching\Cache;
22 | use yii\caching\CacheInterface;
23 | use yii\di\Instance;
24 | use yii\helpers\ArrayHelper;
25 | use yii\web\Response;
26 |
27 | /**
28 | * The api data output action.
29 | *
30 | * ~~~
31 | * public function actions()
32 | * {
33 | * return [
34 | * 'api' => [
35 | * 'class' => 'light\swagger\SwaggerApiAction',
36 | * 'scanDir' => [
37 | * Yii::getAlias('@api/modules/v1/swagger'),
38 | * Yii::getAlias('@api/modules/v1/controllers'),
39 | * ...
40 | * ]
41 | * ]
42 | * ];
43 | * }
44 | * ~~~
45 | */
46 | class SwaggerApiAction extends Action
47 | {
48 | /**
49 | * @var string|array|Finder The directory(s) or filename(s).
50 | * If you configured the directory must be full path of the directory.
51 | */
52 | public $scanDir;
53 | /**
54 | * @var string api key, if configured will perform the authentication.
55 | * @deprecated
56 | */
57 | public $api_key;
58 | /**
59 | * @var string The `apiKey` name specified.
60 | */
61 | public $apiKeyParam = 'api_key';
62 | /**
63 | * @var array The options passed to `Swagger`, Please refer the `Swagger\scan` function for more information.
64 | */
65 | public $scanOptions = [];
66 | /**
67 | * @var Cache|string|null the cache object or the ID of the cache application component that is used to store
68 | * Cache the \Swagger\Scan
69 | */
70 | public $cache = 'cache';
71 | /**
72 | * @var bool If enable caching the scan result.
73 | * @since 2.0.0
74 | */
75 | public $enableCache = false;
76 | /**
77 | * @var string Cache key
78 | * [[cache]] must not be null
79 | */
80 | public $cacheKey = 'api-swagger-cache';
81 |
82 | /**
83 | * @throws InvalidConfigException
84 | */
85 | public function init()
86 | {
87 | $this->cache = Instance::ensure($this->cache, CacheInterface::class);
88 |
89 | $this->initCors();
90 | }
91 |
92 | /**
93 | * @inheritdoc
94 | *
95 | * @throws ExitException
96 | * @throws InvalidConfigException
97 | */
98 | public function run()
99 | {
100 | Yii::$app->response->format = Response::FORMAT_JSON;
101 |
102 | $this->clearCache();
103 |
104 | if ($this->enableCache) {
105 | if (($swagger = $this->cache->get($this->cacheKey)) === false) {
106 | $swagger = $this->getSwagger();
107 | $this->cache->set($this->cacheKey, $swagger);
108 | }
109 | } else {
110 | $swagger = $this->getSwagger();
111 | }
112 |
113 | return $swagger;
114 | }
115 |
116 | /**
117 | * Init cors.
118 | */
119 | protected function initCors()
120 | {
121 | $headers = Yii::$app->getResponse()->getHeaders();
122 |
123 | $headers->set('Access-Control-Allow-Headers', implode(', ', [
124 | 'Content-Type',
125 | $this->apiKeyParam,
126 | 'Authorization',
127 | ]));
128 | $headers->set('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT');
129 | $headers->set('Access-Control-Allow-Origin', '*');
130 | }
131 |
132 | /**
133 | *
134 | * @throws ExitException
135 | */
136 | protected function clearCache()
137 | {
138 | $clearCache = Yii::$app->getRequest()->get('clear-cache', false);
139 | if ($clearCache !== false) {
140 | $this->cache->delete($this->cacheKey);
141 |
142 | Yii::$app->response->content = 'Succeed clear swagger api cache.';
143 | Yii::$app->end();
144 | }
145 | }
146 |
147 | /**
148 | * Get swagger object
149 | *
150 | * @return OpenApi
151 | */
152 | protected function getSwagger()
153 | {
154 | $exclude = ArrayHelper::getValue($this->scanOptions, 'exclude');
155 | $pattern = ArrayHelper::getValue($this->scanOptions, 'pattern');
156 | return Generator::scan(Util::finder($this->scanDir, $exclude, $pattern), $this->scanOptions);
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/SwaggerAction.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * This source file is subject to the MIT license that is bundled
9 | * with this source code in the file LICENSE.
10 | */
11 |
12 | namespace light\swagger;
13 |
14 | use Yii;
15 | use yii\base\Action;
16 | use yii\base\InvalidArgumentException;
17 | use yii\helpers\Json;
18 | use yii\web\JsExpression;
19 | use yii\web\Response;
20 |
21 | /**
22 | * The document display action.
23 | *
24 | * To use url property
25 | * ~~~
26 | * public function actions()
27 | * {
28 | * return [
29 | * 'doc' => [
30 | * 'class' => 'light\swagger\SwaggerAction',
31 | * 'restUrl' => Url::to(['site/api'], true)
32 | * 'additionalAsset' => 'app\modules\api\assets\SwaggerUIAssetOverrides',
33 | * ]
34 | * ];
35 | * }
36 | *
37 | * To use urls property
38 | *
39 | * public function actions()
40 | * {
41 | * return [
42 | * 'doc' => [
43 | * 'class' => 'light\swagger\SwaggerAction',
44 | * 'restUrl' => [
45 | * [
46 | * 'name' => 'API V1',
47 | * 'url' => Url::to(['/site/api-v1'], true),
48 | * ],
49 | * [
50 | * 'name' => 'API V2',
51 | * 'url' => Url::to(['/site/api-v2'], true),
52 | * ],
53 | * ],
54 | * 'additionalAsset' => 'app\modules\api\assets\SwaggerUIAssetOverrides',
55 | * ]
56 | * ];
57 | * }
58 | * ~~~
59 | */
60 | class SwaggerAction extends Action
61 | {
62 | /**
63 | * @var string|array The rest url configuration.
64 | * Check documentation for more information.
65 | * @see https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md
66 | */
67 | public $restUrl;
68 | /**
69 | * @var array The OAuth configuration.
70 | */
71 | public $oauthConfiguration = [];
72 | /**
73 | * @var string The customer asset bundle.
74 | * @since 2.0.0
75 | */
76 | public $additionalAsset;
77 | /**
78 | * @var string
79 | * @since 2.0.0
80 | */
81 | public $title = 'Swagger-ui';
82 | /**
83 | * @var array The swagger-ui component configurations.
84 | * @see https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md
85 | * @since 2.0.0
86 | */
87 | public $configurations = [];
88 | /**
89 | * @var array Default swagger-ui configurations.
90 | * @since 2.0.0
91 | */
92 | protected $defaultConfigurations = [
93 | 'dom_id' => '#swagger-ui',
94 | 'deepLinking' => true,
95 | 'presets' => [
96 | 'SwaggerUIBundle.presets.apis',
97 | 'SwaggerUIStandalonePreset',
98 | ],
99 | 'plugins' => [
100 | 'SwaggerUIBundle.plugins.DownloadUrl',
101 | 'SwaggerUIBundle.plugins.Topbar',
102 | ],
103 | 'layout' => 'StandaloneLayout',
104 | 'validatorUrl' => null,
105 | ];
106 |
107 | /**
108 | * @inheritdoc
109 | */
110 | public function run()
111 | {
112 | Yii::$app->getResponse()->format = Response::FORMAT_HTML;
113 |
114 | $this->controller->layout = false;
115 |
116 | $view = $this->controller->getView();
117 |
118 | return $view->renderFile(__DIR__ . '/index.php', [
119 | 'configurations' => $this->prepareConfiguration(),
120 | 'oauthConfiguration' => $this->oauthConfiguration,
121 | 'title' => $this->title,
122 | ], $this->controller);
123 | }
124 |
125 | /**
126 | * @return string
127 | */
128 | protected function prepareConfiguration()
129 | {
130 | $configurations = array_merge($this->defaultConfigurations, $this->configurations);
131 |
132 | if ($this->restUrl) {
133 | $configurations[is_array($this->restUrl) ? 'urls' : 'url'] = $this->restUrl;
134 | }
135 |
136 | if (isset($configurations['plugins'])) {
137 | $configurations['plugins'] = array_map(
138 | [$this, 'convertJsExpression'],
139 | (array)$configurations['plugins']
140 | );
141 | }
142 |
143 | if (isset($configurations['presets'])) {
144 | $configurations['presets'] = array_map(
145 | [$this, 'convertJsExpression'],
146 | (array)$configurations['presets']
147 | );
148 | }
149 |
150 | return Json::encode($configurations);
151 | }
152 |
153 | /**
154 | * @param string $str
155 | *
156 | * @return JsExpression
157 | */
158 | protected function convertJsExpression($str)
159 | {
160 | return new JsExpression($str);
161 | }
162 |
163 | /**
164 | * @inheritdoc
165 | */
166 | protected function beforeRun()
167 | {
168 | if ($this->additionalAsset != null) {
169 | $additionalAsset = $this->additionalAsset;
170 | if (class_exists($additionalAsset) and method_exists($additionalAsset, 'register')) {
171 | $additionalAsset::register($this->controller->getView());
172 | } else {
173 | throw new InvalidArgumentException('Not valid class');
174 | }
175 | }
176 |
177 | return parent::beforeRun();
178 | }
179 | }
180 |
--------------------------------------------------------------------------------