Skip to content

Commit

Permalink
Add option to generate YAML documentation file as a copy (#150)
Browse files Browse the repository at this point in the history
* Add option to generate YAML documentation file as a copy

* refactoring
  • Loading branch information
DarkaOnLine authored Jun 21, 2018
1 parent b079614 commit ae29726
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 43 deletions.
5 changes: 3 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
"php": ">=7.1.3",
"laravel/framework": "5.6.*",
"zircote/swagger-php": "~2.0|3.*",
"swagger-api/swagger-ui": "^3.0"
"swagger-api/swagger-ui": "^3.0",
"symfony/yaml": "^4.1"
},
"require-dev": {
"phpunit/phpunit": "7.*",
"mockery/mockery": "1.*",
"orchestra/testbench": "3.6.*",
"satooshi/php-coveralls": "^2.0"
"php-coveralls/php-coveralls": "^2.0"
},
"autoload": {
"psr-4": {
Expand Down
16 changes: 16 additions & 0 deletions config/l5-swagger.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@

'docs_json' => 'api-docs.json',

/*
|--------------------------------------------------------------------------
| File name of the generated YAML documentation file
|--------------------------------------------------------------------------
*/

'docs_yaml' => 'api-docs.yaml',

/*
|--------------------------------------------------------------------------
| Absolute path to directory containing the swagger annotations are stored.
Expand Down Expand Up @@ -156,6 +164,14 @@

'generate_always' => env('L5_SWAGGER_GENERATE_ALWAYS', false),

/*
|--------------------------------------------------------------------------
| Turn this on to generate a copy of documentation in yaml format
|--------------------------------------------------------------------------
*/

'generate_yaml_copy' => env('L5_SWAGGER_GENERATE_YAML_COPY', false),

/*
|--------------------------------------------------------------------------
| Edit to set the swagger version number
Expand Down
8 changes: 2 additions & 6 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnFailure="false"
syntaxCheck="true">
stopOnFailure="false">
<testsuite name="L5-Swagger TestSuite">
<directory>tests/</directory>
</testsuite>
Expand All @@ -15,11 +14,8 @@
</whitelist>
</filter>
<logging>
<log type="coverage-html" target="tests/storage/logs/test-reports" charset="UTF-8"
yui="true" highlight="true"
lowUpperBound="50" highLowerBound="80" />
<log type="coverage-html" target="tests/storage/logs/test-reports" lowUpperBound="50" highLowerBound="80" />
<log type="coverage-clover" target="tests/storage/logs/test-reports/clover.xml"/>
<log type="junit" target="tests/storage/logs/test-reports/junit.xml" logIncompleteSkipped="false"/>
</logging>
<php>
<env name="APP_KEY" value="AckfSECXIvnK5r28GVIWUAxmbBSjTsmF"/>
Expand Down
179 changes: 149 additions & 30 deletions src/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,183 @@
namespace L5Swagger;

use File;
use Config;
use L5Swagger\Exceptions\L5SwaggerException;
use Symfony\Component\Yaml\Dumper as YamlDumper;

class Generator
{
/**
* @var string
*/
protected $appDir;

/**
* @var string
*/
protected $docDir;

/**
* @var string
*/
protected $docsFile;

/**
* @var string
*/
protected $yamlDocsFile;

/**
* @var array
*/
protected $excludedDirs;

/**
* @var array
*/
protected $constants;

/**
* @var \Swagger\Annotations\Swagger
*/
protected $swagger;

/**
* @var bool
*/
protected $yamlCopyRequired;

public function __construct()
{
$this->appDir = config('l5-swagger.paths.annotations');
$this->docDir = config('l5-swagger.paths.docs');
$this->docsFile = $this->docDir.'/'.config('l5-swagger.paths.docs_json', 'api-docs.json');
$this->yamlDocsFile = $this->docDir.'/'.config('l5-swagger.paths.docs_yaml', 'api-docs.yaml');
$this->excludedDirs = config('l5-swagger.paths.excludes');
$this->constants = config('l5-swagger.constants') ?: [];
$this->yamlCopyRequired = config('l5-swagger.generate_yaml_copy', false);
}

public static function generateDocs()
{
$appDir = config('l5-swagger.paths.annotations');
$docDir = config('l5-swagger.paths.docs');
if (! File::exists($docDir) || is_writable($docDir)) {
// delete all existing documentation
if (File::exists($docDir)) {
File::deleteDirectory($docDir);
}
(new static)->prepareDirectory()
->defineConstants()
->scanFilesForDocumentation()
->populateServers()
->saveJson()
->makeYamlCopy();
}

self::defineConstants(config('l5-swagger.constants') ?: []);
/**
* Check directory structure and permissions.
*
* @return Generator
*/
protected function prepareDirectory()
{
if (File::exists($this->docDir) && ! is_writable($this->docDir)) {
throw new L5SwaggerException('Documentation storage directory is not writable');
}

File::makeDirectory($docDir);
$excludeDirs = config('l5-swagger.paths.excludes');
$swagger = \Swagger\scan($appDir, ['exclude' => $excludeDirs]);
// delete all existing documentation
if (File::exists($this->docDir)) {
File::deleteDirectory($this->docDir);
}

self::generateServers($swagger);
File::makeDirectory($this->docDir);

$filename = $docDir.'/'.config('l5-swagger.paths.docs_json', 'api-docs.json');
$swagger->saveAs($filename);
return $this;
}

$security = new SecurityDefinitions();
$security->generate($filename);
/**
* Define constant which will be replaced.
*
* @return Generator
*/
protected function defineConstants()
{
if (! empty($this->constants)) {
foreach ($this->constants as $key => $value) {
defined($key) || define($key, $value);
}
}

return $this;
}

/**
* Scan directory and create Swagger.
*
* @return Generator
*/
protected function scanFilesForDocumentation()
{
$this->swagger = \Swagger\scan(
$this->appDir,
['exclude' => $this->excludedDirs]
);

return $this;
}

/**
* Generate servers section or basePath depending on Swagger version.
*
* @param \Swagger\Annotations\OpenApi $swagger Swagger/OpenAPI instance
* @return Generator
*/
protected static function generateServers($swagger)
protected function populateServers()
{
if (config('l5-swagger.paths.base') !== null) {
$isVersion3 = version_compare(config('l5-swagger.swagger_version'), '3.0', '>=');

if ($isVersion3) {
$swagger->servers = [
if ($this->isOpenApi()) {
$this->swagger->servers = [
new \Swagger\Annotations\Server(['url' => config('l5-swagger.paths.base')]),
];
}

if (! $isVersion3) {
$swagger->basePath = config('l5-swagger.paths.base');
if (! $this->isOpenApi()) {
$this->swagger->basePath = config('l5-swagger.paths.base');
}
}

return $this;
}

protected static function defineConstants(array $constants)
/**
* Save documentation as json file.
*
* @return Generator
*/
protected function saveJson()
{
if (! empty($constants)) {
foreach ($constants as $key => $value) {
defined($key) || define($key, $value);
}
$this->swagger->saveAs($this->docsFile);

$security = new SecurityDefinitions();
$security->generate($this->docsFile);

return $this;
}

/**
* Save documentation as yaml file.
*
* @return Generator
*/
protected function makeYamlCopy()
{
if ($this->yamlCopyRequired) {
file_put_contents(
$this->yamlDocsFile,
(new YamlDumper(2))->dump(json_decode(file_get_contents($this->docsFile), true), 20)
);
}
}

/**
* Check which documentation version is used.
*
* @return bool
*/
protected function isOpenApi()
{
return version_compare(config('l5-swagger.swagger_version'), '3.0', '>=');
}
}
10 changes: 5 additions & 5 deletions src/Http/Controllers/SwaggerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ public function api()
// Need the / at the end to avoid CORS errors on Homestead systems.
$response = Response::make(
view('l5-swagger::index', [
'secure' => Request::secure(),
'urlToDocs' => route('l5-swagger.docs', config('l5-swagger.paths.docs_json', 'api-docs.json')),
'operationsSorter' => config('l5-swagger.operations_sort'),
'configUrl' => config('l5-swagger.additional_config_url'),
'validatorUrl' => config('l5-swagger.validator_url'),
'secure' => Request::secure(),
'urlToDocs' => route('l5-swagger.docs', config('l5-swagger.paths.docs_json', 'api-docs.json')),
'operationsSorter' => config('l5-swagger.operations_sort'),
'configUrl' => config('l5-swagger.additional_config_url'),
'validatorUrl' => config('l5-swagger.validator_url'),
]),
200
);
Expand Down
38 changes: 38 additions & 0 deletions tests/GeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,25 @@
namespace Tests;

use L5Swagger\Generator;
use L5Swagger\Exceptions\L5SwaggerException;

class GeneratorTest extends TestCase
{
/** @test **/
public function itThrowsExceptionIfDocumatationDirIsNotWritable()
{
$this->setAnnotationsPath();

mkdir(config('l5-swagger.paths.docs'), 0555);
chmod(config('l5-swagger.paths.docs'), 0555);

$this->expectException(L5SwaggerException::class);

Generator::generateDocs();

chmod(config('l5-swagger.paths.docs'), 0777);
}

/** @test */
public function canGenerateApiJsonFile()
{
Expand All @@ -14,11 +30,17 @@ public function canGenerateApiJsonFile()
Generator::generateDocs();

$this->assertTrue(file_exists($this->jsonDocsFile()));
$this->assertTrue(file_exists($this->yamlDocsFile()));

$this->get(route('l5-swagger.docs'))
->assertSee('L5 Swagger')
->assertSee('my-default-host.com')
->isOk();

$this->get(route('l5-swagger.docs', ['jsonFile' => config('l5-swagger.paths.docs_yaml')]))
->assertSee('L5 Swagger')
->assertSee('my-default-host.com')
->isOk();
}

/** @test */
Expand All @@ -42,6 +64,11 @@ public function canGenerateApiJsonFileWithChangedBasePath()
->assertSee('L5 Swagger')
->assertSee('new_path')
->isOk();

$this->get(route('l5-swagger.docs', ['jsonFile' => config('l5-swagger.paths.docs_yaml')]))
->assertSee('L5 Swagger')
->assertSee('new_path')
->isOk();
}

/** @test */
Expand All @@ -66,6 +93,11 @@ public function canGenerateApiJsonFileWithChangedBaseServer()
->assertSee('https://test-server.url')
->assertDontSee('basePath')
->isOk();

$this->get(route('l5-swagger.docs', ['jsonFile' => config('l5-swagger.paths.docs_yaml')]))
->assertSee('https://test-server.url')
->assertDontSee('basePath')
->isOk();
}

/** @test */
Expand All @@ -81,6 +113,7 @@ public function canSetProxy()
->isOk();

$this->assertTrue(file_exists($this->jsonDocsFile()));
$this->assertTrue(file_exists($this->yamlDocsFile()));
}

/** @test */
Expand All @@ -96,6 +129,11 @@ public function canSetValidatorUrl()
->assertSee('validator-url.dev')
->isOk();

$this->get(route('l5-swagger.api', ['jsonFile' => config('l5-swagger.paths.docs_yaml')]))
->assertSee('validator-url.dev')
->isOk();

$this->assertTrue(file_exists($this->jsonDocsFile()));
$this->assertTrue(file_exists($this->yamlDocsFile()));
}
}
Loading

0 comments on commit ae29726

Please sign in to comment.