Skip to content

Commit 01b0fdc

Browse files
JasonBenettJason Benedetti
and
Jason Benedetti
authored
feat: fully regenerate src directory during client generation (#65)
* feat: fully regenerate src directory during client generation * fix: codestyle * fix: phpstan issue * doc: update changelog Co-authored-by: Jason Benedetti <[email protected]>
1 parent 2a4aa09 commit 01b0fdc

File tree

7 files changed

+253
-5
lines changed

7 files changed

+253
-5
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [9.0.0] - 2022.02.24
8+
### Changed
9+
- API Client Generation triggers a full regeneration of src folder.
10+
711
## [8.1.0] - 2021-12-15
812
### Added
913
- Basic Authentication strategy added

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
},
3636
"require-dev": {
3737
"composer/composer": "^2.1",
38+
"mikey179/vfsstream": "^1.6",
3839
"php-coveralls/php-coveralls": "^2.2",
3940
"phpstan/phpstan": "^0.12.32",
4041
"phpunit/phpunit": "^9.2",

composer.lock

+52-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Command/GenerateCommand.php

+67-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\JsonContentTypeSerializer;
1717
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\VdnApiJsonContentTypeSerializer;
1818
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\XmlContentTypeSerializer;
19+
use DoclerLabs\ApiClientGenerator\Output\DirectoryPrinter;
1920
use DoclerLabs\ApiClientGenerator\Output\Meta\MetaFileCollection;
2021
use DoclerLabs\ApiClientGenerator\Output\MetaFilePrinter;
2122
use DoclerLabs\ApiClientGenerator\Output\Php\PhpFileCollection;
@@ -30,6 +31,7 @@
3031
use Symfony\Component\Console\Style\SymfonyStyle;
3132
use Symfony\Component\Filesystem\Filesystem;
3233
use Symfony\Component\Finder\Finder;
34+
use Throwable;
3335

3436
class GenerateCommand extends Command
3537
{
@@ -38,6 +40,7 @@ class GenerateCommand extends Command
3840
private FileReader $fileReader;
3941
private Parser $parser;
4042
private PhpFilePrinter $phpPrinter;
43+
private DirectoryPrinter $directoryPrinter;
4144
private MetaTemplateFacade $metaTemplate;
4245
private MetaFilePrinter $templatePrinter;
4346
private Finder $fileFinder;
@@ -51,6 +54,7 @@ public function __construct(
5154
Parser $parser,
5255
CodeGeneratorFacade $codeGenerator,
5356
PhpFilePrinter $phpPrinter,
57+
DirectoryPrinter $directoryPrinter,
5458
MetaTemplateFacade $metaTemplate,
5559
MetaFilePrinter $templatePrinter,
5660
Finder $fileFinder,
@@ -64,6 +68,7 @@ public function __construct(
6468
$this->parser = $parser;
6569
$this->codeGenerator = $codeGenerator;
6670
$this->phpPrinter = $phpPrinter;
71+
$this->directoryPrinter = $directoryPrinter;
6772
$this->metaTemplate = $metaTemplate;
6873
$this->templatePrinter = $templatePrinter;
6974
$this->fileFinder = $fileFinder;
@@ -93,10 +98,19 @@ public function execute(InputInterface $input, OutputInterface $output): int
9398

9499
$ss = new SymfonyStyle($input, $output);
95100

96-
$this->generatePhpFiles($ss, $specification);
97-
$this->copySpecification($ss);
98-
$this->generateMetaFiles($ss, $specification);
99-
$this->copyStaticPhpFiles($ss, $specification);
101+
$this->backup($ss);
102+
103+
try {
104+
$this->generatePhpFiles($ss, $specification);
105+
$this->copyStaticPhpFiles($ss, $specification);
106+
$this->copySpecification($ss);
107+
$this->generateMetaFiles($ss, $specification);
108+
} catch (Throwable $throwable) {
109+
$this->restoreBackup($ss);
110+
return Command::FAILURE;
111+
}
112+
113+
$this->removeBackup($ss);
100114

101115
return Command::SUCCESS;
102116
}
@@ -192,6 +206,55 @@ private function copySpecification(StyleInterface $ss): void
192206
);
193207
}
194208

209+
private function backup(StyleInterface $ss): void
210+
{
211+
$ss->text('<info>Backup original source.</info>');
212+
213+
$originalPath = sprintf(
214+
'%s/%s',
215+
$this->configuration->getOutputDirectory(),
216+
$this->configuration->getSourceDirectory()
217+
);
218+
219+
$backupPath = $originalPath . '_old';
220+
221+
$this->directoryPrinter->move(
222+
$backupPath,
223+
$originalPath
224+
);
225+
}
226+
227+
private function restoreBackup(StyleInterface $ss): void
228+
{
229+
$ss->text('<error>Restore original source from backup.</error>');
230+
231+
$originalPath = sprintf(
232+
'%s/%s',
233+
$this->configuration->getOutputDirectory(),
234+
$this->configuration->getSourceDirectory()
235+
);
236+
237+
$backupPath = $originalPath . '_old';
238+
239+
$this->directoryPrinter->move(
240+
$originalPath,
241+
$backupPath
242+
);
243+
}
244+
245+
private function removeBackup(StyleInterface $ss): void
246+
{
247+
$ss->text('<info>Delete backup.</info>');
248+
249+
$backupPath = sprintf(
250+
'%s/%s_old',
251+
$this->configuration->getOutputDirectory(),
252+
$this->configuration->getSourceDirectory()
253+
);
254+
255+
$this->directoryPrinter->delete($backupPath);
256+
}
257+
195258
private function initWarningPrinting(InputInterface $input): void
196259
{
197260
if ($input->getOption('quiet')) {

src/Output/DirectoryPrinter.php

+36
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,40 @@ public function ensureDirectoryExists(string $directoryPath): void
1818
throw new RuntimeException(sprintf('Directory "%s" could not be created', $directoryPath));
1919
}
2020
}
21+
22+
public function move(string $destinationPath, string $sourcePath): void
23+
{
24+
$this->ensureDirectoryExists($sourcePath);
25+
$this->delete($destinationPath);
26+
27+
rename($sourcePath, $destinationPath);
28+
}
29+
30+
public function delete(string $path): bool
31+
{
32+
if (!file_exists($path)) {
33+
return true;
34+
}
35+
36+
if (!is_dir($path)) {
37+
return unlink($path);
38+
}
39+
40+
$directoryContent = scandir($path);
41+
if ($directoryContent === false) {
42+
return true;
43+
}
44+
45+
foreach ($directoryContent as $item) {
46+
if ($item === '.' || $item === '..') {
47+
continue;
48+
}
49+
50+
if (!$this->delete($path . DIRECTORY_SEPARATOR . $item)) {
51+
return false;
52+
}
53+
}
54+
55+
return rmdir($path);
56+
}
2157
}

