From c6f7bc033f96190215a2ab86ac295e3521ee5097 Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 13:01:24 +0100 Subject: [PATCH 01/10] Refactored transfer generator command to terminate process on error, handeled termination, changed error messages --- src/Command/Exception/CommandException.php | 12 +++++ src/Command/TransferGeneratorCommand.php | 45 +++++++++++-------- .../Generator/BulkTransferGenerator.php | 2 + .../Generator/FiberTransferGenerator.php | 21 ++++----- .../FiberTransferGeneratorInterface.php | 4 -- .../Generator/GeneratorProcessor.php | 15 +++---- .../Generator/GeneratorProcessorInterface.php | 17 +++++-- .../Generator/Generator/TransferGenerator.php | 26 +++++++++-- .../Command/TransferGeneratorCommandTest.php | 2 +- .../Generator/BulkTransferGeneratorTest.php | 4 +- 10 files changed, 94 insertions(+), 54 deletions(-) create mode 100644 src/Command/Exception/CommandException.php diff --git a/src/Command/Exception/CommandException.php b/src/Command/Exception/CommandException.php new file mode 100644 index 0000000..ee89bff --- /dev/null +++ b/src/Command/Exception/CommandException.php @@ -0,0 +1,12 @@ +error(self::ERROR_MESSAGE); - return Command::FAILURE; } @@ -82,30 +84,37 @@ private function generateTransfers(SymfonyStyle $styleOutput): bool $generatorFiber = $this->generatorFacade->getTransferGeneratorFiber(); $generatorTransfer = $generatorFiber->start(); - $this->writelnGeneratorTransfer($generatorTransfer, $styleOutput); + if ($generatorTransfer !== null && $generatorTransfer->validator?->isValid === false) { + $this->writelnGeneratorError($generatorTransfer, $styleOutput); + $generatorFiber->throw(new CommandException()); + } while (!$generatorFiber->isTerminated()) { $generatorTransfer = $generatorFiber->resume(); - $this->writelnGeneratorTransfer($generatorTransfer, $styleOutput); + if ($generatorTransfer === null || $generatorTransfer->validator?->isValid === true) { + continue; + } + + $this->writelnGeneratorError($generatorTransfer, $styleOutput); + $generatorFiber->throw(new CommandException()); } return $generatorFiber->getReturn(); } - private function writelnGeneratorTransfer( + private function writelnGeneratorError( ?TransferGeneratorTransfer $generatorTransfer, SymfonyStyle $styleOutput, ): void { - if ($generatorTransfer === null || $generatorTransfer->validator?->isValid === true) { - return; + $styleOutput->error(self::ERROR_MESSAGE); + + if ($generatorTransfer->className !== null) { + $styleOutput->error(sprintf(self::TRANSFER_OBJECT_MESSAGE_TEMPLATE, $generatorTransfer->className)); } - $error = sprintf( - self::ERROR_TEMPLATE, - $generatorTransfer->className ?: '---', - $generatorTransfer->fileName ?: '---', - ); - $styleOutput->error($error); + if ($generatorTransfer->fileName !== null) { + $styleOutput->error(sprintf(self::DEFINITION_MESSAGE_TEMPLATE, $generatorTransfer->fileName)); + } $this->writelnValidatorErrorMessages($generatorTransfer->validator->errorMessages, $styleOutput); } @@ -126,8 +135,6 @@ private function loadConfig(string $configPath, SymfonyStyle $styleOutput): bool return false; } - $styleOutput->info('Config: ' . $configPath); - return true; } @@ -137,7 +144,7 @@ private function loadConfig(string $configPath, SymfonyStyle $styleOutput): bool private function writelnValidatorErrorMessages(ArrayObject $errorMessages, SymfonyStyle $styleOutput): void { foreach ($errorMessages as $errorMessage) { - $styleOutput->warning($errorMessage->errorMessage); + $styleOutput->error($errorMessage->errorMessage); } } } diff --git a/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php b/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php index f7f2a77..582d513 100644 --- a/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php +++ b/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php @@ -22,11 +22,13 @@ public function __construct( */ public function generateTransfers(): void { + $transferGenerator = $this->generator->getTransferGenerator(); foreach ($this->generator->getTransferGenerator() as $generatorTransfer) { if ($generatorTransfer->validator?->isValid === true) { continue; } + $transferGenerator->throw(new TransferGeneratorException()); $this->throwError($generatorTransfer); } } diff --git a/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php b/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php index 7993acf..6f55588 100644 --- a/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php +++ b/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php @@ -5,6 +5,7 @@ namespace Picamator\TransferObject\TransferGenerator\Generator\Generator; use Fiber; +use Throwable; readonly class FiberTransferGenerator implements FiberTransferGeneratorInterface { @@ -13,23 +14,17 @@ public function __construct( ) { } - /** - * @throws \FiberError - * @throws \Throwable - */ public function getTransferFiberCallback(): bool { - $generatorIterator = $this->generator->getTransferGenerator(); - - $currentDefinitionFile = ''; - foreach ($generatorIterator as $generatorTransfer) { - if ($currentDefinitionFile !== $generatorTransfer->fileName) { - $currentDefinitionFile = $generatorTransfer->fileName; + $transferGenerator = $this->generator->getTransferGenerator(); + foreach ($transferGenerator as $generatorTransfer) { + try { + Fiber::suspend($generatorTransfer); + } catch (Throwable $e) { + $transferGenerator->throw($e); } - - Fiber::suspend($generatorTransfer); } - return $generatorIterator->getReturn(); + return $transferGenerator->getReturn(); } } diff --git a/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php b/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php index 11460b0..25ed1c8 100644 --- a/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php +++ b/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php @@ -6,9 +6,5 @@ interface FiberTransferGeneratorInterface { - /** - * @throws \FiberError - * @throws \Throwable - */ public function getTransferFiberCallback(): bool; } diff --git a/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php b/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php index 8e2ed04..d13ed6a 100644 --- a/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php +++ b/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php @@ -22,23 +22,22 @@ public function __construct( ) { } - public function preGenerateTransfer(): void + public function preProcess(): void { $this->filesystem->createTempDir(); } - public function postGenerateTransfer(bool $isSuccess): void + public function postProcessSuccess(): void { - if ($isSuccess) { - $this->filesystem->rotateTempDir(); - - return; - } + $this->filesystem->rotateTempDir(); + } + public function postProcessError(): void + { $this->filesystem->deleteTempDir(); } - public function generateTransfer(DefinitionTransfer $definitionTransfer): TransferGeneratorTransfer + public function process(DefinitionTransfer $definitionTransfer): TransferGeneratorTransfer { if (!$definitionTransfer->validator?->isValid) { return $this->createGeneratorTransfer($definitionTransfer); diff --git a/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php b/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php index 05499e1..7a6260a 100644 --- a/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php +++ b/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php @@ -9,9 +9,20 @@ interface GeneratorProcessorInterface { - public function preGenerateTransfer(): void; + /** + * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException + */ + public function preProcess(): void; - public function postGenerateTransfer(bool $isSuccess): void; + /** + * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException + */ + public function postProcessSuccess(): void; - public function generateTransfer(DefinitionTransfer $definitionTransfer): TransferGeneratorTransfer; + /** + * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException + */ + public function postProcessError(): void; + + public function process(DefinitionTransfer $definitionTransfer): TransferGeneratorTransfer; } diff --git a/src/TransferGenerator/Generator/Generator/TransferGenerator.php b/src/TransferGenerator/Generator/Generator/TransferGenerator.php index 70c49e8..2a2b82c 100644 --- a/src/TransferGenerator/Generator/Generator/TransferGenerator.php +++ b/src/TransferGenerator/Generator/Generator/TransferGenerator.php @@ -6,6 +6,7 @@ use Generator; use Picamator\TransferObject\TransferGenerator\Definition\Reader\DefinitionReaderInterface; +use Throwable; readonly class TransferGenerator implements TransferGeneratorInterface { @@ -17,20 +18,37 @@ public function __construct( public function getTransferGenerator(): Generator { - $this->processor->preGenerateTransfer(); + $this->processor->preProcess(); $failCount = 0; $definitionGenerator = $this->definitionReader->getDefinitions(); foreach ($definitionGenerator as $definitionTransfer) { - $generatorTransfer = $this->processor->generateTransfer($definitionTransfer); + $generatorTransfer = $this->processor->process($definitionTransfer); $failCount += (int)!$generatorTransfer->validator?->isValid; - yield $generatorTransfer; + try { + yield $generatorTransfer; + } catch (Throwable $e) { + $this->processor->postProcessError(); + + return false; + } } $isSuccess = $definitionGenerator->getReturn() > 0 && $failCount === 0; - $this->processor->postGenerateTransfer($isSuccess); + $this->postProcess($isSuccess); return $isSuccess; } + + private function postProcess(bool $isSuccess): void + { + if ($isSuccess) { + $this->processor->postProcessSuccess(); + + return; + } + + $this->processor->postProcessError(); + } } diff --git a/tests/integration/Command/TransferGeneratorCommandTest.php b/tests/integration/Command/TransferGeneratorCommandTest.php index 251816d..cd1fccd 100644 --- a/tests/integration/Command/TransferGeneratorCommandTest.php +++ b/tests/integration/Command/TransferGeneratorCommandTest.php @@ -56,7 +56,7 @@ public function testRunCommandWithValidConfigurationShouldShowSuccessMessage(): // Assert $this->commandTester->assertCommandIsSuccessful(); - $this->assertStringContainsString('Transfer Objects successfully generated.', $output); + $this->assertStringContainsString('Transfer Objects were generated successfully.', $output); } public function testRunCommandWithValidConfigurationButInvalidDefinitionShouldShowErrorMessage(): void diff --git a/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php b/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php index d3c3dd7..6c618f1 100644 --- a/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php +++ b/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php @@ -31,9 +31,9 @@ public function testGeneratorIteratesInvalidItemShouldRiseException(): void // Arrange $generatorTransfer = $this->createErrorGeneratorTransfer(); - $this->generatorMock->expects($this->once()) + $this->generatorMock->expects($this->exactly(2)) ->method('getTransferGenerator') - ->willReturnCallback(fn () => yield $generatorTransfer); + ->willReturnCallback(fn() => yield $generatorTransfer); $this->expectException(TransferGeneratorException::class); From d8e32c708cf50ec95b99a118fb008f13106f6fd0 Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 13:08:20 +0100 Subject: [PATCH 02/10] Removed generateTransfers from TransferGeneratorFacadeInterface --- src/TransferGenerator/TransferGeneratorFacade.php | 11 ----------- .../TransferGeneratorFacadeInterface.php | 15 +-------------- .../Helper/TransferGeneratorHelperTrait.php | 14 +++++++++++--- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/src/TransferGenerator/TransferGeneratorFacade.php b/src/TransferGenerator/TransferGeneratorFacade.php index 3c7d800..a7f7ba6 100644 --- a/src/TransferGenerator/TransferGeneratorFacade.php +++ b/src/TransferGenerator/TransferGeneratorFacade.php @@ -5,7 +5,6 @@ namespace Picamator\TransferObject\TransferGenerator; use Fiber; -use Generator; use Picamator\TransferObject\Generated\ConfigTransfer; use Picamator\TransferObject\Generated\TransferGeneratorTransfer; use Picamator\TransferObject\TransferGenerator\Generator\TransferGeneratorFactory; @@ -14,16 +13,6 @@ class TransferGeneratorFacade implements TransferGeneratorFacadeInterface { private static TransferGeneratorFactory $factory; - /** - * @return \Generator - */ - public function getTransferGenerator(): Generator - { - return $this->getFactory() - ->createTransferGenerator() - ->getTransferGenerator(); - } - /** * @return \Fiber */ diff --git a/src/TransferGenerator/TransferGeneratorFacadeInterface.php b/src/TransferGenerator/TransferGeneratorFacadeInterface.php index 23bee5b..358d757 100644 --- a/src/TransferGenerator/TransferGeneratorFacadeInterface.php +++ b/src/TransferGenerator/TransferGeneratorFacadeInterface.php @@ -11,19 +11,6 @@ interface TransferGeneratorFacadeInterface { - /** - * Specification: - * - Requires config loading `self::loadConfig()` - * - Generates new Transfer Object on each iteration - * - Transfer object `TransferGeneratorTransfer` might contain error messages if any occur - * - Returns `true` when whole process is successful, `false` otherwise - * - * @throws \Picamator\TransferObject\Exception\TransferExceptionInterface - * - * @return \Generator - */ - public function getTransferGenerator(): Generator; - /** * Specification: * - Requires config loading `self::loadConfig()` @@ -42,7 +29,7 @@ public function getTransferGeneratorFiber(): Fiber; /** * Specification: * - Requires config loading `self::loadConfig()` - * - Generates Transfer Objects without output + * - Generates Transfer Objects * - Throws exception on any error * * @throws \Picamator\TransferObject\Exception\TransferExceptionInterface diff --git a/tests/integration/Helper/TransferGeneratorHelperTrait.php b/tests/integration/Helper/TransferGeneratorHelperTrait.php index 361615c..bdc2747 100644 --- a/tests/integration/Helper/TransferGeneratorHelperTrait.php +++ b/tests/integration/Helper/TransferGeneratorHelperTrait.php @@ -15,13 +15,21 @@ trait TransferGeneratorHelperTrait */ protected function generateTransfers(callable $postGenerateItemCallback): bool { - $generatorIterator = new TransferGeneratorFacade()->getTransferGenerator(); + $generatorFiber = new TransferGeneratorFacade()->getTransferGeneratorFiber(); - foreach ($generatorIterator as $generatorTransfer) { + $generatorTransfer = $generatorFiber->start(); + if ($generatorTransfer !== null) { $postGenerateItemCallback($generatorTransfer); } - return $generatorIterator->getReturn(); + while (!$generatorFiber->isTerminated()) { + $generatorTransfer = $generatorFiber->resume(); + if ($generatorTransfer !== null) { + $postGenerateItemCallback($generatorTransfer); + } + } + + return $generatorFiber->getReturn(); } /** From ba75dc362f4c8922b0133dcd4bec60d60209f6bd Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 14:35:35 +0100 Subject: [PATCH 03/10] Refactore transfer object config, removed conatainer, replaced config with proxy --- .../Config/Config/Config.php | 30 +++++++++++ .../Config/Config/ConfigInterface.php | 23 +++++++++ .../Config/Config/ConfigProxy.php | 41 +++++++++++++++ .../Config/ConfigFactoryTrait.php | 6 +-- .../Config/Container/Config.php | 30 ----------- .../Config/Container/ConfigContainer.php | 34 ------------- .../Config/Container/ConfigInterface.php | 14 ------ .../Exception/ConfigNotFoundException.php | 12 +++++ .../Config/Loader/ConfigLoader.php | 6 ++- .../Filesystem/DefinitionFinder.php | 2 +- .../Filesystem/GeneratorFilesystem.php | 2 +- .../Generator/Render/TemplateBuilder.php | 2 +- .../Config/Container/ConfigContainerTest.php | 50 ------------------- .../Filesystem/GeneratorFilesystemTest.php | 2 +- 14 files changed, 117 insertions(+), 137 deletions(-) create mode 100644 src/TransferGenerator/Config/Config/Config.php create mode 100644 src/TransferGenerator/Config/Config/ConfigInterface.php create mode 100644 src/TransferGenerator/Config/Config/ConfigProxy.php delete mode 100644 src/TransferGenerator/Config/Container/Config.php delete mode 100644 src/TransferGenerator/Config/Container/ConfigContainer.php delete mode 100644 src/TransferGenerator/Config/Container/ConfigInterface.php create mode 100644 src/TransferGenerator/Config/Exception/ConfigNotFoundException.php delete mode 100644 tests/unit/TransferGenerator/Config/Container/ConfigContainerTest.php diff --git a/src/TransferGenerator/Config/Config/Config.php b/src/TransferGenerator/Config/Config/Config.php new file mode 100644 index 0000000..9c144d8 --- /dev/null +++ b/src/TransferGenerator/Config/Config/Config.php @@ -0,0 +1,30 @@ +configTransfer->transferNamespace; + } + + public function getTransferPath(): string + { + return $this->configTransfer->transferPath; + } + + public function getDefinitionPath(): string + { + return $this->configTransfer->definitionPath; + } +} diff --git a/src/TransferGenerator/Config/Config/ConfigInterface.php b/src/TransferGenerator/Config/Config/ConfigInterface.php new file mode 100644 index 0000000..341414e --- /dev/null +++ b/src/TransferGenerator/Config/Config/ConfigInterface.php @@ -0,0 +1,23 @@ +getConfig()->getTransferNamespace(); + } + + public function getTransferPath(): string + { + return $this->getConfig()->getTransferPath(); + } + + public function getDefinitionPath(): string + { + return $this->getConfig()->getDefinitionPath(); + } + + public static function loadConfig(ConfigInterface $config): void + { + self::$config = $config; + } + + private function getConfig(): ConfigInterface + { + if (!isset(self::$config)) { + throw new ConfigNotFoundException('Transfer Object configuration not found.'); + } + + return self::$config; + } +} diff --git a/src/TransferGenerator/Config/ConfigFactoryTrait.php b/src/TransferGenerator/Config/ConfigFactoryTrait.php index 6f96817..e8b185f 100644 --- a/src/TransferGenerator/Config/ConfigFactoryTrait.php +++ b/src/TransferGenerator/Config/ConfigFactoryTrait.php @@ -4,13 +4,13 @@ namespace Picamator\TransferObject\TransferGenerator\Config; -use Picamator\TransferObject\TransferGenerator\Config\Container\ConfigContainer; -use Picamator\TransferObject\TransferGenerator\Config\Container\ConfigInterface; +use Picamator\TransferObject\TransferGenerator\Config\Config\ConfigInterface; +use Picamator\TransferObject\TransferGenerator\Config\Config\ConfigProxy; trait ConfigFactoryTrait { protected function getConfig(): ConfigInterface { - return ConfigContainer::getConfig(); + return new ConfigProxy(); } } diff --git a/src/TransferGenerator/Config/Container/Config.php b/src/TransferGenerator/Config/Container/Config.php deleted file mode 100644 index cb54d5d..0000000 --- a/src/TransferGenerator/Config/Container/Config.php +++ /dev/null @@ -1,30 +0,0 @@ -transferNamespace; - } - - public function getTransferPath(): string - { - return $this->transferPath; - } - - public function getDefinitionPath(): string - { - return $this->definitionPath; - } -} diff --git a/src/TransferGenerator/Config/Container/ConfigContainer.php b/src/TransferGenerator/Config/Container/ConfigContainer.php deleted file mode 100644 index ed3eb25..0000000 --- a/src/TransferGenerator/Config/Container/ConfigContainer.php +++ /dev/null @@ -1,34 +0,0 @@ -transferNamespace, - transferPath: $configTransfer->transferPath, - definitionPath: $configTransfer->definitionPath, - ); - } - - /** - * @throws \Picamator\TransferObject\TransferGenerator\Exception\TransferGeneratorConfigException - */ - public static function getConfig(): ConfigInterface - { - if (!isset(self::$config)) { - throw new TransferGeneratorConfigException('Configuration not loaded. Run self::loadConfig() first.'); - } - - return self::$config; - } -} diff --git a/src/TransferGenerator/Config/Container/ConfigInterface.php b/src/TransferGenerator/Config/Container/ConfigInterface.php deleted file mode 100644 index 59a23b7..0000000 --- a/src/TransferGenerator/Config/Container/ConfigInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -reader->getConfig($configPath); if ($configTransfer->validator->isValid) { - ConfigContainer::loadConfig($configTransfer->content); + $config = new Config($configTransfer->content); + ConfigProxy::loadConfig($config); } return $configTransfer; diff --git a/src/TransferGenerator/Definition/Filesystem/DefinitionFinder.php b/src/TransferGenerator/Definition/Filesystem/DefinitionFinder.php index d48669c..f1695f8 100644 --- a/src/TransferGenerator/Definition/Filesystem/DefinitionFinder.php +++ b/src/TransferGenerator/Definition/Filesystem/DefinitionFinder.php @@ -6,7 +6,7 @@ use Generator; use Picamator\TransferObject\Dependency\Finder\FinderInterface; -use Picamator\TransferObject\TransferGenerator\Config\Container\ConfigInterface; +use Picamator\TransferObject\TransferGenerator\Config\Config\ConfigInterface; use Picamator\TransferObject\TransferGenerator\Exception\TransferGeneratorDefinitionException; readonly class DefinitionFinder implements DefinitionFinderInterface diff --git a/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php b/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php index 72cfefc..7f54f17 100644 --- a/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php +++ b/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php @@ -6,7 +6,7 @@ use Picamator\TransferObject\Dependency\Filesystem\FilesystemInterface; use Picamator\TransferObject\Dependency\Finder\FinderInterface; -use Picamator\TransferObject\TransferGenerator\Config\Container\ConfigInterface; +use Picamator\TransferObject\TransferGenerator\Config\Config\ConfigInterface; use Picamator\TransferObject\TransferGenerator\Exception\TransferGeneratorException; readonly class GeneratorFilesystem implements GeneratorFilesystemInterface diff --git a/src/TransferGenerator/Generator/Render/TemplateBuilder.php b/src/TransferGenerator/Generator/Render/TemplateBuilder.php index fa30110..fd8c9f9 100644 --- a/src/TransferGenerator/Generator/Render/TemplateBuilder.php +++ b/src/TransferGenerator/Generator/Render/TemplateBuilder.php @@ -5,7 +5,7 @@ namespace Picamator\TransferObject\TransferGenerator\Generator\Render; use ArrayObject; -use Picamator\TransferObject\TransferGenerator\Config\Container\ConfigInterface; +use Picamator\TransferObject\TransferGenerator\Config\Config\ConfigInterface; use Picamator\TransferObject\TransferGenerator\Generator\Enum\TransferEnum; use Picamator\TransferObject\Generated\DefinitionContentTransfer; use Picamator\TransferObject\Generated\DefinitionPropertyTransfer; diff --git a/tests/unit/TransferGenerator/Config/Container/ConfigContainerTest.php b/tests/unit/TransferGenerator/Config/Container/ConfigContainerTest.php deleted file mode 100644 index 4f26cf1..0000000 --- a/tests/unit/TransferGenerator/Config/Container/ConfigContainerTest.php +++ /dev/null @@ -1,50 +0,0 @@ -configContainer = new ConfigContainer(); - } - - public function testGetConfigWithoutLoadShouldThrowException(): void - { - // Act - $this->expectException(TransferGeneratorConfigException::class); - - // Assert - $this->configContainer->getConfig(); - } - - public function testLoadConfigAndGetShouldReturnConfig(): void - { - // Arrange - $contentTransfer = new ConfigContentTransfer() - ->fromArray([ - ConfigContentTransfer::TRANSFER_NAMESPACE => 'Test\SomeNamespace', - ConfigContentTransfer::TRANSFER_PATH => 'test\path\Generated', - ConfigContentTransfer::DEFINITION_PATH => 'test\path\config\definitions', - ]); - - $this->configContainer->loadConfig($contentTransfer); - - // Act - $actual = $this->configContainer->getConfig(); - - // Assert - $this->assertSame($contentTransfer->transferNamespace, $actual->getTransferNamespace()); - $this->assertSame($contentTransfer->transferPath, $actual->getTransferPath()); - $this->assertSame($contentTransfer->definitionPath, $actual->getDefinitionPath()); - } -} diff --git a/tests/unit/TransferGenerator/Generator/Filesystem/GeneratorFilesystemTest.php b/tests/unit/TransferGenerator/Generator/Filesystem/GeneratorFilesystemTest.php index 9d2c89c..dbf2a9e 100644 --- a/tests/unit/TransferGenerator/Generator/Filesystem/GeneratorFilesystemTest.php +++ b/tests/unit/TransferGenerator/Generator/Filesystem/GeneratorFilesystemTest.php @@ -8,7 +8,7 @@ use PHPUnit\Framework\TestCase; use Picamator\TransferObject\Dependency\Filesystem\FilesystemInterface; use Picamator\TransferObject\Dependency\Finder\FinderInterface; -use Picamator\TransferObject\TransferGenerator\Config\Container\ConfigInterface; +use Picamator\TransferObject\TransferGenerator\Config\Config\ConfigInterface; use Picamator\TransferObject\TransferGenerator\Exception\TransferGeneratorException; use Picamator\TransferObject\TransferGenerator\Generator\Filesystem\GeneratorFilesystem; use Picamator\TransferObject\TransferGenerator\Generator\Filesystem\GeneratorFilesystemInterface; From 62fbfe9b577d2f022d488753f43afc45a5dc5d8c Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 17:46:09 +0100 Subject: [PATCH 04/10] Simplified Transfer Object Facade interface refactoring how load config is working --- doc/samples/try-definition-generator.php | 13 ++-- doc/samples/try-transfer-generator.php | 14 ++-- src/Command/TransferGeneratorCommand.php | 56 ++++---------- .../Config/Config/ConfigProxy.php | 4 +- .../Config/Reader/ConfigReader.php | 4 - .../Filesystem/GeneratorFilesystem.php | 6 +- .../Generator/BulkTransferGenerator.php | 6 +- .../BulkTransferGeneratorInterface.php | 2 +- .../Generator/FiberTransferGenerator.php | 6 +- .../FiberTransferGeneratorInterface.php | 2 +- .../Generator/GeneratorProcessor.php | 51 ++++++++++--- .../Generator/GeneratorProcessorInterface.php | 15 +--- .../Generator/Generator/TransferGenerator.php | 40 +++++++--- .../Generator/TransferGeneratorInterface.php | 2 +- .../Generator/TransferGeneratorFactory.php | 13 ++-- .../TransferGeneratorFacade.php | 14 +--- .../TransferGeneratorFacadeInterface.php | 25 ++---- .../DefinitionGeneratorFacadeTest.php | 4 +- .../Helper/TransferGeneratorHelperTrait.php | 23 +----- tests/integration/Transfer/TransferTest.php | 5 +- .../{ => Config/Loader}/ConfigLoaderTest.php | 16 ++-- .../TransferGeneratorFacadeErrorTest.php | 27 +++++-- .../TransferGeneratorFacadeSuccessTest.php | 5 +- .../definition-path-is-not-exist.config.yml | 2 +- .../error/generator-key-bool.config.yml | 2 - .../invalid-definition-root-key.config.yml | 1 + .../Config/Config/ConfigProxyTest.php | 29 +++++++ .../Config/Reader/ConfigReaderTest.php | 75 ++++++++++++++++++ .../Generator/BulkTransferGeneratorTest.php | 6 +- .../Generator/GeneratorProcessorTest.php | 76 +++++++++++++++++++ 30 files changed, 357 insertions(+), 187 deletions(-) rename tests/integration/TransferGenerator/{ => Config/Loader}/ConfigLoaderTest.php (70%) delete mode 100644 tests/integration/TransferGenerator/data/config/error/generator-key-bool.config.yml create mode 100644 tests/integration/TransferGenerator/data/config/error/invalid-definition-root-key.config.yml create mode 100644 tests/unit/TransferGenerator/Config/Config/ConfigProxyTest.php create mode 100644 tests/unit/TransferGenerator/Config/Reader/ConfigReaderTest.php create mode 100644 tests/unit/TransferGenerator/Generator/Generator/GeneratorProcessorTest.php diff --git a/doc/samples/try-definition-generator.php b/doc/samples/try-definition-generator.php index 43ead0e..e153c15 100644 --- a/doc/samples/try-definition-generator.php +++ b/doc/samples/try-definition-generator.php @@ -4,6 +4,7 @@ use Picamator\Doc\Samples\TransferObject\Generated\DefinitionGenerator\ProductTransfer; use Picamator\TransferObject\DefinitionGenerator\DefinitionGeneratorFacade; +use Picamator\TransferObject\Exception\TransferExceptionInterface; use Picamator\TransferObject\Generated\DefinitionGeneratorContentTransfer; use Picamator\TransferObject\Generated\DefinitionGeneratorTransfer; use Picamator\TransferObject\TransferGenerator\TransferGeneratorFacade; @@ -86,14 +87,14 @@ ====================================================== STORY; -$transferGeneratorFacade = new TransferGeneratorFacade(); - -// ----- Load Configuration $configPath = __DIR__ . '/config/definition-generator/generator.config.yml'; -$configTransfer = $transferGeneratorFacade->loadConfig($configPath); -// ----- Generate Transfer Objects -$transferGeneratorFacade->generateTransfers(); +try { + new TransferGeneratorFacade()->generateTransfers($configPath); +} catch (TransferExceptionInterface $e) { + echo $e->getMessage(); + exit(1); +} echo <<<'STORY' ====================================================== diff --git a/doc/samples/try-transfer-generator.php b/doc/samples/try-transfer-generator.php index 0fa2e02..2187f9b 100644 --- a/doc/samples/try-transfer-generator.php +++ b/doc/samples/try-transfer-generator.php @@ -6,6 +6,7 @@ use Picamator\Doc\Samples\TransferObject\Generated\TransferGenerator\AgentTransfer; use Picamator\Doc\Samples\TransferObject\Generated\TransferGenerator\CustomerTransfer; use Picamator\Doc\Samples\TransferObject\Generated\TransferGenerator\MerchantTransfer; +use Picamator\TransferObject\Exception\TransferExceptionInterface; use Picamator\TransferObject\TransferGenerator\TransferGeneratorFacade; require_once __DIR__ . '/../../vendor/autoload.php'; @@ -13,18 +14,17 @@ echo <<<'STORY' ====================================================== Generate Transfer Objects - Note: for demo error handles were skipped ====================================================== STORY; -$transferGeneratorFacade = new TransferGeneratorFacade(); - -// ----- Load Configuration $configPath = __DIR__ . '/config/transfer-generator/generator.config.yml'; -$configTransfer = $transferGeneratorFacade->loadConfig($configPath); -// ----- Generate Transfer Objects -$transferGeneratorFacade->generateTransfers(); +try { + new TransferGeneratorFacade()->generateTransfers($configPath); +} catch (TransferExceptionInterface $e) { + echo $e->getMessage(); + exit(1); +} echo <<<'STORY' ====================================================== diff --git a/src/Command/TransferGeneratorCommand.php b/src/Command/TransferGeneratorCommand.php index 024d60c..6024240 100644 --- a/src/Command/TransferGeneratorCommand.php +++ b/src/Command/TransferGeneratorCommand.php @@ -59,17 +59,18 @@ protected function configure(): void protected function execute(InputInterface $input, OutputInterface $output): int { - $configPath = $input->getOption(self::OPTION_NAME_CONFIGURATION) ?: ''; - $styleOutput = new SymfonyStyle($input, $output); $styleOutput->section(self::START_SECTION_NAME); - $isSuccess = $this->loadConfig($configPath, $styleOutput); - if (!$isSuccess) { + $configPath = $input->getOption(self::OPTION_NAME_CONFIGURATION) ?: ''; + if ($configPath === '') { + $styleOutput->error(self::ERROR_MESSAGE); + $styleOutput->error(self::ERROR_MISSED_OPTION_CONFIG_MESSAGE); + return Command::FAILURE; } - $isSuccess = $this->generateTransfers($styleOutput); + $isSuccess = $this->generateTransfers($configPath, $styleOutput); if ($isSuccess) { $styleOutput->success(self::SUCCESS_MESSAGE); @@ -79,24 +80,24 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::FAILURE; } - private function generateTransfers(SymfonyStyle $styleOutput): bool + private function generateTransfers(string $configPath, SymfonyStyle $styleOutput): bool { $generatorFiber = $this->generatorFacade->getTransferGeneratorFiber(); - $generatorTransfer = $generatorFiber->start(); - if ($generatorTransfer !== null && $generatorTransfer->validator?->isValid === false) { + $generatorTransfer = $generatorFiber->start($configPath); + if ($generatorTransfer === null || $generatorTransfer->validator?->isValid === false) { $this->writelnGeneratorError($generatorTransfer, $styleOutput); $generatorFiber->throw(new CommandException()); + + return $generatorFiber->getReturn(); } while (!$generatorFiber->isTerminated()) { $generatorTransfer = $generatorFiber->resume(); - if ($generatorTransfer === null || $generatorTransfer->validator?->isValid === true) { - continue; + if ($generatorTransfer !== null && $generatorTransfer->validator?->isValid === false) { + $this->writelnGeneratorError($generatorTransfer, $styleOutput); + $generatorFiber->throw(new CommandException()); } - - $this->writelnGeneratorError($generatorTransfer, $styleOutput); - $generatorFiber->throw(new CommandException()); } return $generatorFiber->getReturn(); @@ -116,34 +117,7 @@ private function writelnGeneratorError( $styleOutput->error(sprintf(self::DEFINITION_MESSAGE_TEMPLATE, $generatorTransfer->fileName)); } - $this->writelnValidatorErrorMessages($generatorTransfer->validator->errorMessages, $styleOutput); - } - - private function loadConfig(string $configPath, SymfonyStyle $styleOutput): bool - { - if ($configPath === '') { - $styleOutput->error(self::ERROR_MESSAGE); - $styleOutput->error(self::ERROR_MISSED_OPTION_CONFIG_MESSAGE); - - return false; - } - - $configTransfer = $this->generatorFacade->loadConfig($configPath); - if (!$configTransfer->validator->isValid) { - $this->writelnValidatorErrorMessages($configTransfer->validator->errorMessages, $styleOutput); - - return false; - } - - return true; - } - - /** - * @param \ArrayObject $errorMessages - */ - private function writelnValidatorErrorMessages(ArrayObject $errorMessages, SymfonyStyle $styleOutput): void - { - foreach ($errorMessages as $errorMessage) { + foreach ($generatorTransfer->validator->errorMessages as $errorMessage) { $styleOutput->error($errorMessage->errorMessage); } } diff --git a/src/TransferGenerator/Config/Config/ConfigProxy.php b/src/TransferGenerator/Config/Config/ConfigProxy.php index 39b75cd..74d9e75 100644 --- a/src/TransferGenerator/Config/Config/ConfigProxy.php +++ b/src/TransferGenerator/Config/Config/ConfigProxy.php @@ -33,7 +33,9 @@ public static function loadConfig(ConfigInterface $config): void private function getConfig(): ConfigInterface { if (!isset(self::$config)) { - throw new ConfigNotFoundException('Transfer Object configuration not found.'); + throw new ConfigNotFoundException( + 'Transfer Object generator configuration not found. Please load configuration first.' + ); } return self::$config; diff --git a/src/TransferGenerator/Config/Reader/ConfigReader.php b/src/TransferGenerator/Config/Reader/ConfigReader.php index a8496b0..2b05a02 100644 --- a/src/TransferGenerator/Config/Reader/ConfigReader.php +++ b/src/TransferGenerator/Config/Reader/ConfigReader.php @@ -42,11 +42,7 @@ private function handleConfig(string $configPath): ConfigTransfer } $contentTransfer = $this->parser->parseConfig($configPath); - $validatorTransfer = $this->validator->validateContent($contentTransfer); - if (!$validatorTransfer->isValid) { - return $this->createConfigTransfer($validatorTransfer); - } $configTransfer = $this->createConfigTransfer($validatorTransfer); $configTransfer->content = $contentTransfer; diff --git a/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php b/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php index 7f54f17..26d9e97 100644 --- a/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php +++ b/src/TransferGenerator/Generator/Filesystem/GeneratorFilesystem.php @@ -64,8 +64,9 @@ public function writeFile(string $className, string $content): void } /** - * @throws \Picamator\TransferObject\Dependency\Exception\FinderException * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException + * @throws \Picamator\TransferObject\Dependency\Exception\FinderException + * @throws \Picamator\TransferObject\TransferGenerator\Config\Exception\ConfigNotFoundException */ private function deleteOldFiles(): void { @@ -79,8 +80,9 @@ private function deleteOldFiles(): void } /** - * @throws \Picamator\TransferObject\Dependency\Exception\FinderException * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException + * @throws \Picamator\TransferObject\Dependency\Exception\FinderException + * @throws \Picamator\TransferObject\TransferGenerator\Config\Exception\ConfigNotFoundException */ private function copyTempFiles(): void { diff --git a/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php b/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php index 582d513..f7e655b 100644 --- a/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php +++ b/src/TransferGenerator/Generator/Generator/BulkTransferGenerator.php @@ -20,10 +20,10 @@ public function __construct( /** * @throws \Picamator\TransferObject\Exception\TransferExceptionInterface */ - public function generateTransfers(): void + public function generateTransfers(string $configPath): void { - $transferGenerator = $this->generator->getTransferGenerator(); - foreach ($this->generator->getTransferGenerator() as $generatorTransfer) { + $transferGenerator = $this->generator->getTransferGenerator($configPath); + foreach ($transferGenerator as $generatorTransfer) { if ($generatorTransfer->validator?->isValid === true) { continue; } diff --git a/src/TransferGenerator/Generator/Generator/BulkTransferGeneratorInterface.php b/src/TransferGenerator/Generator/Generator/BulkTransferGeneratorInterface.php index 2b2a110..2aff3e8 100644 --- a/src/TransferGenerator/Generator/Generator/BulkTransferGeneratorInterface.php +++ b/src/TransferGenerator/Generator/Generator/BulkTransferGeneratorInterface.php @@ -9,5 +9,5 @@ interface BulkTransferGeneratorInterface /** * @throws \Picamator\TransferObject\TransferGenerator\Exception\TransferGeneratorException */ - public function generateTransfers(): void; + public function generateTransfers(string $configPath): void; } diff --git a/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php b/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php index 6f55588..26218cf 100644 --- a/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php +++ b/src/TransferGenerator/Generator/Generator/FiberTransferGenerator.php @@ -10,13 +10,13 @@ readonly class FiberTransferGenerator implements FiberTransferGeneratorInterface { public function __construct( - private TransferGeneratorInterface $generator, + private TransferGeneratorInterface $transferGenerator, ) { } - public function getTransferFiberCallback(): bool + public function getTransferFiberCallback(string $configPath): bool { - $transferGenerator = $this->generator->getTransferGenerator(); + $transferGenerator = $this->transferGenerator->getTransferGenerator($configPath); foreach ($transferGenerator as $generatorTransfer) { try { Fiber::suspend($generatorTransfer); diff --git a/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php b/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php index 25ed1c8..3d4cea2 100644 --- a/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php +++ b/src/TransferGenerator/Generator/Generator/FiberTransferGeneratorInterface.php @@ -6,5 +6,5 @@ interface FiberTransferGeneratorInterface { - public function getTransferFiberCallback(): bool; + public function getTransferFiberCallback(string $configPath): bool; } diff --git a/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php b/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php index d13ed6a..7e53257 100644 --- a/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php +++ b/src/TransferGenerator/Generator/Generator/GeneratorProcessor.php @@ -5,6 +5,7 @@ namespace Picamator\TransferObject\TransferGenerator\Generator\Generator; use Picamator\TransferObject\Dependency\Exception\FilesystemException; +use Picamator\TransferObject\Dependency\Exception\FinderException; use Picamator\TransferObject\Generated\DefinitionTransfer; use Picamator\TransferObject\Generated\DefinitionValidatorTransfer; use Picamator\TransferObject\Generated\TransferGeneratorTransfer; @@ -17,24 +18,42 @@ readonly class GeneratorProcessor implements GeneratorProcessorInterface { public function __construct( - private TemplateRenderInterface $renderer, + private TemplateRenderInterface $render, private GeneratorFilesystemInterface $filesystem, ) { } - public function preProcess(): void + public function preProcess(): TransferGeneratorTransfer { - $this->filesystem->createTempDir(); + try { + $this->filesystem->createTempDir(); + } catch (FilesystemException $e) { + return $this->createErrorGeneratorTransfer($e); + } + + return $this->createSuccessGeneratorTransfer(); } - public function postProcessSuccess(): void + public function postProcessSuccess(): TransferGeneratorTransfer { - $this->filesystem->rotateTempDir(); + try { + $this->filesystem->rotateTempDir(); + } catch (FilesystemException | FinderException $e) { + return $this->createErrorGeneratorTransfer($e); + } + + return $this->createSuccessGeneratorTransfer(); } - public function postProcessError(): void + public function postProcessError(): TransferGeneratorTransfer { - $this->filesystem->deleteTempDir(); + try { + $this->filesystem->deleteTempDir(); + } catch (FilesystemException $e) { + return $this->createErrorGeneratorTransfer($e); + } + + return $this->createSuccessGeneratorTransfer(); } public function process(DefinitionTransfer $definitionTransfer): TransferGeneratorTransfer @@ -44,7 +63,7 @@ public function process(DefinitionTransfer $definitionTransfer): TransferGenerat } try { - $content = $this->renderer->renderTemplate($definitionTransfer->content); + $content = $this->render->renderTemplate($definitionTransfer->content); $this->filesystem->writeFile($definitionTransfer->content->className, $content); return $this->createGeneratorTransfer($definitionTransfer); @@ -55,12 +74,12 @@ public function process(DefinitionTransfer $definitionTransfer): TransferGenerat private function createErrorGeneratorTransfer( Throwable $e, - DefinitionTransfer $definitionTransfer, + ?DefinitionTransfer $definitionTransfer = null, ): TransferGeneratorTransfer { $generatorTransfer = new TransferGeneratorTransfer(); - $generatorTransfer->className = $definitionTransfer->content?->className; - $generatorTransfer->fileName = $definitionTransfer->fileName; + $generatorTransfer->className = $definitionTransfer?->content?->className; + $generatorTransfer->fileName = $definitionTransfer?->fileName; $generatorTransfer->validator = new DefinitionValidatorTransfer(); $generatorTransfer->validator->isValid = false; @@ -73,6 +92,16 @@ private function createErrorGeneratorTransfer( return $generatorTransfer; } + private function createSuccessGeneratorTransfer(): TransferGeneratorTransfer + { + $generatorTransfer = new TransferGeneratorTransfer(); + + $generatorTransfer->validator = new DefinitionValidatorTransfer(); + $generatorTransfer->validator->isValid = true; + + return $generatorTransfer; + } + private function createGeneratorTransfer(DefinitionTransfer $definitionTransfer): TransferGeneratorTransfer { $generatorTransfer = new TransferGeneratorTransfer(); diff --git a/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php b/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php index 7a6260a..b968746 100644 --- a/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php +++ b/src/TransferGenerator/Generator/Generator/GeneratorProcessorInterface.php @@ -9,20 +9,11 @@ interface GeneratorProcessorInterface { - /** - * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException - */ - public function preProcess(): void; + public function preProcess(): TransferGeneratorTransfer; - /** - * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException - */ - public function postProcessSuccess(): void; + public function postProcessSuccess(): TransferGeneratorTransfer; - /** - * @throws \Picamator\TransferObject\Dependency\Exception\FilesystemException - */ - public function postProcessError(): void; + public function postProcessError(): TransferGeneratorTransfer; public function process(DefinitionTransfer $definitionTransfer): TransferGeneratorTransfer; } diff --git a/src/TransferGenerator/Generator/Generator/TransferGenerator.php b/src/TransferGenerator/Generator/Generator/TransferGenerator.php index 2a2b82c..7cf4569 100644 --- a/src/TransferGenerator/Generator/Generator/TransferGenerator.php +++ b/src/TransferGenerator/Generator/Generator/TransferGenerator.php @@ -5,20 +5,28 @@ namespace Picamator\TransferObject\TransferGenerator\Generator\Generator; use Generator; +use Picamator\TransferObject\Generated\DefinitionValidatorTransfer; +use Picamator\TransferObject\Generated\TransferGeneratorTransfer; +use Picamator\TransferObject\TransferGenerator\Config\Loader\ConfigLoaderInterface; use Picamator\TransferObject\TransferGenerator\Definition\Reader\DefinitionReaderInterface; use Throwable; readonly class TransferGenerator implements TransferGeneratorInterface { public function __construct( + private ConfigLoaderInterface $configLoader, private DefinitionReaderInterface $definitionReader, private GeneratorProcessorInterface $processor, ) { } - public function getTransferGenerator(): Generator + public function getTransferGenerator(string $configPath): Generator { - $this->processor->preProcess(); + try { + yield $this->preProcess($configPath); + } catch (Throwable) { + return false; + } $failCount = 0; $definitionGenerator = $this->definitionReader->getDefinitions(); @@ -28,27 +36,41 @@ public function getTransferGenerator(): Generator try { yield $generatorTransfer; - } catch (Throwable $e) { - $this->processor->postProcessError(); + } catch (Throwable) { + yield $this->processor->postProcessError(); return false; } } $isSuccess = $definitionGenerator->getReturn() > 0 && $failCount === 0; - $this->postProcess($isSuccess); + yield $this->postProcess($isSuccess); return $isSuccess; } - private function postProcess(bool $isSuccess): void + private function postProcess(bool $isSuccess): TransferGeneratorTransfer { if ($isSuccess) { - $this->processor->postProcessSuccess(); + return $this->processor->postProcessSuccess(); + } + + return $this->processor->postProcessError(); + } - return; + private function preProcess(string $configPath): TransferGeneratorTransfer + { + $configTransfer = $this->configLoader->loadConfig($configPath); + + if ($configTransfer->validator->isValid) { + return $this->processor->preProcess(); } - $this->processor->postProcessError(); + $generatorTransfer = new TransferGeneratorTransfer(); + $generatorTransfer->validator = new DefinitionValidatorTransfer(); + $generatorTransfer->validator->isValid = false; + $generatorTransfer->validator->errorMessages = $configTransfer->validator->errorMessages; + + return $generatorTransfer; } } diff --git a/src/TransferGenerator/Generator/Generator/TransferGeneratorInterface.php b/src/TransferGenerator/Generator/Generator/TransferGeneratorInterface.php index 30a426a..f19e59c 100644 --- a/src/TransferGenerator/Generator/Generator/TransferGeneratorInterface.php +++ b/src/TransferGenerator/Generator/Generator/TransferGeneratorInterface.php @@ -11,5 +11,5 @@ interface TransferGeneratorInterface /** * @return \Generator */ - public function getTransferGenerator(): Generator; + public function getTransferGenerator(string $configPath): Generator; } diff --git a/src/TransferGenerator/Generator/TransferGeneratorFactory.php b/src/TransferGenerator/Generator/TransferGeneratorFactory.php index ddb1a5d..79a10ed 100644 --- a/src/TransferGenerator/Generator/TransferGeneratorFactory.php +++ b/src/TransferGenerator/Generator/TransferGeneratorFactory.php @@ -42,7 +42,7 @@ use DependencyFactoryTrait; /** - * @return \Fiber + * @return \Fiber */ public function createTransferGeneratorFiber(): Fiber { @@ -57,6 +57,7 @@ private function createFiberTransferGenerator(): FiberTransferGeneratorInterface public function createTransferGenerator(): TransferGeneratorInterface { return new TransferGenerator( + $this->createConfigLoader(), $this->createDefinitionReader(), $this->createGeneratorProcessor(), ); @@ -67,11 +68,6 @@ public function createBulkTransferGenerator(): BulkTransferGeneratorInterface return new BulkTransferGenerator($this->createTransferGenerator()); } - public function createConfigLoader(): ConfigLoaderInterface - { - return new ConfigFactory()->createConfigLoader(); - } - protected function createGeneratorProcessor(): GeneratorProcessorInterface { return new GeneratorProcessor( @@ -147,6 +143,11 @@ protected function createFinder(): FinderInterface return $this->getDependency(DependencyContainer::FINDER); } + protected function createConfigLoader(): ConfigLoaderInterface + { + return new ConfigFactory()->createConfigLoader(); + } + protected function createDefinitionReader(): DefinitionReaderInterface { return new DefinitionFactory()->createDefinitionReader(); diff --git a/src/TransferGenerator/TransferGeneratorFacade.php b/src/TransferGenerator/TransferGeneratorFacade.php index a7f7ba6..5d5c7e5 100644 --- a/src/TransferGenerator/TransferGeneratorFacade.php +++ b/src/TransferGenerator/TransferGeneratorFacade.php @@ -5,7 +5,6 @@ namespace Picamator\TransferObject\TransferGenerator; use Fiber; -use Picamator\TransferObject\Generated\ConfigTransfer; use Picamator\TransferObject\Generated\TransferGeneratorTransfer; use Picamator\TransferObject\TransferGenerator\Generator\TransferGeneratorFactory; @@ -14,7 +13,7 @@ class TransferGeneratorFacade implements TransferGeneratorFacadeInterface private static TransferGeneratorFactory $factory; /** - * @return \Fiber + * @return \Fiber */ public function getTransferGeneratorFiber(): Fiber { @@ -22,18 +21,11 @@ public function getTransferGeneratorFiber(): Fiber ->createTransferGeneratorFiber(); } - public function generateTransfers(): void + public function generateTransfers(string $configPath): void { $this->getFactory() ->createBulkTransferGenerator() - ->generateTransfers(); - } - - public function loadConfig(string $configPath): ConfigTransfer - { - return $this->getFactory() - ->createConfigLoader() - ->loadConfig($configPath); + ->generateTransfers($configPath); } private function getFactory(): TransferGeneratorFactory diff --git a/src/TransferGenerator/TransferGeneratorFacadeInterface.php b/src/TransferGenerator/TransferGeneratorFacadeInterface.php index 358d757..b8abf2b 100644 --- a/src/TransferGenerator/TransferGeneratorFacadeInterface.php +++ b/src/TransferGenerator/TransferGeneratorFacadeInterface.php @@ -5,43 +5,34 @@ namespace Picamator\TransferObject\TransferGenerator; use Fiber; -use Generator; -use Picamator\TransferObject\Generated\ConfigTransfer; use Picamator\TransferObject\Generated\TransferGeneratorTransfer; interface TransferGeneratorFacadeInterface { /** * Specification: - * - Requires config loading `self::loadConfig()` * - Provides Transfer Generator Fiber - * - Suspends after generating Transfer Object passing `TransferGeneratorTransfer` back + * - Starts fiber with `$configPath` + * - First fiber suspend after configuration load + * - Next fiber suspends after generating Transfer Object passing `TransferGeneratorTransfer` back + * - Throw fiber exception terminates process and return `false` * - Transfer object `TransferGeneratorTransfer` might contain error messages if any occur * - Returns `true` when whole process is successful, `false` otherwise * * @throws \FiberError * @throws \Picamator\TransferObject\Exception\TransferExceptionInterface * - * @return \Fiber + * @return \Fiber */ public function getTransferGeneratorFiber(): Fiber; /** * Specification: - * - Requires config loading `self::loadConfig()` + * - Loads configuration * - Generates Transfer Objects - * - Throws exception on any error + * - Throws exception on error * * @throws \Picamator\TransferObject\Exception\TransferExceptionInterface */ - public function generateTransfers(): void; - - /** - * Specification: - * - Reads and parses provided configuration file - * - Statically loads configuration to reuse for transfer object generation - * - * @throws \Picamator\TransferObject\Exception\TransferExceptionInterface - */ - public function loadConfig(string $configPath): ConfigTransfer; + public function generateTransfers(string $configPath): void; } diff --git a/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php b/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php index 1675dc2..045428b 100644 --- a/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php +++ b/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php @@ -87,10 +87,8 @@ public function testGenerateTransferBasedOnDefinitionShouldSuccessfullyGenerateT $pathPlaceholder = pathinfo($sampleFileName, PATHINFO_FILENAME); $configPath = sprintf(self::CONFIG_PATH_TEMPLATE, $pathPlaceholder); - $this->assertLoadConfigSuccess($configPath); - // Act - $actual = $this->generateTransfers($this->assertGeneratorSuccess(...)); + $actual = $this->generateTransfers($configPath, $this->assertGeneratorSuccess(...)); // Assert $this->assertTrue($actual); diff --git a/tests/integration/Helper/TransferGeneratorHelperTrait.php b/tests/integration/Helper/TransferGeneratorHelperTrait.php index bdc2747..7a7a37c 100644 --- a/tests/integration/Helper/TransferGeneratorHelperTrait.php +++ b/tests/integration/Helper/TransferGeneratorHelperTrait.php @@ -13,11 +13,11 @@ trait TransferGeneratorHelperTrait /** * @throws \Throwable */ - protected function generateTransfers(callable $postGenerateItemCallback): bool + protected function generateTransfers(string $configPath, callable $postGenerateItemCallback): bool { - $generatorFiber = new TransferGeneratorFacade()->getTransferGeneratorFiber(); + $generatorFiber = new TransferGeneratorFacade()->getTransferGeneratorFiber(); - $generatorTransfer = $generatorFiber->start(); + $generatorTransfer = $generatorFiber->start($configPath); if ($generatorTransfer !== null) { $postGenerateItemCallback($generatorTransfer); } @@ -32,23 +32,8 @@ protected function generateTransfers(callable $postGenerateItemCallback): bool return $generatorFiber->getReturn(); } - /** - * @throws \Throwable - */ - protected function assertLoadConfigSuccess(string $configPath): void + protected function assertGeneratorSuccess(TransferGeneratorTransfer $generatorTransfer): void { - $configTransfer = new TransferGeneratorFacade()->loadConfig($configPath); - $message = $this->groupValidatorMessages($configTransfer->validator->errorMessages); - - $this->assertTrue($configTransfer->validator->isValid, $message); - } - - protected function assertGeneratorSuccess(?TransferGeneratorTransfer $generatorTransfer): void - { - if ($generatorTransfer === null) { - return; - } - $message = $this->groupValidatorMessages($generatorTransfer->validator->errorMessages); $this->assertTrue($generatorTransfer->validator->isValid, $message); diff --git a/tests/integration/Transfer/TransferTest.php b/tests/integration/Transfer/TransferTest.php index f2677fc..58b4355 100644 --- a/tests/integration/Transfer/TransferTest.php +++ b/tests/integration/Transfer/TransferTest.php @@ -22,11 +22,8 @@ class TransferTest extends TestCase public function testGenerateTransferShouldSucceed(): void { - // Arrange - $this->assertLoadConfigSuccess(self::GENERATOR_CONFIG_PATH); - // Act - $actual = $this->generateTransfers($this->assertGeneratorSuccess(...)); + $actual = $this->generateTransfers(self::GENERATOR_CONFIG_PATH, $this->assertGeneratorSuccess(...)); // Assert $this->assertTrue($actual); diff --git a/tests/integration/TransferGenerator/ConfigLoaderTest.php b/tests/integration/TransferGenerator/Config/Loader/ConfigLoaderTest.php similarity index 70% rename from tests/integration/TransferGenerator/ConfigLoaderTest.php rename to tests/integration/TransferGenerator/Config/Loader/ConfigLoaderTest.php index 88fb2f3..003108e 100644 --- a/tests/integration/TransferGenerator/ConfigLoaderTest.php +++ b/tests/integration/TransferGenerator/Config/Loader/ConfigLoaderTest.php @@ -2,23 +2,23 @@ declare(strict_types=1); -namespace Picamator\Tests\Integration\TransferObject\TransferGenerator; +namespace Picamator\Tests\Integration\TransferObject\TransferGenerator\Config\Loader; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -use Picamator\TransferObject\TransferGenerator\TransferGeneratorFacade; -use Picamator\TransferObject\TransferGenerator\TransferGeneratorFacadeInterface; +use Picamator\TransferObject\TransferGenerator\Config\ConfigFactory; +use Picamator\TransferObject\TransferGenerator\Config\Loader\ConfigLoaderInterface; class ConfigLoaderTest extends TestCase { - private const string CONFIG_PATH = __DIR__ . '/data/config/error/'; + private const string CONFIG_PATH = __DIR__ . '/../../data/config/error/'; - private TransferGeneratorFacadeInterface $generatorFacade; + private ConfigLoaderInterface $configLoader; protected function setUp(): void { - $this->generatorFacade = new TransferGeneratorFacade(); + $this->configLoader = new ConfigFactory()->createConfigLoader(); } #[DataProvider('invalidConfigDataProvider')] @@ -28,7 +28,7 @@ public function testInvalidConfigShouldReturnError(string $configName): void $configPath = self::CONFIG_PATH . $configName; // Act - $actual = $this->generatorFacade->loadConfig($configPath); + $actual = $this->configLoader->loadConfig($configPath); // Assert $this->assertFalse($actual->validator->isValid); @@ -52,6 +52,6 @@ public static function invalidConfigDataProvider(): Generator yield 'empty config file' => ['empty.config.yml']; - yield 'generator root kee is boolean' => ['generator-key-bool.config.yml']; + yield 'invalid definition root key' => ['invalid-definition-root-key.config.yml']; } } diff --git a/tests/integration/TransferGenerator/TransferGeneratorFacadeErrorTest.php b/tests/integration/TransferGenerator/TransferGeneratorFacadeErrorTest.php index ecf26d5..8c95e71 100644 --- a/tests/integration/TransferGenerator/TransferGeneratorFacadeErrorTest.php +++ b/tests/integration/TransferGenerator/TransferGeneratorFacadeErrorTest.php @@ -9,6 +9,8 @@ use PHPUnit\Framework\TestCase; use Picamator\Tests\Integration\TransferObject\Helper\TransferGeneratorHelperTrait; use Picamator\TransferObject\Generated\TransferGeneratorTransfer; +use Picamator\TransferObject\TransferGenerator\Exception\TransferGeneratorException; +use Picamator\TransferObject\TransferGenerator\TransferGeneratorFacade; class TransferGeneratorFacadeErrorTest extends TestCase { @@ -23,10 +25,9 @@ public function testGenerateTransferObjectByInvalidDefinitionShouldFail( ): void { // Arrange $configPath = $this->getConfigPath($configCaseName); - $this->assertLoadConfigSuccess($configPath); - $callback = function (?TransferGeneratorTransfer $generatorTransfer) use ($expectedMessage): void { - if ($generatorTransfer === null) { + $callback = function (TransferGeneratorTransfer $generatorTransfer) use ($expectedMessage): void { + if ($generatorTransfer->validator->isValid) { return; } @@ -39,7 +40,7 @@ public function testGenerateTransferObjectByInvalidDefinitionShouldFail( }; // Act - $actual = $this->generateTransfers($callback); + $actual = $this->generateTransfers($configPath, $callback); // Assert $this->assertFalse($actual); @@ -51,10 +52,9 @@ public function testGenerateTransferObjectByDuplicateDefinitionShouldFail(): voi // Arrange $configPath = $this->getConfigPath($configCaseName); - $this->assertLoadConfigSuccess($configPath); - $callback = function (?TransferGeneratorTransfer $generatorTransfer): void { - if ($generatorTransfer === null || $generatorTransfer->validator->isValid) { + $callback = function (TransferGeneratorTransfer $generatorTransfer): void { + if ($generatorTransfer->validator->isValid) { return; } @@ -67,7 +67,7 @@ public function testGenerateTransferObjectByDuplicateDefinitionShouldFail(): voi }; // Act - $actual = $this->generateTransfers($callback); + $actual = $this->generateTransfers($configPath, $callback); // Assert $this->assertFalse($actual); @@ -134,6 +134,17 @@ public static function invalidDefinitionDataProvider(): Generator ]; } + public function testBulkTransferGeneratorShouldFailOnError(): void + { + // Arrange + $configPath = $this->getConfigPath('invalid-class-name'); + + $this->expectException(TransferGeneratorException::class); + + // Act + new TransferGeneratorFacade()->generateTransfers($configPath); + } + private function getConfigPath(string $configCaseName): string { return sprintf(self::CONFIG_PATH_TEMPLATE, $configCaseName); diff --git a/tests/integration/TransferGenerator/TransferGeneratorFacadeSuccessTest.php b/tests/integration/TransferGenerator/TransferGeneratorFacadeSuccessTest.php index 337b780..a187027 100644 --- a/tests/integration/TransferGenerator/TransferGeneratorFacadeSuccessTest.php +++ b/tests/integration/TransferGenerator/TransferGeneratorFacadeSuccessTest.php @@ -23,11 +23,8 @@ class TransferGeneratorFacadeSuccessTest extends TestCase public function testGenerateTransferObjectByValidDefinitionShouldSucceed(): void { - // Arrange - $this->assertLoadConfigSuccess(self::GENERATOR_CONFIG_PATH); - // Act - $actual = $this->generateTransfers($this->assertGeneratorSuccess(...)); + $actual = $this->generateTransfers(self::GENERATOR_CONFIG_PATH, $this->assertGeneratorSuccess(...)); // Assert $this->assertTrue($actual); diff --git a/tests/integration/TransferGenerator/data/config/error/definition-path-is-not-exist.config.yml b/tests/integration/TransferGenerator/data/config/error/definition-path-is-not-exist.config.yml index 708cdf5..dc3adbc 100644 --- a/tests/integration/TransferGenerator/data/config/error/definition-path-is-not-exist.config.yml +++ b/tests/integration/TransferGenerator/data/config/error/definition-path-is-not-exist.config.yml @@ -1,4 +1,4 @@ generator: transferNamespace: "Picamator\\Tests\\Integration\\TransferObject\\TransferGenerator\\Generated\\Error" transferPath: "${PROJECT_ROOT}/tests/integration/TransferGenerator/Generated/Error" - definitionPath: "${PROJECT_ROOT}/tests/integration/some-unexisting-path" + definitionPath: "${PROJECT_ROOT}/tests/integration/some-invalid-path" diff --git a/tests/integration/TransferGenerator/data/config/error/generator-key-bool.config.yml b/tests/integration/TransferGenerator/data/config/error/generator-key-bool.config.yml deleted file mode 100644 index 211fe21..0000000 --- a/tests/integration/TransferGenerator/data/config/error/generator-key-bool.config.yml +++ /dev/null @@ -1,2 +0,0 @@ -generator: - something: something diff --git a/tests/integration/TransferGenerator/data/config/error/invalid-definition-root-key.config.yml b/tests/integration/TransferGenerator/data/config/error/invalid-definition-root-key.config.yml new file mode 100644 index 0000000..bbcbca4 --- /dev/null +++ b/tests/integration/TransferGenerator/data/config/error/invalid-definition-root-key.config.yml @@ -0,0 +1 @@ +generator: true diff --git a/tests/unit/TransferGenerator/Config/Config/ConfigProxyTest.php b/tests/unit/TransferGenerator/Config/Config/ConfigProxyTest.php new file mode 100644 index 0000000..82808c3 --- /dev/null +++ b/tests/unit/TransferGenerator/Config/Config/ConfigProxyTest.php @@ -0,0 +1,29 @@ +proxy = new ConfigProxy(); + } + + public function testGetTransferNamespaceWithoutLoadingConfigFirstShouldRiseException(): void + { + // Arrange + $this->expectException(ConfigNotFoundException::class); + + // Act + $this->proxy->getTransferNamespace(); + } +} diff --git a/tests/unit/TransferGenerator/Config/Reader/ConfigReaderTest.php b/tests/unit/TransferGenerator/Config/Reader/ConfigReaderTest.php new file mode 100644 index 0000000..356c626 --- /dev/null +++ b/tests/unit/TransferGenerator/Config/Reader/ConfigReaderTest.php @@ -0,0 +1,75 @@ +parserMock = $this->createMock(ConfigParserInterface::class); + + $this->validatorMock = $this->createMock(ConfigValidatorInterface::class); + + $this->reader = new ConfigReader( + $this->parserMock, + $this->validatorMock, + ); + } + + public function testShouldCatchFileSystemExceptionOnGetConfig(): void + { + // Arrange + $configPath = 'some-config-path.yml'; + + $this->validatorMock->expects($this->once()) + ->method('validateFile') + ->willThrowException(new FilesystemException()); + + // Act + $actual = $this->reader->getConfig($configPath); + + // Assert + $this->assertFalse($actual->validator->isValid); + } + + public function testShouldCatchYmlParserExceptionOnGetConfig(): void + { + // Arrange + $configPath = 'some-config-path.yml'; + + $validatorTransfer = new ConfigValidatorTransfer(); + $validatorTransfer->isValid = true; + + $this->validatorMock->expects($this->once()) + ->method('validateFile') + ->willReturn($validatorTransfer); + + $this->parserMock->expects($this->once()) + ->method('parseConfig') + ->willThrowException(new YmlParserException()); + + // Act + $actual = $this->reader->getConfig($configPath); + + // Assert + $this->assertFalse($actual->validator->isValid); + } +} diff --git a/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php b/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php index 6c618f1..c32ad87 100644 --- a/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php +++ b/tests/unit/TransferGenerator/Generator/Generator/BulkTransferGeneratorTest.php @@ -29,16 +29,18 @@ protected function setUp(): void public function testGeneratorIteratesInvalidItemShouldRiseException(): void { // Arrange + $configPath = 'some-config-path.yml'; + $generatorTransfer = $this->createErrorGeneratorTransfer(); - $this->generatorMock->expects($this->exactly(2)) + $this->generatorMock->expects($this->once()) ->method('getTransferGenerator') ->willReturnCallback(fn() => yield $generatorTransfer); $this->expectException(TransferGeneratorException::class); // Act - $this->bulkGenerator->generateTransfers(); + $this->bulkGenerator->generateTransfers($configPath); } private function createErrorGeneratorTransfer(): TransferGeneratorTransfer diff --git a/tests/unit/TransferGenerator/Generator/Generator/GeneratorProcessorTest.php b/tests/unit/TransferGenerator/Generator/Generator/GeneratorProcessorTest.php new file mode 100644 index 0000000..660cfbd --- /dev/null +++ b/tests/unit/TransferGenerator/Generator/Generator/GeneratorProcessorTest.php @@ -0,0 +1,76 @@ +renderMock = $this->createMock(TemplateRenderInterface::class); + + $this->filesystemMock = $this->createMock(GeneratorFilesystemInterface::class); + + $this->generatorProcessor = new GeneratorProcessor( + $this->renderMock, + $this->filesystemMock, + ); + } + + public function testFilesystemExceptionShouldBeHandledOnPreProcess(): void + { + // Arrange + $this->filesystemMock->expects($this->once()) + ->method('createTempDir') + ->willThrowException(new FilesystemException()); + + // Act + $actual = $this->generatorProcessor->preProcess(); + + // Assert + $this->assertFalse($actual->validator->isValid); + } + + public function testFilesystemExceptionShouldBeHandledOnPostProcessSuccess(): void + { + // Arrange + $this->filesystemMock->expects($this->once()) + ->method('rotateTempDir') + ->willThrowException(new FilesystemException()); + + // Act + $actual = $this->generatorProcessor->postProcessSuccess(); + + // Assert + $this->assertFalse($actual->validator->isValid); + } + + public function testFilesystemExceptionShouldBeHandledOnPostProcessError(): void + { + // Arrange + $this->filesystemMock->expects($this->once()) + ->method('deleteTempDir') + ->willThrowException(new FilesystemException()); + + // Act + $actual = $this->generatorProcessor->postProcessError(); + + // Assert + $this->assertFalse($actual->validator->isValid); + } +} From da0a126eb582b8846ba159dacf90eaf125ac9424 Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 18:04:42 +0100 Subject: [PATCH 05/10] Upgraded dependencies --- composer.lock | 22 +++++++++++----------- phpstan.neon | 3 +++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/composer.lock b/composer.lock index 1849d9a..0c1fa4e 100644 --- a/composer.lock +++ b/composer.lock @@ -287,16 +287,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.0", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { @@ -331,7 +331,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.0" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -347,7 +347,7 @@ "type": "tidelift" } ], - "time": "2024-10-23T06:56:12+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1289,16 +1289,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.0.4", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "50d276fc3bf1430ec315f2f109bbde2769821524" + "reference": "2392d360fdf54ea253aa6c68cad1d4ba2e54e927" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/50d276fc3bf1430ec315f2f109bbde2769821524", - "reference": "50d276fc3bf1430ec315f2f109bbde2769821524", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2392d360fdf54ea253aa6c68cad1d4ba2e54e927", + "reference": "2392d360fdf54ea253aa6c68cad1d4ba2e54e927", "shasum": "" }, "require": { @@ -1343,7 +1343,7 @@ "type": "github" } ], - "time": "2024-12-17T17:14:01+00:00" + "time": "2024-12-31T07:30:03+00:00" }, { "name": "phpunit/php-code-coverage", diff --git a/phpstan.neon b/phpstan.neon index a296f9e..3426f52 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -7,3 +7,6 @@ parameters: - generate-transfer excludePaths: - tests/*/data/* + ignoreErrors: + - + identifier: propertyGetHook.noRead From 1970e3c60bd53706936be18d081cb67a3e48d391 Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 18:11:09 +0100 Subject: [PATCH 06/10] Updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 210b374..d223e97 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Transfer Object Generator ========================== -Would you like to build Transfer Objects (TO) effortlessly? +Would you like to build Transfer Objects (TO) easily? You're in the right place! Build TOs Using an Array as Blueprint @@ -45,7 +45,7 @@ Check out how it works: Installation ------------ -Easily install via Composer: +Install via Composer: ```bash composer require-dev picamator/transfer-object From 874e37b97fa17b0269a2ca1a78d775b024f29e60 Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 18:25:04 +0100 Subject: [PATCH 07/10] Added Google shopping API content for the definition generator test --- .../DefinitionGeneratorFacadeTest.php | 16 + .../GoogleShoppingContent/PriceTransfer.php | 46 +++ .../GoogleShoppingContent/ProductTransfer.php | 304 ++++++++++++++++++ .../DefinitionGenerator/data/REFERENCE.md | 9 +- .../definition/product.transfer.yml | 58 ++++ .../generator.config.yml | 4 + .../json-samples/google-shopping-content.json | 32 ++ 7 files changed, 465 insertions(+), 4 deletions(-) create mode 100644 tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/PriceTransfer.php create mode 100644 tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/ProductTransfer.php create mode 100644 tests/integration/DefinitionGenerator/data/config/google-shopping-content/definition/product.transfer.yml create mode 100644 tests/integration/DefinitionGenerator/data/config/google-shopping-content/generator.config.yml create mode 100644 tests/integration/DefinitionGenerator/data/json-samples/google-shopping-content.json diff --git a/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php b/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php index 045428b..47af4d3 100644 --- a/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php +++ b/tests/integration/DefinitionGenerator/DefinitionGeneratorFacadeTest.php @@ -8,6 +8,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Depends; use PHPUnit\Framework\TestCase; +use Picamator\Tests\Integration\TransferObject\DefinitionGenerator\Generated\GoogleShoppingContent\ProductTransfer; use Picamator\Tests\Integration\TransferObject\DefinitionGenerator\Generated\NasaNeo\AsteroidTransfer; use Picamator\Tests\Integration\TransferObject\DefinitionGenerator\Generated\OpenWeather\ForecastTransfer; use Picamator\Tests\Integration\TransferObject\Helper\DefinitionGeneratorHelperTrait; @@ -76,6 +77,12 @@ public static function generateDefinitionDataProvider(): Generator 'sampleFileName' => 'open-weather.json', 'definitionFileName' => 'forecast.transfer.yml', ]; + + yield 'Google Shopping Content' => [ + 'className' => 'Product', + 'sampleFileName' => 'google-shopping-content.json', + 'definitionFileName' => 'product.transfer.yml', + ]; } #[DataProvider('configPathDataProvider')] @@ -106,6 +113,10 @@ public static function configPathDataProvider(): Generator yield 'Open Weather Response' => [ 'open-weather.json', ]; + + yield 'Google Shopping Content' => [ + 'google-shopping-content.json', + ]; } #[DataProvider('matchDefinitionDataProvider')] @@ -145,5 +156,10 @@ public static function matchDefinitionDataProvider(): Generator ForecastTransfer::class, 'open-weather.json', ]; + + yield 'Google Shopping Content' => [ + ProductTransfer::class, + 'google-shopping-content.json', + ]; } } diff --git a/tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/PriceTransfer.php b/tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/PriceTransfer.php new file mode 100644 index 0000000..0e18105 --- /dev/null +++ b/tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/PriceTransfer.php @@ -0,0 +1,46 @@ + self::CURRENCY_DATA_NAME, + self::VALUE => self::VALUE_DATA_NAME, + ]; + + // currency + public const string CURRENCY = 'currency'; + protected const string CURRENCY_DATA_NAME = 'CURRENCY'; + protected const int CURRENCY_DATA_INDEX = 0; + + public ?string $currency { + get => $this->getData(self::CURRENCY_DATA_INDEX); + set => $this->setData(self::CURRENCY_DATA_INDEX, $value); + } + + // value + public const string VALUE = 'value'; + protected const string VALUE_DATA_NAME = 'VALUE'; + protected const int VALUE_DATA_INDEX = 1; + + public ?string $value { + get => $this->getData(self::VALUE_DATA_INDEX); + set => $this->setData(self::VALUE_DATA_INDEX, $value); + } +} diff --git a/tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/ProductTransfer.php b/tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/ProductTransfer.php new file mode 100644 index 0000000..f099cec --- /dev/null +++ b/tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent/ProductTransfer.php @@ -0,0 +1,304 @@ + self::AGE_GROUP_DATA_NAME, + self::AVAILABILITY => self::AVAILABILITY_DATA_NAME, + self::AVAILABILITY_DATE => self::AVAILABILITY_DATE_DATA_NAME, + self::BRAND => self::BRAND_DATA_NAME, + self::CHANNEL => self::CHANNEL_DATA_NAME, + self::COLOR => self::COLOR_DATA_NAME, + self::CONDITION => self::CONDITION_DATA_NAME, + self::CONTENT_LANGUAGE => self::CONTENT_LANGUAGE_DATA_NAME, + self::DESCRIPTION => self::DESCRIPTION_DATA_NAME, + self::FEED_LABEL => self::FEED_LABEL_DATA_NAME, + self::GENDER => self::GENDER_DATA_NAME, + self::GOOGLE_PRODUCT_CATEGORY => self::GOOGLE_PRODUCT_CATEGORY_DATA_NAME, + self::GTIN => self::GTIN_DATA_NAME, + self::ID => self::ID_DATA_NAME, + self::IMAGE_LINK => self::IMAGE_LINK_DATA_NAME, + self::ITEM_GROUP_ID => self::ITEM_GROUP_ID_DATA_NAME, + self::KIND => self::KIND_DATA_NAME, + self::LINK => self::LINK_DATA_NAME, + self::MPN => self::MPN_DATA_NAME, + self::OFFER_ID => self::OFFER_ID_DATA_NAME, + self::PRICE => self::PRICE_DATA_NAME, + self::SIZES => self::SIZES_DATA_NAME, + self::SOURCE => self::SOURCE_DATA_NAME, + self::TARGET_COUNTRY => self::TARGET_COUNTRY_DATA_NAME, + self::TITLE => self::TITLE_DATA_NAME, + ]; + + // ageGroup + public const string AGE_GROUP = 'ageGroup'; + protected const string AGE_GROUP_DATA_NAME = 'AGE_GROUP'; + protected const int AGE_GROUP_DATA_INDEX = 0; + + public ?string $ageGroup { + get => $this->getData(self::AGE_GROUP_DATA_INDEX); + set => $this->setData(self::AGE_GROUP_DATA_INDEX, $value); + } + + // availability + public const string AVAILABILITY = 'availability'; + protected const string AVAILABILITY_DATA_NAME = 'AVAILABILITY'; + protected const int AVAILABILITY_DATA_INDEX = 1; + + public ?string $availability { + get => $this->getData(self::AVAILABILITY_DATA_INDEX); + set => $this->setData(self::AVAILABILITY_DATA_INDEX, $value); + } + + // availabilityDate + public const string AVAILABILITY_DATE = 'availabilityDate'; + protected const string AVAILABILITY_DATE_DATA_NAME = 'AVAILABILITY_DATE'; + protected const int AVAILABILITY_DATE_DATA_INDEX = 2; + + public ?string $availabilityDate { + get => $this->getData(self::AVAILABILITY_DATE_DATA_INDEX); + set => $this->setData(self::AVAILABILITY_DATE_DATA_INDEX, $value); + } + + // brand + public const string BRAND = 'brand'; + protected const string BRAND_DATA_NAME = 'BRAND'; + protected const int BRAND_DATA_INDEX = 3; + + public ?string $brand { + get => $this->getData(self::BRAND_DATA_INDEX); + set => $this->setData(self::BRAND_DATA_INDEX, $value); + } + + // channel + public const string CHANNEL = 'channel'; + protected const string CHANNEL_DATA_NAME = 'CHANNEL'; + protected const int CHANNEL_DATA_INDEX = 4; + + public ?string $channel { + get => $this->getData(self::CHANNEL_DATA_INDEX); + set => $this->setData(self::CHANNEL_DATA_INDEX, $value); + } + + // color + public const string COLOR = 'color'; + protected const string COLOR_DATA_NAME = 'COLOR'; + protected const int COLOR_DATA_INDEX = 5; + + public ?string $color { + get => $this->getData(self::COLOR_DATA_INDEX); + set => $this->setData(self::COLOR_DATA_INDEX, $value); + } + + // condition + public const string CONDITION = 'condition'; + protected const string CONDITION_DATA_NAME = 'CONDITION'; + protected const int CONDITION_DATA_INDEX = 6; + + public ?string $condition { + get => $this->getData(self::CONDITION_DATA_INDEX); + set => $this->setData(self::CONDITION_DATA_INDEX, $value); + } + + // contentLanguage + public const string CONTENT_LANGUAGE = 'contentLanguage'; + protected const string CONTENT_LANGUAGE_DATA_NAME = 'CONTENT_LANGUAGE'; + protected const int CONTENT_LANGUAGE_DATA_INDEX = 7; + + public ?string $contentLanguage { + get => $this->getData(self::CONTENT_LANGUAGE_DATA_INDEX); + set => $this->setData(self::CONTENT_LANGUAGE_DATA_INDEX, $value); + } + + // description + public const string DESCRIPTION = 'description'; + protected const string DESCRIPTION_DATA_NAME = 'DESCRIPTION'; + protected const int DESCRIPTION_DATA_INDEX = 8; + + public ?string $description { + get => $this->getData(self::DESCRIPTION_DATA_INDEX); + set => $this->setData(self::DESCRIPTION_DATA_INDEX, $value); + } + + // feedLabel + public const string FEED_LABEL = 'feedLabel'; + protected const string FEED_LABEL_DATA_NAME = 'FEED_LABEL'; + protected const int FEED_LABEL_DATA_INDEX = 9; + + public ?string $feedLabel { + get => $this->getData(self::FEED_LABEL_DATA_INDEX); + set => $this->setData(self::FEED_LABEL_DATA_INDEX, $value); + } + + // gender + public const string GENDER = 'gender'; + protected const string GENDER_DATA_NAME = 'GENDER'; + protected const int GENDER_DATA_INDEX = 10; + + public ?string $gender { + get => $this->getData(self::GENDER_DATA_INDEX); + set => $this->setData(self::GENDER_DATA_INDEX, $value); + } + + // googleProductCategory + public const string GOOGLE_PRODUCT_CATEGORY = 'googleProductCategory'; + protected const string GOOGLE_PRODUCT_CATEGORY_DATA_NAME = 'GOOGLE_PRODUCT_CATEGORY'; + protected const int GOOGLE_PRODUCT_CATEGORY_DATA_INDEX = 11; + + public ?string $googleProductCategory { + get => $this->getData(self::GOOGLE_PRODUCT_CATEGORY_DATA_INDEX); + set => $this->setData(self::GOOGLE_PRODUCT_CATEGORY_DATA_INDEX, $value); + } + + // gtin + public const string GTIN = 'gtin'; + protected const string GTIN_DATA_NAME = 'GTIN'; + protected const int GTIN_DATA_INDEX = 12; + + public ?string $gtin { + get => $this->getData(self::GTIN_DATA_INDEX); + set => $this->setData(self::GTIN_DATA_INDEX, $value); + } + + // id + public const string ID = 'id'; + protected const string ID_DATA_NAME = 'ID'; + protected const int ID_DATA_INDEX = 13; + + public ?string $id { + get => $this->getData(self::ID_DATA_INDEX); + set => $this->setData(self::ID_DATA_INDEX, $value); + } + + // imageLink + public const string IMAGE_LINK = 'imageLink'; + protected const string IMAGE_LINK_DATA_NAME = 'IMAGE_LINK'; + protected const int IMAGE_LINK_DATA_INDEX = 14; + + public ?string $imageLink { + get => $this->getData(self::IMAGE_LINK_DATA_INDEX); + set => $this->setData(self::IMAGE_LINK_DATA_INDEX, $value); + } + + // itemGroupId + public const string ITEM_GROUP_ID = 'itemGroupId'; + protected const string ITEM_GROUP_ID_DATA_NAME = 'ITEM_GROUP_ID'; + protected const int ITEM_GROUP_ID_DATA_INDEX = 15; + + public ?string $itemGroupId { + get => $this->getData(self::ITEM_GROUP_ID_DATA_INDEX); + set => $this->setData(self::ITEM_GROUP_ID_DATA_INDEX, $value); + } + + // kind + public const string KIND = 'kind'; + protected const string KIND_DATA_NAME = 'KIND'; + protected const int KIND_DATA_INDEX = 16; + + public ?string $kind { + get => $this->getData(self::KIND_DATA_INDEX); + set => $this->setData(self::KIND_DATA_INDEX, $value); + } + + // link + public const string LINK = 'link'; + protected const string LINK_DATA_NAME = 'LINK'; + protected const int LINK_DATA_INDEX = 17; + + public ?string $link { + get => $this->getData(self::LINK_DATA_INDEX); + set => $this->setData(self::LINK_DATA_INDEX, $value); + } + + // mpn + public const string MPN = 'mpn'; + protected const string MPN_DATA_NAME = 'MPN'; + protected const int MPN_DATA_INDEX = 18; + + public ?string $mpn { + get => $this->getData(self::MPN_DATA_INDEX); + set => $this->setData(self::MPN_DATA_INDEX, $value); + } + + // offerId + public const string OFFER_ID = 'offerId'; + protected const string OFFER_ID_DATA_NAME = 'OFFER_ID'; + protected const int OFFER_ID_DATA_INDEX = 19; + + public ?string $offerId { + get => $this->getData(self::OFFER_ID_DATA_INDEX); + set => $this->setData(self::OFFER_ID_DATA_INDEX, $value); + } + + // price + #[PropertyTypeAttribute(PriceTransfer::class)] + public const string PRICE = 'price'; + protected const string PRICE_DATA_NAME = 'PRICE'; + protected const int PRICE_DATA_INDEX = 20; + + public ?PriceTransfer $price { + get => $this->getData(self::PRICE_DATA_INDEX); + set => $this->setData(self::PRICE_DATA_INDEX, $value); + } + + // sizes + #[ArrayPropertyTypeAttribute] + public const string SIZES = 'sizes'; + protected const string SIZES_DATA_NAME = 'SIZES'; + protected const int SIZES_DATA_INDEX = 21; + + /** @var array */ + public array $sizes { + get => $this->getData(self::SIZES_DATA_INDEX); + set => $this->setData(self::SIZES_DATA_INDEX, $value); + } + + // source + public const string SOURCE = 'source'; + protected const string SOURCE_DATA_NAME = 'SOURCE'; + protected const int SOURCE_DATA_INDEX = 22; + + public ?string $source { + get => $this->getData(self::SOURCE_DATA_INDEX); + set => $this->setData(self::SOURCE_DATA_INDEX, $value); + } + + // targetCountry + public const string TARGET_COUNTRY = 'targetCountry'; + protected const string TARGET_COUNTRY_DATA_NAME = 'TARGET_COUNTRY'; + protected const int TARGET_COUNTRY_DATA_INDEX = 23; + + public ?string $targetCountry { + get => $this->getData(self::TARGET_COUNTRY_DATA_INDEX); + set => $this->setData(self::TARGET_COUNTRY_DATA_INDEX, $value); + } + + // title + public const string TITLE = 'title'; + protected const string TITLE_DATA_NAME = 'TITLE'; + protected const int TITLE_DATA_INDEX = 24; + + public ?string $title { + get => $this->getData(self::TITLE_DATA_INDEX); + set => $this->setData(self::TITLE_DATA_INDEX, $value); + } +} diff --git a/tests/integration/DefinitionGenerator/data/REFERENCE.md b/tests/integration/DefinitionGenerator/data/REFERENCE.md index da81173..9d7aac6 100644 --- a/tests/integration/DefinitionGenerator/data/REFERENCE.md +++ b/tests/integration/DefinitionGenerator/data/REFERENCE.md @@ -1,7 +1,8 @@ REFERENCE ========= -| File | Source | -|--------------------------------------------------------------------------------------|--------------------------------------------------------------------------------| -| [nasa-neo-rest-v1-neo-2465633.json](/json-samples/nasa-neo-rest-v1-neo-2465633.json) | [NASA Open Api](https://api.nasa.gov/neo/rest/v1/neo/2465633?api_key=DEMO_KEY) | -| [open-weather.json](/json-samples/open-weather.json) | [OpenWeather](https://openweathermap.org/current#example_JSON) | +| File | Source | +|--------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| +| [nasa-neo-rest-v1-neo-2465633.json](/json-samples/nasa-neo-rest-v1-neo-2465633.json) | [NASA Open Api](https://api.nasa.gov/neo/rest/v1/neo/2465633?api_key=DEMO_KEY) | +| [open-weather.json](/json-samples/open-weather.json) | [OpenWeather](https://openweathermap.org/current#example_JSON) | +| [google-shopping-content-api.json](/json-samples/google-shopping-content-api.json) | [Content API for Shopping](https://developers.google.com/shopping-content/guides/products/products-api?hl=en) | diff --git a/tests/integration/DefinitionGenerator/data/config/google-shopping-content/definition/product.transfer.yml b/tests/integration/DefinitionGenerator/data/config/google-shopping-content/definition/product.transfer.yml new file mode 100644 index 0000000..2835791 --- /dev/null +++ b/tests/integration/DefinitionGenerator/data/config/google-shopping-content/definition/product.transfer.yml @@ -0,0 +1,58 @@ +Product: + kind: + type: string + id: + type: string + offerId: + type: string + source: + type: string + title: + type: string + description: + type: string + link: + type: string + imageLink: + type: string + contentLanguage: + type: string + targetCountry: + type: string + feedLabel: + type: string + channel: + type: string + ageGroup: + type: string + availability: + type: string + availabilityDate: + type: string + brand: + type: string + color: + type: string + condition: + type: string + gender: + type: string + googleProductCategory: + type: string + gtin: + type: string + itemGroupId: + type: string + mpn: + type: string + price: + type: Price + sizes: + type: array + +Price: + value: + type: string + currency: + type: string + diff --git a/tests/integration/DefinitionGenerator/data/config/google-shopping-content/generator.config.yml b/tests/integration/DefinitionGenerator/data/config/google-shopping-content/generator.config.yml new file mode 100644 index 0000000..8aaae95 --- /dev/null +++ b/tests/integration/DefinitionGenerator/data/config/google-shopping-content/generator.config.yml @@ -0,0 +1,4 @@ +generator: + transferNamespace: "Picamator\\Tests\\Integration\\TransferObject\\DefinitionGenerator\\Generated\\GoogleShoppingContent" + transferPath: "${PROJECT_ROOT}/tests/integration/DefinitionGenerator/Generated/GoogleShoppingContent" + definitionPath: "${PROJECT_ROOT}/tests/integration/DefinitionGenerator/data/config/google-shopping-content/definition" diff --git a/tests/integration/DefinitionGenerator/data/json-samples/google-shopping-content.json b/tests/integration/DefinitionGenerator/data/json-samples/google-shopping-content.json new file mode 100644 index 0000000..52b9eef --- /dev/null +++ b/tests/integration/DefinitionGenerator/data/json-samples/google-shopping-content.json @@ -0,0 +1,32 @@ +{ + "kind": "content#product", + "id": "online:en:US:1111111111", + "offerId": "1111111111", + "source": "api", + "title": "Google Tee Black", + "description": "The Black Google Tee is available in unisex sizing.", + "link": "http://my.site.com/blacktee/", + "imageLink": "https://shop.example.com/.../images/GGOEGXXX1100.jpg", + "contentLanguage": "en", + "targetCountry": "US", + "feedLabel": "US", + "channel": "online", + "ageGroup": "adult", + "availability": "in stock", + "availabilityDate": "2019-01-25T13:00:00-08:00", + "brand": "Google", + "color": "black", + "condition": "new", + "gender": "male", + "googleProductCategory": "1604", + "gtin": "608802531656", + "itemGroupId": "google_tee", + "mpn": "608802531656", + "price": { + "value": "21.99", + "currency": "USD" + }, + "sizes": [ + "Large" + ] +} From 3c81a41e532b47ed0d0be7418baba8af5b0fb5d3 Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 18:30:46 +0100 Subject: [PATCH 08/10] Added CONTRIBUTING.md to export-ignore --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index b7fb024..3ac8da4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,7 @@ /.gitattributes export-ignore /.gitignore export-ignore /captainhook.json export-ignore +/CONTRIBUTING.md export-ignore /docker-compose.yml export-ignore /phpcs.xml export-ignore /phpstan.neon export-ignore From 3c7b81d37aeb89d76127446ca041d7571c86936d Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 18:31:25 +0100 Subject: [PATCH 09/10] Added diff driver for php files --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 3ac8da4..f00fca9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ * eol=lf * text=auto +*.php diff=php /.github export-ignore /doc/ export-ignore From c1339c3b90d1f04445bb4f15a7ebb415b6b8b8b1 Mon Sep 17 00:00:00 2001 From: Sergii Pryz Date: Wed, 1 Jan 2025 18:38:49 +0100 Subject: [PATCH 10/10] Actualized readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d223e97..ef4dbfb 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,8 @@ Installation Install via Composer: -```bash -composer require-dev picamator/transfer-object +```shell +$ composer require-dev picamator/transfer-object ``` Usage @@ -60,8 +60,8 @@ Transfer Object (TO) generator can be used in two ways: Run following command, specifying your configuration file: -```bash -./vendor/bin/generate-transfer [-c|--configuration CONFIGURATION] +```shell +$ ./vendor/bin/generate-transfer [-c|--configuration CONFIGURATION] ``` For more details are in Wiki: