From 54fe1c97a27178cca954d62b2a7a8f3ad02b3ad5 Mon Sep 17 00:00:00 2001 From: lichunqiang Date: Fri, 30 Mar 2018 23:41:30 +0800 Subject: [PATCH] implementation with swagger-ui3.0 --- src/SwaggerAction.php | 116 +++++++++--- src/SwaggerApiAction.php | 308 +++++++++++++++----------------- src/SwaggerUIAsset.php | 3 + src/SwaggerUIAssetOverrides.php | 26 --- src/index.php | 205 ++++++++++----------- 5 files changed, 337 insertions(+), 321 deletions(-) delete mode 100644 src/SwaggerUIAssetOverrides.php diff --git a/src/SwaggerAction.php b/src/SwaggerAction.php index ac2a4fa..a8ad6f1 100644 --- a/src/SwaggerAction.php +++ b/src/SwaggerAction.php @@ -14,7 +14,9 @@ use Yii; use yii\base\Action; use yii\base\InvalidArgumentException; +use yii\helpers\Json; use yii\web\AssetBundle; +use yii\web\JsExpression; use yii\web\Response; /** @@ -61,52 +63,118 @@ class SwaggerAction extends Action /** * @var string|array The rest url configuration. * Check documentation for more information. - * @doc https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md + * @see https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md */ public $restUrl; /** - * @var array The OAuth configration + * @var array The OAuth configuration. */ public $oauthConfiguration = []; - + /** + * @var string The customer asset bundle. + * @since 2.0.0 + */ public $additionalAsset; - + /** + * @var string + * @since 2.0.0 + */ + public $title = 'Swagger-ui'; + /** + * @var array The swagger-ui component configurations. + * @see https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/configuration.md + * @since 2.0.0 + */ + public $configurations = []; + /** + * @var array Default swagger-ui configurations. + * @since 2.0.0 + */ + protected $defaultConfigurations = [ + 'dom_id' => '#swagger-ui', + 'deepLinking' => true, + 'presets' => [ + 'SwaggerUIBundle.presets.apis', + 'SwaggerUIStandalonePreset', + ], + 'plugins' => [ + 'SwaggerUIBundle.plugins.DownloadUrl', + 'SwaggerUIBundle.plugins.Topbar', + ], + 'layout' => 'StandaloneLayout', + 'validatorUrl' => null, + ]; + + /** + * @inheritdoc + */ public function run() { Yii::$app->getResponse()->format = Response::FORMAT_HTML; - + $this->controller->layout = false; - + $view = $this->controller->getView(); - - if (empty($this->oauthConfiguration)) { - $this->oauthConfiguration = [ - 'clientId' => 'your-client-id', - 'clientSecret' => 'your-client-secret-if-required', - 'realm' => 'your-realms', - 'appName' => 'your-app-name', - 'scopeSeparator' => ' ', - 'additionalQueryStringParams' => [], - ]; - } - + return $view->renderFile(__DIR__ . '/index.php', [ - 'rest_url' => $this->restUrl, - 'oauthConfig' => $this->oauthConfiguration, + 'configurations' => $this->prepareConfiguration(), + 'oauthConfiguration' => $this->oauthConfiguration, + 'title' => $this->title, ], $this->controller); } - + + /** + * @return string + */ + protected function prepareConfiguration() + { + $configurations = array_merge($this->defaultConfigurations, $this->configurations); + + if ($this->restUrl) { + $configurations[is_array($this->restUrl) ? 'urls' : 'url'] = $this->restUrl; + } + + if (isset($configurations['plugins'])) { + $configurations['plugins'] = array_map( + [$this, 'convertJsExpression'], + (array)$configurations['plugins'] + ); + } + + if (isset($configurations['presets'])) { + $configurations['presets'] = array_map( + [$this, 'convertJsExpression'], + (array)$configurations['presets'] + ); + } + + return Json::encode($configurations); + } + + /** + * @param string $str + * + * @return JsExpression + */ + protected function convertJsExpression($str) + { + return new JsExpression($str); + } + + /** + * @inheritdoc + */ protected function beforeRun() { if ($this->additionalAsset != null) { $additionalAsset = $this->additionalAsset; if (class_exists($additionalAsset)) { - $additionalAsset::register($this->controller->view); + $additionalAsset::register($this->controller->getView()); } else { - throw new InvalidArgumentException("Not valid class"); + throw new InvalidArgumentException('Not valid class'); } } - + return parent::beforeRun(); } } diff --git a/src/SwaggerApiAction.php b/src/SwaggerApiAction.php index 4138096..9206a3e 100644 --- a/src/SwaggerApiAction.php +++ b/src/SwaggerApiAction.php @@ -1,160 +1,148 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace light\swagger; - -use Yii; -use yii\base\Action; -use yii\caching\Cache; -use yii\web\Response; - -/** - * The api data output action. - * - * ~~~ - * public function actions() - * { - * return [ - * 'api' => [ - * 'class' => 'light\swagger\SwaggerApiAction', - * 'scanDir' => [ - * Yii::getAlias('@api/modules/v1/swagger'), - * Yii::getAlias('@api/modules/v1/controllers'), - * ... - * ] - * ] - * ]; - * } - * ~~~ - */ -class SwaggerApiAction extends Action -{ - /** - * @var string|array|\Symfony\Component\Finder\Finder The directory(s) or filename(s). - * If you configured the directory must be full path of the directory. - */ - public $scanDir; - /** - * @var string api key, if configured will perform the authentication. - */ - public $api_key; - /** - * @var string Query param to get api key. - */ - public $apiKeyParam = 'api_key'; - /** - * @var array The options passed to `Swagger`, Please refer the `Swagger\scan` function for more information. - */ - public $scanOptions = []; - /** - * @var Cache|string|null the cache object or the ID of the cache application component that is used to store - * Cache the \Swagger\Scan - */ - public $cache = null; - /** - * @var string Cache key - * [[cache]] must not be null - */ - public $cacheKey = 'api-swagger-cache'; - - /** - * @inheritdoc - */ - public function run() - { - $this->initCors(); - - Yii::$app->response->format = Response::FORMAT_JSON; - - $headers = Yii::$app->getRequest()->getHeaders(); - $requestApiKey = $headers->get($this->apiKeyParam, Yii::$app->getRequest()->get($this->apiKeyParam)); - - if (null !== $this->api_key - && $this->api_key != $requestApiKey - ) { - return $this->getNeedAuthResponse(); - } - - $this->clearCache(); - - if ($this->cache !== null) { - $cache = $this->getCache(); - if (($swagger = $cache->get($this->cacheKey)) === false) { - $swagger = $this->getSwagger(); - $cache->set($this->cacheKey, $swagger); - } - } else { - $swagger = $this->getSwagger(); - } - - return $swagger; - } - - /** - * Init cors. - */ - protected function initCors() - { - $headers = Yii::$app->getResponse()->getHeaders(); - - $headers->set('Access-Control-Allow-Headers', 'Content-Type, api_key, Authorization'); - $headers->set('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT'); - $headers->set('Access-Control-Allow-Origin', '*'); - $headers->set('Allow', 'OPTIONS,HEAD,GET'); - } - - /** - * @return array - */ - protected function getNeedAuthResponse() - { - return [ - 'securityDefinitions' => [ - 'api_key' => ['in' => 'header', 'type' => 'apiKey', 'name' => $this->apiKeyParam], - ], - 'swagger' => '2.0', - 'schemes' => ['http'], - 'info' => [ - 'title' => 'Please take authentication firstly.', - ], - ]; - } - - protected function clearCache() - { - $clearCache = Yii::$app->getRequest()->get('clear-cache', false); - if ($clearCache !== false) { - $this->getCache()->delete($this->cacheKey); - - Yii::$app->response->content = 'Succeed clear swagger api cache.'; - Yii::$app->end(); - } - } - - /** - * @return Cache - * @throws \yii\base\InvalidConfigException - */ - protected function getCache() - { - return is_string($this->cache) ? Yii::$app->get($this->cache, false) : $this->cache; - } - - /** - * Get swagger object - * - * @return \Swagger\Annotations\Swagger - */ - protected function getSwagger() - { - return \Swagger\scan($this->scanDir, $this->scanOptions); - } -} + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace light\swagger; + +use Yii; +use yii\base\Action; +use yii\caching\Cache; +use yii\caching\CacheInterface; +use yii\di\Instance; +use yii\web\Response; + +/** + * The api data output action. + * + * ~~~ + * public function actions() + * { + * return [ + * 'api' => [ + * 'class' => 'light\swagger\SwaggerApiAction', + * 'scanDir' => [ + * Yii::getAlias('@api/modules/v1/swagger'), + * Yii::getAlias('@api/modules/v1/controllers'), + * ... + * ] + * ] + * ]; + * } + * ~~~ + */ +class SwaggerApiAction extends Action +{ + /** + * @var string|array|\Symfony\Component\Finder\Finder The directory(s) or filename(s). + * If you configured the directory must be full path of the directory. + */ + public $scanDir; + /** + * @var string api key, if configured will perform the authentication. + * @deprecated + */ + public $api_key; + /** + * @var string The `apiKey` name specified. + */ + public $apiKeyParam = 'api_key'; + /** + * @var array The options passed to `Swagger`, Please refer the `Swagger\scan` function for more information. + */ + public $scanOptions = []; + /** + * @var Cache|string|null the cache object or the ID of the cache application component that is used to store + * Cache the \Swagger\Scan + */ + public $cache = 'cache'; + /** + * @var bool If enable caching the scan result. + * @since 2.0.0 + */ + public $enableCache = false; + /** + * @var string Cache key + * [[cache]] must not be null + */ + public $cacheKey = 'api-swagger-cache'; + + /** + * @throws \yii\base\InvalidConfigException + */ + public function init() + { + $this->cache = Instance::ensure($this->cache, CacheInterface::class); + + $this->initCors(); + } + + /** + * @inheritdoc + */ + public function run() + { + Yii::$app->response->format = Response::FORMAT_JSON; + + $this->clearCache(); + + if ($this->enableCache) { + if (($swagger = $this->cache->get($this->cacheKey)) === false) { + $swagger = $this->getSwagger(); + $this->cache->set($this->cacheKey, $swagger); + } + } else { + $swagger = $this->getSwagger(); + } + + return $swagger; + } + + /** + * Init cors. + */ + protected function initCors() + { + $headers = Yii::$app->getResponse()->getHeaders(); + + $headers->set('Access-Control-Allow-Headers', implode(', ', [ + 'Content-Type', + $this->apiKeyParam, + 'Authorization', + ])); + $headers->set('Access-Control-Allow-Methods', 'GET, POST, DELETE, PUT'); + $headers->set('Access-Control-Allow-Origin', '*'); + } + + /**s + * + * @throws \yii\base\InvalidConfigException + * @throws \yii\base\ExitException + */ + protected function clearCache() + { + $clearCache = Yii::$app->getRequest()->get('clear-cache', false); + if ($clearCache !== false) { + $this->cache->delete($this->cacheKey); + + Yii::$app->response->content = 'Succeed clear swagger api cache.'; + Yii::$app->end(); + } + } + + /** + * Get swagger object + * + * @return \Swagger\Annotations\Swagger + */ + protected function getSwagger() + { + return \Swagger\scan($this->scanDir, $this->scanOptions); + } +} diff --git a/src/SwaggerUIAsset.php b/src/SwaggerUIAsset.php index a6069bc..212b8a7 100644 --- a/src/SwaggerUIAsset.php +++ b/src/SwaggerUIAsset.php @@ -14,6 +14,9 @@ use yii\web\AssetBundle; use yii\web\View; +/** + * Assets bundle for swagger-ui. + */ class SwaggerUIAsset extends AssetBundle { public $sourcePath = '@bower/swagger-ui/dist'; diff --git a/src/SwaggerUIAssetOverrides.php b/src/SwaggerUIAssetOverrides.php deleted file mode 100644 index 4e7022b..0000000 --- a/src/SwaggerUIAssetOverrides.php +++ /dev/null @@ -1,26 +0,0 @@ - -beginPage() ?> - - - - - Swagger UI - - - - - head() ?> - - - -beginBody() ?> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-endBody() ?> - - - - -endPage() ?> \ No newline at end of file + +beginPage() ?> + + + + + <?= $title ?> + + + + + head() ?> + + + +beginBody() ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+endBody() ?> + + + + +endPage() ?>