src/ServiceProvider.php

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
declare(strict_types=1);
34

45
namespace DoclerLabs\ApiClientGenerator;
@@ -96,6 +97,7 @@ public function register(Container $pimple): void
9697
$container[OpenApiParser::class],
9798
$container[CodeGeneratorFacade::class],
9899
$container[PhpFilePrinter::class],
100+
$container[DirectoryPrinter::class],
99101
$container[MetaTemplateFacade::class],
100102
$container[MetaFilePrinter::class],
101103
$container[Finder::class],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DoclerLabs\ApiClientGenerator\Test\Unit\Output;
6+
7+
use DoclerLabs\ApiClientGenerator\Output\DirectoryPrinter;
8+
use org\bovigo\vfs\vfsStream;
9+
use org\bovigo\vfs\vfsStreamDirectory;
10+
use PHPUnit\Framework\TestCase;
11+
12+
/**
13+
* @covers \DoclerLabs\ApiClientGenerator\Output\DirectoryPrinter
14+
*/
15+
class DirectoryPrinterTest extends TestCase
16+
{
17+
private DirectoryPrinter $sut;
18+
private vfsStreamDirectory $directory;
19+
20+
protected function setUp(): void
21+
{
22+
$this->sut = new DirectoryPrinter();
23+
$this->directory = vfsStream::setup();
24+
}
25+
26+
public function testCreationDuringEnsureDirectoryExists(): void
27+
{
28+
$directory = 'my-dir';
29+
30+
$this->sut->ensureDirectoryExists(
31+
$this->directory->url() . DIRECTORY_SEPARATOR . $directory
32+
);
33+
34+
self::assertTrue($this->directory->hasChild($directory));
35+
}
36+
37+
public function testExistingDuringEnsureDirectoryExists(): void
38+
{
39+
$directory = 'existing';
40+
41+
vfsStream::newDirectory($directory)->at($this->directory);
42+
43+
$this->sut->ensureDirectoryExists(
44+
$this->directory->url() . DIRECTORY_SEPARATOR . $directory
45+
);
46+
47+
self::assertTrue($this->directory->hasChild($directory));
48+
}
49+
50+
public function testMove(): void
51+
{
52+
$source = 'old';
53+
$destination = 'new';
54+
55+
vfsStream::newDirectory($source)->at($this->directory);
56+
57+
$this->sut->move(
58+
$this->directory->url() . DIRECTORY_SEPARATOR . $destination,
59+
$this->directory->url() . DIRECTORY_SEPARATOR . $source
60+
);
61+
62+
self::assertTrue($this->directory->hasChild($destination));
63+
self::assertFalse($this->directory->hasChild($source));
64+
}
65+
66+
public function testDeleteFolder(): void
67+
{
68+
$pathToKeep = 'to-keep';
69+
70+
$pathToRemove = 'to-remove';
71+
$fileToRemove = 'file-to-remove';
72+
$subFolderToRemove = 'sub-folder';
73+
$subFileToRemove = 'subfile-to-remove';
74+
75+
vfsStream::newDirectory($pathToKeep)->at($this->directory);
76+
77+
$toRemove = vfsStream::newDirectory($pathToRemove)->at($this->directory);
78+
vfsStream::newFile($fileToRemove)->at($toRemove);
79+
$toRemoveSubFolder = vfsStream::newDirectory($subFolderToRemove)->at($toRemove);
80+
vfsStream::newFile($subFileToRemove)->at($toRemoveSubFolder);
81+
82+
self::assertTrue(
83+
$this->sut->delete(
84+
$this->directory->url() . DIRECTORY_SEPARATOR . $pathToRemove,
85+
)
86+
);
87+
88+
self::assertTrue($this->directory->hasChild($pathToKeep));
89+
self::assertFalse($this->directory->hasChild($pathToRemove));
90+
}
91+
}

0 commit comments

Comments
 (0)