Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ Code Style

### Tests

- all tests classes should be a `final`
- tests classes should be a `final`
- tests should have at least one test group

Module Structure
----------------
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,12 @@ Usage Tests
Definition Files and Transfer Object generators have been tested against the following APIs:

* [NASA Open Api](https://api.nasa.gov/neo/rest/v1/neo/2465633?api_key=DEMO_KEY)
* [OpenWeather](https://openweathermap.org/current#example_JSON)
* [Content API for Shopping](https://developers.google.com/shopping-content/guides/products/products-api?hl=en)
* [Frankfurter is a free, open-source currency data API](https://api.frankfurter.dev/v1/latest)
* [OpenWeather](https://openweathermap.org/current?collection=current_forecast#example_JSON)
* [Google Content API for Shopping](https://developers.google.com/shopping-content/guides/products/products-api?hl=en)
* [Frankfurter - open-source currency data API](https://api.frankfurter.dev/v1/latest)
* [Tagesschau API](https://tagesschau.api.bund.dev)
* [Statistisches Bundesamt (Destatis)](https://www-genesis.destatis.de/genesisWS/swagger-ui/index.html#/find/findPost)
* [Wero - Digital Payment Wallet](https://developerhub.ppro.com/global-api/docs/wero)

### Scenario

Expand Down
25 changes: 14 additions & 11 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions docker/sdk
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,14 @@ case $1 in
docker compose stop
;;
cli)
if [ -n "$2" ]; then
$DOCKER_EXEC php -f $2
if [ -n "$5" ]; then
$DOCKER_EXEC php "$2" "$3" "$4" "$5"
elif [ -n "$4" ]; then
$DOCKER_EXEC php "$2" "$3" "$4"
elif [ -n "$3" ]; then
$DOCKER_EXEC php "$2" "$3"
elif [ -n "$2" ]; then
$DOCKER_EXEC php $2
else
$DOCKER_EXEC bash
fi
Expand Down
35 changes: 19 additions & 16 deletions src/Command/TransferGeneratorCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,22 @@ private function generateTransfers(SymfonyStyle $io, string $configPath): bool
}

$this->writelnErrorMessages($io, $generatorTransfer);
$this->writelnDebugMessages($io, $generatorTransfer);
if ($this->isDebugMessages($io, $generatorTransfer)) {
$lastFileName ??= $generatorTransfer->fileName;
$this->writelnDebugMessages($io, $generatorTransfer, $lastFileName);
}
}

return $generatorFiber->getReturn();
}

private function writelnDebugMessages(SymfonyStyle $io, TransferGeneratorTransfer $generatorTransfer): void
{
if (
!$io->isVerbose()
|| $generatorTransfer->validator->isValid === false
|| $generatorTransfer->fileName === null
|| $generatorTransfer->className === null
) {
return;
}

static $fileName = $generatorTransfer->fileName;

if ($fileName !== $generatorTransfer->fileName) {
$fileName = $generatorTransfer->fileName;
private function writelnDebugMessages(
SymfonyStyle $io,
TransferGeneratorTransfer $generatorTransfer,
?string &$lastFileName,
): void {
if ($lastFileName !== $generatorTransfer->fileName) {
$lastFileName = $generatorTransfer->fileName;

$io->newLine();
}
Expand All @@ -156,6 +151,14 @@ private function writelnDebugMessages(SymfonyStyle $io, TransferGeneratorTransfe
);
}

private function isDebugMessages(SymfonyStyle $io, TransferGeneratorTransfer $generatorTransfer): bool
{
return $io->isVerbose()
&& $generatorTransfer->validator->isValid === true
&& $generatorTransfer->fileName !== null
&& $generatorTransfer->className !== null;
}

private function writelnErrorMessages(SymfonyStyle $io, TransferGeneratorTransfer $generatorTransfer): void
{
if ($generatorTransfer->validator->isValid === true) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,13 @@ private function createDateTimePropertyTransfer(string $propertyName): Definitio

private function createPropertyTransfer(string $propertyName, string $builtInType): DefinitionPropertyTransfer
{
$tapeWithDocBlock = $this->parseTypeWithDocBlock($builtInType) ?? [];
$typeDocBlock = $this->parseTypeWithDocBlock($builtInType);

/** @var string $type */
$type = array_key_first($tapeWithDocBlock);
$type = BuiltInTypeEnum::from($type);

$docBlock = array_first($tapeWithDocBlock);
$type = BuiltInTypeEnum::from($typeDocBlock->type);

$builtInTypeTransfer = new DefinitionBuiltInTypeTransfer();
$builtInTypeTransfer->name = $type;
$builtInTypeTransfer->docBlock = $docBlock;
$builtInTypeTransfer->docBlock = $typeDocBlock->docBlock;

$propertyTransfer = new DefinitionPropertyTransfer();
$propertyTransfer->propertyName = $propertyName;
Expand Down
4 changes: 2 additions & 2 deletions src/Shared/Filesystem/FileAppender.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function appendToFile(string $filename, string $content): void

if ($writeResult === false) {
throw new FileAppenderException(
sprintf('Failed to write content into the file "%s".', $filename),
sprintf('Failed to write content to file "%s".', $filename),
);
}
}
Expand All @@ -35,7 +35,7 @@ public function closeFile(string $filename): void
$isClosed = $this->fclose($file);
if ($isClosed === false) {
throw new FileAppenderException(
sprintf('Failed to close the file "%s".', $filename),
sprintf('Failed to close file "%s".', $filename),
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Shared/Filesystem/FileReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private function assertEndOfFile($file, string $filename, int $fileLine): void
$this->fclose($file);

throw new FileReaderException(
sprintf('Failed to read file "%s" line "%d".', $filename, $fileLine),
sprintf('Failed to read file "%s" at line "%d".', $filename, $fileLine),
);
}

Expand Down
23 changes: 8 additions & 15 deletions src/Shared/Parser/DocBlockParserTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,17 @@

trait DocBlockParserTrait
{
private const string TYPE_KEY = 'type';
private const string DOCK_BLOCK_REGEX = '#^(?<type>[^<> ]+)\s*(?<docBlock><.+>)$#';

private const string DOC_BLOCK_KEY = 'docBlock';

private const string TYPE_REGEX = '#(?<type>[^<>]*)(?<docBlock>.*)#';

/**
* @return array<string,string|null>|null
*/
final protected function parseTypeWithDocBlock(string $type): ?array
final protected function parseTypeWithDocBlock(string $type): TypeDocBlock
{
if (preg_match(self::TYPE_REGEX, $type, $matches) === false) {
return null;
if (!str_contains($type, '<') || preg_match(self::DOCK_BLOCK_REGEX, $type, $matches) !== 1) {
return new TypeDocBlock(type: $type);
}

$type = $matches[self::TYPE_KEY] ?? '';
$docBlock = $matches[self::DOC_BLOCK_KEY] ?? null;

return [$type => $docBlock];
return new TypeDocBlock(
type: $matches['type'],
docBlock: $matches['docBlock'],
);
}
}
14 changes: 14 additions & 0 deletions src/Shared/Parser/TypeDocBlock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

declare(strict_types=1);

namespace Picamator\TransferObject\Shared\Parser;

readonly class TypeDocBlock
{
public function __construct(
public string $type,
public ?string $docBlock = null,
) {
}
}
4 changes: 2 additions & 2 deletions src/Shared/Reader/FileReaderProgress.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ private function getTotalBytes(string $filename): int
if ($fileSize === false) {
throw new FileReaderException(
sprintf(
'Failed to get file size "%s". Error: "%s".',
'Failed to get size for file "%s". Error: "%s".',
$filename,
error_get_last()['message'] ?? '',
error_get_last()['message'] ?? 'Unknown error.',
),
);
}
Expand Down
7 changes: 4 additions & 3 deletions src/Transfer/Adapter/TransferAdapterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ trait TransferAdapterTrait
*/
private ?WeakReference $_reflectionObjectReference = null;

private static bool $_isBcMathLoaded;

/**
* @return \Traversable<string, mixed>
*/
Expand Down Expand Up @@ -262,9 +264,8 @@ private function isBcMathType(mixed $type): bool

private function isBcMathLoaded(): bool
{
/** @var bool $isLoaded */
static $isLoaded = \extension_loaded('bcmath');
self::$_isBcMathLoaded ??= \extension_loaded('bcmath');

return $isLoaded;
return self::$_isBcMathLoaded;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ final class AttributesPropertyExpander implements PropertyExpanderInterface

private const string ATTRIBUTES_KEY = 'attributes';

private const string ATTRIBUTES_REGEX = '#(?<namespace>[^()]*)(?<arguments>.*)#';
private const string ATTRIBUTES_REGEX = '#^(?<namespace>[^()]+)\s*(?<arguments>.*)$#';

public function __construct(
private readonly NamespaceBuilderInterface $namespaceBuilder,
Expand Down Expand Up @@ -51,15 +51,14 @@ protected function handleExpander(array $matchedType, DefinitionPropertyTransfer

private function getAttributeTransfer(string $attribute): ?DefinitionAttributeTransfer
{
if (preg_match(self::ATTRIBUTES_REGEX, $attribute, $matches) === false) {
if (preg_match(self::ATTRIBUTES_REGEX, $attribute, $matches) !== 1) {
return null;
}

$namespace = $matches['namespace'] ?? '';
$namespaceTransfer = $this->namespaceBuilder->createNamespaceTransfer($namespace);
$namespaceTransfer = $this->namespaceBuilder->createNamespaceTransfer($matches['namespace']);

$builtInTypeTransfer = new DefinitionAttributeTransfer();
$builtInTypeTransfer->arguments = $matches['arguments'] ?? null;
$builtInTypeTransfer->arguments = $matches['arguments'];
$builtInTypeTransfer->namespace = $namespaceTransfer;

return $builtInTypeTransfer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ final class TypePropertyExpander extends AbstractPropertyExpander
{
use DocBlockParserTrait;

private const string TYPE_KEY = 'type';

public function __construct(
private readonly EmbeddedTypeBuilderInterface $typeBuilder,
) {
Expand Down Expand Up @@ -41,22 +43,16 @@ protected function handleExpander(string $matchedType, DefinitionPropertyTransfe

private function getBuiltInTypeTransfer(string $matchedType): ?DefinitionBuiltInTypeTransfer
{
$tapeWithDocBlock = $this->parseTypeWithDocBlock($matchedType);
if ($tapeWithDocBlock === null) {
return null;
}

/** @var string $type */
$type = array_key_first($tapeWithDocBlock);
$type = BuiltInTypeEnum::tryFrom($type);
$typeDocBlock = $this->parseTypeWithDocBlock($matchedType);
$type = BuiltInTypeEnum::tryFrom($typeDocBlock->type);

if ($type === null) {
return null;
}

$builtInTypeTransfer = new DefinitionBuiltInTypeTransfer();
$builtInTypeTransfer->name = $type;
$builtInTypeTransfer->docBlock = array_first($tapeWithDocBlock);
$builtInTypeTransfer->docBlock = $typeDocBlock->docBlock;

return $builtInTypeTransfer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use Picamator\TransferObject\Generated\ValidatorMessageTransfer;
use Picamator\TransferObject\Shared\Validator\ValidatorMessageTrait;

readonly class NumberTypePropertyValidator implements PropertyValidatorInterface
class NumberTypePropertyValidator implements PropertyValidatorInterface
{
use ValidatorMessageTrait;

Expand All @@ -19,6 +19,8 @@
private const string EXTENSION_IS_NOT_LOADED_ERROR
= 'PHP extension BCMath was not loaded. Please install and load extension.';

private static bool $isBcMathLoaded;

public function isApplicable(DefinitionPropertyTransfer $propertyTransfer): bool
{
return $propertyTransfer->numberType !== null;
Expand Down Expand Up @@ -57,9 +59,8 @@ private function getErrorMessage(DefinitionPropertyTransfer $propertyTransfer):

protected function isBcMathLoaded(): bool
{
/** @var bool $isLoaded */
static $isLoaded = extension_loaded('bcmath');
self::$isBcMathLoaded ??= extension_loaded('bcmath');

return $isLoaded;
return self::$isBcMathLoaded;
}
}
Loading