From a79791a972e4e20405564558d07189db80b51765 Mon Sep 17 00:00:00 2001 From: Simon Kuehn Date: Tue, 19 May 2026 10:56:37 +0000 Subject: [PATCH] style: apply CS Fixer formatting across codebase Consistent brace style, spacing, and method expansion throughout domain, infrastructure, and test files. Co-Authored-By: Claude Sonnet 4.6 --- src/Application/Article/PhotoService.php | 3 - src/Domain/Article/Article.php | 1 + src/Domain/Article/ArticleType.php | 21 ++++--- src/Domain/Article/ArticleTypeEbayMapping.php | 58 ++++++++++++----- src/Domain/I18n/Translation.php | 52 +++++++++++++--- src/Infrastructure/AI/Agent/EbayTextAgent.php | 4 +- .../AI/Agent/SpecsResearchAgent.php | 4 +- src/Infrastructure/AI/MistralClient.php | 2 +- .../Channel/Frappe/FrappeErpAdapter.php | 2 +- .../Console/CreateApiKeyCommand.php | 2 +- .../Admin/AIPipelineJobCrudController.php | 4 +- .../Admin/ArticleTypeCrudController.php | 8 +-- .../Admin/EbayAspectImportController.php | 62 +++++++++---------- .../Admin/PipelineStreamController.php | 40 +++++------- .../Admin/PromptTemplateCrudController.php | 2 +- .../Admin/TranslationCrudController.php | 2 +- .../Http/Form/StringArrayType.php | 4 +- .../Messenger/Handler/DraftArticleHandler.php | 2 +- .../Messenger/Handler/PhotoUploadHandler.php | 2 +- .../DoctrineTranslationRepository.php | 4 +- .../Security/PermissionVoter.php | 8 +-- .../Translation/DatabaseTranslator.php | 6 +- .../Ebay/EbayTaxonomyIntegrationTest.php | 18 +++--- .../Frappe/FrappeCustomerIntegrationTest.php | 8 +-- .../FrappeErpAdapterIntegrationTest.php | 6 +- .../ArticleTypeRequiredAttributesTest.php | 1 - .../Article/AttributeDefinitionTest.php | 4 +- tests/Unit/Domain/Auth/ApiKeyTest.php | 2 +- .../AI/Agent/JsonCodingAgentTest.php | 4 +- .../AI/Agent/OllamaVisionAgentTest.php | 8 +-- .../Infrastructure/AI/MistralClientTest.php | 8 +-- .../Admin/ArticleTypeCrudControllerTest.php | 4 +- .../AttributeDefinitionCrudControllerTest.php | 2 +- .../Channel/Ebay/EbayWebhookVerifierTest.php | 6 +- .../Channel/Frappe/FrappeErpAdapterTest.php | 14 ++--- .../Console/CreateApiKeyCommandTest.php | 6 +- .../Order/CustomerResolverTest.php | 6 +- 37 files changed, 223 insertions(+), 167 deletions(-) diff --git a/src/Application/Article/PhotoService.php b/src/Application/Article/PhotoService.php index cab8722..6e899db 100644 --- a/src/Application/Article/PhotoService.php +++ b/src/Application/Article/PhotoService.php @@ -57,9 +57,6 @@ final class PhotoService } } - /** - * @param list $orderedPhotoIds UUIDs in the desired display order - */ /** * Attach a file that was already stored (e.g. uploaded at ingest time) to an article. * diff --git a/src/Domain/Article/Article.php b/src/Domain/Article/Article.php index e0d4657..e1db03e 100644 --- a/src/Domain/Article/Article.php +++ b/src/Domain/Article/Article.php @@ -200,6 +200,7 @@ class Article foreach ($this->attributeValues as $existing) { if ($existing->getAttributeDefinition()->getId()->equals($value->getAttributeDefinition()->getId())) { $existing->setValue($value->getValue()); + return; } } diff --git a/src/Domain/Article/ArticleType.php b/src/Domain/Article/ArticleType.php index b1edb85..af54f4a 100644 --- a/src/Domain/Article/ArticleType.php +++ b/src/Domain/Article/ArticleType.php @@ -88,6 +88,7 @@ class ArticleType $existing->setArticleFieldKey($mapping->getArticleFieldKey()); $existing->setAttributeDefinition($mapping->getAttributeDefinition()); $existing->setRequired($mapping->isRequired()); + return; } } @@ -105,7 +106,7 @@ class ArticleType public function getAttributeDefinitions(): Collection { return $this->attributeAssignments->map( - fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition() + static fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition() ); } @@ -113,8 +114,8 @@ class ArticleType public function getRequiredAttributeDefinitions(): Collection { return $this->attributeAssignments - ->filter(fn (ArticleTypeAttribute $a) => $a->isRequired()) - ->map(fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition()); + ->filter(static fn (ArticleTypeAttribute $a) => $a->isRequired()) + ->map(static fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition()); } // ------------------------------------------------------------------------- @@ -125,15 +126,15 @@ class ArticleType public function getRequiredAttributeDefs(): Collection { return $this->attributeAssignments - ->filter(fn (ArticleTypeAttribute $a) => $a->isRequired()) - ->map(fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition()); + ->filter(static fn (ArticleTypeAttribute $a) => $a->isRequired()) + ->map(static fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition()); } /** @param iterable $defs */ public function setRequiredAttributeDefs(iterable $defs): void { /** @var list $list */ - $list = $defs instanceof Collection ? $defs->toArray() : \iterator_to_array($defs, false); + $list = $defs instanceof Collection ? $defs->toArray() : iterator_to_array($defs, false); $this->pendingRequired = $list; } @@ -141,15 +142,15 @@ class ArticleType public function getOptionalAttributeDefs(): Collection { return $this->attributeAssignments - ->filter(fn (ArticleTypeAttribute $a) => !$a->isRequired()) - ->map(fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition()); + ->filter(static fn (ArticleTypeAttribute $a) => !$a->isRequired()) + ->map(static fn (ArticleTypeAttribute $a) => $a->getAttributeDefinition()); } /** @param iterable $defs */ public function setOptionalAttributeDefs(iterable $defs): void { /** @var list $list */ - $list = $defs instanceof Collection ? $defs->toArray() : \iterator_to_array($defs, false); + $list = $defs instanceof Collection ? $defs->toArray() : iterator_to_array($defs, false); $this->pendingOptional = $list; } @@ -159,7 +160,7 @@ class ArticleType */ public function applyAttributeAssignments(): void { - if ($this->pendingRequired === null && $this->pendingOptional === null) { + if (null === $this->pendingRequired && null === $this->pendingOptional) { return; } diff --git a/src/Domain/Article/ArticleTypeEbayMapping.php b/src/Domain/Article/ArticleTypeEbayMapping.php index 5f468fd..a1ab399 100644 --- a/src/Domain/Article/ArticleTypeEbayMapping.php +++ b/src/Domain/Article/ArticleTypeEbayMapping.php @@ -18,7 +18,7 @@ use Symfony\Component\Uid\Uuid; class ArticleTypeEbayMapping { public const SOURCE_ARTICLE_FIELD = 'article_field'; - public const SOURCE_ATTRIBUTE = 'attribute'; + public const SOURCE_ATTRIBUTE = 'attribute'; #[ORM\Id] #[ORM\Column(type: 'uuid')] @@ -46,31 +46,61 @@ class ArticleTypeEbayMapping public function __construct(ArticleType $articleType, string $ebayAspectName, string $sourceType) { - $this->id = Uuid::v7(); - $this->articleType = $articleType; + $this->id = Uuid::v7(); + $this->articleType = $articleType; $this->ebayAspectName = $ebayAspectName; - $this->sourceType = $sourceType; + $this->sourceType = $sourceType; } - public function getId(): Uuid { return $this->id; } + public function getId(): Uuid + { + return $this->id; + } - public function getArticleType(): ArticleType { return $this->articleType; } + public function getArticleType(): ArticleType + { + return $this->articleType; + } - public function getEbayAspectName(): string { return $this->ebayAspectName; } + public function getEbayAspectName(): string + { + return $this->ebayAspectName; + } - public function getSourceType(): string { return $this->sourceType; } + public function getSourceType(): string + { + return $this->sourceType; + } - public function getArticleFieldKey(): ?string { return $this->articleFieldKey; } + public function getArticleFieldKey(): ?string + { + return $this->articleFieldKey; + } - public function setArticleFieldKey(?string $key): void { $this->articleFieldKey = $key; } + public function setArticleFieldKey(?string $key): void + { + $this->articleFieldKey = $key; + } - public function getAttributeDefinition(): ?AttributeDefinition { return $this->attributeDefinition; } + public function getAttributeDefinition(): ?AttributeDefinition + { + return $this->attributeDefinition; + } - public function setAttributeDefinition(?AttributeDefinition $def): void { $this->attributeDefinition = $def; } + public function setAttributeDefinition(?AttributeDefinition $def): void + { + $this->attributeDefinition = $def; + } - public function isRequired(): bool { return $this->required; } + public function isRequired(): bool + { + return $this->required; + } - public function setRequired(bool $required): void { $this->required = $required; } + public function setRequired(bool $required): void + { + $this->required = $required; + } public function getSourceLabel(): string { diff --git a/src/Domain/I18n/Translation.php b/src/Domain/I18n/Translation.php index d06569f..306a1f5 100644 --- a/src/Domain/I18n/Translation.php +++ b/src/Domain/I18n/Translation.php @@ -37,14 +37,48 @@ class Translation $this->value = $value; } - public function getId(): Uuid { return $this->id; } - public function getLocale(): string { return $this->locale; } - public function getDomain(): string { return $this->domain; } - public function getKey(): string { return $this->key; } - public function getValue(): string { return $this->value; } + public function getId(): Uuid + { + return $this->id; + } - public function setLocale(string $locale): void { $this->locale = $locale; } - public function setDomain(string $domain): void { $this->domain = $domain; } - public function setKey(string $key): void { $this->key = $key; } - public function setValue(string $value): void { $this->value = $value; } + public function getLocale(): string + { + return $this->locale; + } + + public function getDomain(): string + { + return $this->domain; + } + + public function getKey(): string + { + return $this->key; + } + + public function getValue(): string + { + return $this->value; + } + + public function setLocale(string $locale): void + { + $this->locale = $locale; + } + + public function setDomain(string $domain): void + { + $this->domain = $domain; + } + + public function setKey(string $key): void + { + $this->key = $key; + } + + public function setValue(string $value): void + { + $this->value = $value; + } } diff --git a/src/Infrastructure/AI/Agent/EbayTextAgent.php b/src/Infrastructure/AI/Agent/EbayTextAgent.php index bf4f2b8..bf91102 100644 --- a/src/Infrastructure/AI/Agent/EbayTextAgent.php +++ b/src/Infrastructure/AI/Agent/EbayTextAgent.php @@ -45,9 +45,9 @@ final class EbayTextAgent $modelNumber = $article->getModelNumber() ?? ''; $deviceLabel = trim("{$manufacturer} {$modelName} {$modelNumber}") ?: $typeName; - $specsSection = $attributeText !== '' + $specsSection = '' !== $attributeText ? "Known attributes:\n{$attributeText}" - : ($specsText !== '' ? "Research notes:\n".mb_substr($specsText, 0, 1500) : ''); + : ('' !== $specsText ? "Research notes:\n".mb_substr($specsText, 0, 1500) : ''); $titlePrompt = $this->prompts->render('ebay_title', [ 'typeName' => $typeName, diff --git a/src/Infrastructure/AI/Agent/SpecsResearchAgent.php b/src/Infrastructure/AI/Agent/SpecsResearchAgent.php index 3e05080..8919abd 100644 --- a/src/Infrastructure/AI/Agent/SpecsResearchAgent.php +++ b/src/Infrastructure/AI/Agent/SpecsResearchAgent.php @@ -25,7 +25,7 @@ final class SpecsResearchAgent */ public function research(string $modelName, string $articleTypeName, string $manufacturer = '', array $attributeFields = []): array { - $subject = trim(($manufacturer !== '' ? $manufacturer.' ' : '').$modelName); + $subject = trim(('' !== $manufacturer ? $manufacturer.' ' : '').$modelName); $searchResults = $this->search->search("{$subject} {$articleTypeName} specifications"); @@ -36,7 +36,7 @@ final class SpecsResearchAgent $prompt = $this->prompts->render('specs_research', [ 'articleType' => $articleTypeName, 'subject' => $subject, - 'searchResults' => $searchResults !== '' ? $searchResults : 'No web results available.', + 'searchResults' => '' !== $searchResults ? $searchResults : 'No web results available.', 'fields' => $fieldsList, ]); diff --git a/src/Infrastructure/AI/MistralClient.php b/src/Infrastructure/AI/MistralClient.php index cae4427..1330bd5 100644 --- a/src/Infrastructure/AI/MistralClient.php +++ b/src/Infrastructure/AI/MistralClient.php @@ -129,7 +129,7 @@ final class MistralClient implements OllamaClientInterface private function guessMimeType(string $path): string { - return match (strtolower(pathinfo($path, PATHINFO_EXTENSION))) { + return match (strtolower(pathinfo($path, \PATHINFO_EXTENSION))) { 'jpg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', diff --git a/src/Infrastructure/Channel/Frappe/FrappeErpAdapter.php b/src/Infrastructure/Channel/Frappe/FrappeErpAdapter.php index 52c2dba..af50f62 100644 --- a/src/Infrastructure/Channel/Frappe/FrappeErpAdapter.php +++ b/src/Infrastructure/Channel/Frappe/FrappeErpAdapter.php @@ -127,7 +127,7 @@ final class FrappeErpAdapter implements ErpAdapterInterface */ private function addressMatches(array $addr, string $street, string $city, string $zip): bool { - $n = static fn(string $s): string => mb_strtolower(trim($s)); + $n = static fn (string $s): string => mb_strtolower(trim($s)); return $n($addr['address_line1'] ?? '') === $n($street) && $n($addr['city'] ?? '') === $n($city) diff --git a/src/Infrastructure/Console/CreateApiKeyCommand.php b/src/Infrastructure/Console/CreateApiKeyCommand.php index cc2fd88..a68a3e2 100644 --- a/src/Infrastructure/Console/CreateApiKeyCommand.php +++ b/src/Infrastructure/Console/CreateApiKeyCommand.php @@ -50,7 +50,7 @@ final class CreateApiKeyCommand extends Command $rawKey = bin2hex(random_bytes(24)); $prefix = substr($rawKey, 0, 8); - $keyHash = password_hash($rawKey, PASSWORD_BCRYPT); + $keyHash = password_hash($rawKey, \PASSWORD_BCRYPT); $apiKey = new ApiKey($user, $label, $prefix, $keyHash); $this->apiKeyRepository->save($apiKey); diff --git a/src/Infrastructure/Http/Controller/Admin/AIPipelineJobCrudController.php b/src/Infrastructure/Http/Controller/Admin/AIPipelineJobCrudController.php index bce23ec..06d1e29 100644 --- a/src/Infrastructure/Http/Controller/Admin/AIPipelineJobCrudController.php +++ b/src/Infrastructure/Http/Controller/Admin/AIPipelineJobCrudController.php @@ -10,10 +10,11 @@ use App\Infrastructure\Messenger\Message\JsonCodingMessage; use App\Infrastructure\Messenger\Message\PhotoUploadMessage; use App\Infrastructure\Messenger\Message\SpecsResearchMessage; use App\Infrastructure\Messenger\Message\ValidationMessage; +use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\QueryBuilder; +use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminRoute; use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection; -use EasyCorp\Bundle\EasyAdminBundle\Attribute\AdminRoute; use EasyCorp\Bundle\EasyAdminBundle\Config\Action; use EasyCorp\Bundle\EasyAdminBundle\Config\Actions; use EasyCorp\Bundle\EasyAdminBundle\Config\Crud; @@ -27,7 +28,6 @@ use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField; use EasyCorp\Bundle\EasyAdminBundle\Field\TextField; use EasyCorp\Bundle\EasyAdminBundle\Orm\EntityRepository; -use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Messenger\MessageBusInterface; use Symfony\Component\Translation\TranslatableMessage; diff --git a/src/Infrastructure/Http/Controller/Admin/ArticleTypeCrudController.php b/src/Infrastructure/Http/Controller/Admin/ArticleTypeCrudController.php index cd72e90..4f25a16 100644 --- a/src/Infrastructure/Http/Controller/Admin/ArticleTypeCrudController.php +++ b/src/Infrastructure/Http/Controller/Admin/ArticleTypeCrudController.php @@ -62,7 +62,7 @@ final class ArticleTypeCrudController extends AbstractCrudController yield TextField::new('name', 'Name'); yield TextField::new('ebayCategoryId', 'eBay Category ID')->setRequired(false)->hideOnIndex(); yield IntegerField::new('attributeAssignments', '# Attributes') - ->formatValue(static fn (mixed $v): int => is_countable($v) ? count($v) : 0) + ->formatValue(static fn (mixed $v): int => is_countable($v) ? \count($v) : 0) ->hideOnForm() ->setSortable(false); @@ -77,8 +77,7 @@ final class ArticleTypeCrudController extends AbstractCrudController 'attr' => ['data-ea-widget' => 'ea-autocomplete'], ]) ->hideOnIndex() - ->formatValue(static fn (mixed $v, ArticleType $at): string => - implode(', ', $at->getRequiredAttributeDefs()->map(fn (AttributeDefinition $d) => $d->getName())->toArray()) ?: '—' + ->formatValue(static fn (mixed $v, ArticleType $at): string => implode(', ', $at->getRequiredAttributeDefs()->map(static fn (AttributeDefinition $d) => $d->getName())->toArray()) ?: '—' ); yield Field::new('optionalAttributeDefs', 'Optional Attributes') @@ -92,8 +91,7 @@ final class ArticleTypeCrudController extends AbstractCrudController 'attr' => ['data-ea-widget' => 'ea-autocomplete'], ]) ->hideOnIndex() - ->formatValue(static fn (mixed $v, ArticleType $at): string => - implode(', ', $at->getOptionalAttributeDefs()->map(fn (AttributeDefinition $d) => $d->getName())->toArray()) ?: '—' + ->formatValue(static fn (mixed $v, ArticleType $at): string => implode(', ', $at->getOptionalAttributeDefs()->map(static fn (AttributeDefinition $d) => $d->getName())->toArray()) ?: '—' ); } diff --git a/src/Infrastructure/Http/Controller/Admin/EbayAspectImportController.php b/src/Infrastructure/Http/Controller/Admin/EbayAspectImportController.php index 32e7036..fa5926b 100644 --- a/src/Infrastructure/Http/Controller/Admin/EbayAspectImportController.php +++ b/src/Infrastructure/Http/Controller/Admin/EbayAspectImportController.php @@ -45,7 +45,7 @@ final class EbayAspectImportController extends AbstractController return $this->json([]); } - return $this->json(array_slice($results, 0, 15)); + return $this->json(\array_slice($results, 0, 15)); } /** @@ -54,23 +54,23 @@ final class EbayAspectImportController extends AbstractController */ private const ARTICLE_FIELDS = [ 'articleTypeName' => 'Produktart (Artikel-Typ)', - 'manufacturer' => 'Hersteller (Marke)', - 'modelNumber' => 'Herstellernummer (PN / MPN)', - 'modelName' => 'Modellname', - 'serialNumber' => 'Seriennummer', + 'manufacturer' => 'Hersteller (Marke)', + 'modelNumber' => 'Herstellernummer (PN / MPN)', + 'modelName' => 'Modellname', + 'serialNumber' => 'Seriennummer', ]; /** eBay aspect names (lowercase) that auto-match to article fields. */ private const ARTICLE_FIELD_ALIASES = [ - 'produktart' => 'articleTypeName', - 'marke' => 'manufacturer', - 'brand' => 'manufacturer', - 'hersteller' => 'manufacturer', - 'herstellernummer' => 'modelNumber', - 'mpn' => 'modelNumber', - 'teilenummer' => 'modelNumber', - 'modell' => 'modelName', - 'seriennummer' => 'serialNumber', + 'produktart' => 'articleTypeName', + 'marke' => 'manufacturer', + 'brand' => 'manufacturer', + 'hersteller' => 'manufacturer', + 'herstellernummer' => 'modelNumber', + 'mpn' => 'modelNumber', + 'teilenummer' => 'modelNumber', + 'modell' => 'modelName', + 'seriennummer' => 'serialNumber', ]; #[Route('/admin/ebay/aspect-import/{id}', name: 'admin_ebay_aspect_import')] @@ -109,20 +109,20 @@ final class EbayAspectImportController extends AbstractController $allDefs = $this->em->getRepository(AttributeDefinition::class)->findBy([], ['name' => 'ASC']); $rows = $this->buildRows($aspects, $allDefs, $articleType); $counts = [ - 'required' => count(array_filter($aspects, static fn (array $a) => $a['required'])), - 'recommended' => count(array_filter($aspects, static fn (array $a) => !$a['required'] && 'RECOMMENDED' === $a['usage'])), - 'optional' => count(array_filter($aspects, static fn (array $a) => !$a['required'] && 'OPTIONAL' === $a['usage'])), + 'required' => \count(array_filter($aspects, static fn (array $a) => $a['required'])), + 'recommended' => \count(array_filter($aspects, static fn (array $a) => !$a['required'] && 'RECOMMENDED' === $a['usage'])), + 'optional' => \count(array_filter($aspects, static fn (array $a) => !$a['required'] && 'OPTIONAL' === $a['usage'])), ]; } return $this->render('admin/ebay/aspect_import.html.twig', [ - 'articleType' => $articleType, - 'rows' => $rows, - 'allDefs' => $allDefs, + 'articleType' => $articleType, + 'rows' => $rows, + 'allDefs' => $allDefs, 'articleFields' => self::ARTICLE_FIELDS, - 'counts' => $counts, - 'categoryId' => $categoryId, - 'searchUrl' => $this->generateUrl('admin_ebay_category_search'), + 'counts' => $counts, + 'categoryId' => $categoryId, + 'searchUrl' => $this->generateUrl('admin_ebay_category_search'), 'existingMappings' => $articleType->getEbayMappings(), ]); } @@ -158,7 +158,7 @@ final class EbayAspectImportController extends AbstractController /** @var array $data */ $data = array_map(static fn (mixed $v): string => \is_scalar($v) ? (string) $v : '', $rawData); - $action = $data['action'] ?? 'skip'; + $action = $data['action'] ?? 'skip'; $ebayName = $data['ebayName'] ?? ''; $isRequired = ($data['ebayRequired'] ?? '0') === '1'; @@ -193,7 +193,7 @@ final class EbayAspectImportController extends AbstractController } $rawValues = array_values(array_filter(array_map('trim', explode(',', $data['ebayValues'] ?? '')))); - $type = (count($rawValues) > 0 && count($rawValues) <= 30) + $type = (\count($rawValues) > 0 && \count($rawValues) <= 30) ? AttributeType::Select : AttributeType::String; @@ -289,12 +289,12 @@ final class EbayAspectImportController extends AbstractController $existing = $existingMappings[$aspect['name']]; $isFieldMapping = ArticleTypeEbayMapping::SOURCE_ARTICLE_FIELD === $existing->getSourceType(); $rows[] = [ - 'aspect' => $aspect, - 'action' => $isFieldMapping ? 'article_field' : 'match', - 'preMatchId' => $isFieldMapping ? null : $existing->getAttributeDefinition()?->getId()->toRfc4122(), - 'preFieldKey' => $isFieldMapping ? $existing->getArticleFieldKey() : null, + 'aspect' => $aspect, + 'action' => $isFieldMapping ? 'article_field' : 'match', + 'preMatchId' => $isFieldMapping ? null : $existing->getAttributeDefinition()?->getId()->toRfc4122(), + 'preFieldKey' => $isFieldMapping ? $existing->getArticleFieldKey() : null, 'alreadyAssigned' => true, - 'suggestedType' => 'string', + 'suggestedType' => 'string', ]; continue; } @@ -327,7 +327,7 @@ final class EbayAspectImportController extends AbstractController $preMatchId = null; } - $suggestedType = (count($aspect['values']) > 0 && count($aspect['values']) <= 30) + $suggestedType = (\count($aspect['values']) > 0 && \count($aspect['values']) <= 30) ? AttributeType::Select->value : AttributeType::String->value; diff --git a/src/Infrastructure/Http/Controller/Admin/PipelineStreamController.php b/src/Infrastructure/Http/Controller/Admin/PipelineStreamController.php index 3d640d5..6d2f25b 100644 --- a/src/Infrastructure/Http/Controller/Admin/PipelineStreamController.php +++ b/src/Infrastructure/Http/Controller/Admin/PipelineStreamController.php @@ -18,12 +18,12 @@ use Symfony\Contracts\Translation\TranslatorInterface; final class PipelineStreamController extends AbstractController { private const array STEP_KEYS = [ - 'vision' => 'pipeline.step.vision', + 'vision' => 'pipeline.step.vision', 'specs_research' => 'pipeline.step.specs_research', - 'json_coding' => 'pipeline.step.json_coding', - 'draft_article' => 'pipeline.step.draft_article', - 'ebay_text' => 'pipeline.step.ebay_text', - 'validation' => 'pipeline.step.validation', + 'json_coding' => 'pipeline.step.json_coding', + 'draft_article' => 'pipeline.step.draft_article', + 'ebay_text' => 'pipeline.step.ebay_text', + 'validation' => 'pipeline.step.validation', ]; public function __construct( @@ -69,7 +69,7 @@ final class PipelineStreamController extends AbstractController $status = $job->getStatus()->value; $prev = $seen[$jobId] ?? null; - if ($prev !== null && $prev['step'] === $step && $prev['status'] === $status) { + if (null !== $prev && $prev['step'] === $step && $prev['status'] === $status) { continue; } @@ -105,31 +105,25 @@ final class PipelineStreamController extends AbstractController $label = "Job #{$inv}"; $t = fn (string $key, array $p = []) => $this->translator->trans($key, $p, 'admin'); - $stepLabel = $step !== null + $stepLabel = null !== $step ? $t(self::STEP_KEYS[$step] ?? $step) : ''; $message = match (true) { - $status === AIPipelineJobStatus::Queued->value - => $t('pipeline.event.queued', ['%inv%' => $inv]), - $status === AIPipelineJobStatus::Processing->value && $step === null - => $t('pipeline.event.processing_start', ['%inv%' => $inv]), - $status === AIPipelineJobStatus::Processing->value - => $t('pipeline.event.processing_step', ['%inv%' => $inv, '%step%' => $stepLabel]), - $status === AIPipelineJobStatus::Completed->value - => $t('pipeline.event.completed', ['%inv%' => $inv]), - $status === AIPipelineJobStatus::Failed->value - => $t('pipeline.event.failed', ['%inv%' => $inv, '%reason%' => $job->getErrorMessage() ?? '']), - $status === AIPipelineJobStatus::NeedsReview->value - => $t('pipeline.event.needs_review', ['%inv%' => $inv]), + $status === AIPipelineJobStatus::Queued->value => $t('pipeline.event.queued', ['%inv%' => $inv]), + $status === AIPipelineJobStatus::Processing->value && null === $step => $t('pipeline.event.processing_start', ['%inv%' => $inv]), + $status === AIPipelineJobStatus::Processing->value => $t('pipeline.event.processing_step', ['%inv%' => $inv, '%step%' => $stepLabel]), + $status === AIPipelineJobStatus::Completed->value => $t('pipeline.event.completed', ['%inv%' => $inv]), + $status === AIPipelineJobStatus::Failed->value => $t('pipeline.event.failed', ['%inv%' => $inv, '%reason%' => $job->getErrorMessage() ?? '']), + $status === AIPipelineJobStatus::NeedsReview->value => $t('pipeline.event.needs_review', ['%inv%' => $inv]), default => "{$label}: {$status}", }; return [ - 'jobId' => $job->getId()->toRfc4122(), - 'label' => $label, - 'status' => $status, - 'step' => $step, + 'jobId' => $job->getId()->toRfc4122(), + 'label' => $label, + 'status' => $status, + 'step' => $step, 'message' => $message, ]; } diff --git a/src/Infrastructure/Http/Controller/Admin/PromptTemplateCrudController.php b/src/Infrastructure/Http/Controller/Admin/PromptTemplateCrudController.php index 11fcd9f..1e1312d 100644 --- a/src/Infrastructure/Http/Controller/Admin/PromptTemplateCrudController.php +++ b/src/Infrastructure/Http/Controller/Admin/PromptTemplateCrudController.php @@ -62,7 +62,7 @@ final class PromptTemplateCrudController extends AbstractCrudController $lines = ['Use {{variableName}} as placeholders. Known keys and their variables:']; $lines[] = '
    '; foreach ($known as $key => $vars) { - $varList = $vars !== [] ? implode(', ', array_map(static fn (string $v) => "{{$v}}", $vars)) : '—'; + $varList = [] !== $vars ? implode(', ', array_map(static fn (string $v) => "{{$v}}", $vars)) : '—'; $lines[] = "
  • {$key}: {$varList}
  • "; } $lines[] = '
'; diff --git a/src/Infrastructure/Http/Controller/Admin/TranslationCrudController.php b/src/Infrastructure/Http/Controller/Admin/TranslationCrudController.php index c270437..0791093 100644 --- a/src/Infrastructure/Http/Controller/Admin/TranslationCrudController.php +++ b/src/Infrastructure/Http/Controller/Admin/TranslationCrudController.php @@ -39,7 +39,7 @@ final class TranslationCrudController extends AbstractCrudController public function configureFields(string $pageName): iterable { - $readonly = $pageName === Crud::PAGE_EDIT; + $readonly = Crud::PAGE_EDIT === $pageName; yield IdField::new('id')->hideOnForm()->hideOnIndex(); diff --git a/src/Infrastructure/Http/Form/StringArrayType.php b/src/Infrastructure/Http/Form/StringArrayType.php index 2ab8e95..2249fdc 100644 --- a/src/Infrastructure/Http/Form/StringArrayType.php +++ b/src/Infrastructure/Http/Form/StringArrayType.php @@ -15,8 +15,8 @@ final class StringArrayType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder->addModelTransformer(new CallbackTransformer( - fn (?array $v) => implode("\n", $v ?? []), - fn (mixed $v) => '' === ($v ?? '') ? null : array_values( + static fn (?array $v) => implode("\n", $v ?? []), + static fn (mixed $v) => '' === ($v ?? '') ? null : array_values( array_filter(array_map('trim', explode("\n", (string) $v))) ), )); diff --git a/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php b/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php index d3f7a08..a89a61a 100644 --- a/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php +++ b/src/Infrastructure/Messenger/Handler/DraftArticleHandler.php @@ -69,7 +69,7 @@ final class DraftArticleHandler $article->setManufacturer((string) $vision['manufacturer']); } $correctedModelNumber = (string) ($job->getOutputData()['specs_research']['correctedModelNumber'] ?? ''); - $modelNumber = $correctedModelNumber !== '' ? $correctedModelNumber : (string) ($vision['modelNumber'] ?? ''); + $modelNumber = '' !== $correctedModelNumber ? $correctedModelNumber : (string) ($vision['modelNumber'] ?? ''); if ('' !== $modelNumber) { $article->setModelNumber($modelNumber); } diff --git a/src/Infrastructure/Messenger/Handler/PhotoUploadHandler.php b/src/Infrastructure/Messenger/Handler/PhotoUploadHandler.php index 52bf856..4c9d644 100644 --- a/src/Infrastructure/Messenger/Handler/PhotoUploadHandler.php +++ b/src/Infrastructure/Messenger/Handler/PhotoUploadHandler.php @@ -80,7 +80,7 @@ final class PhotoUploadHandler attributes: $attributes, condition: $inputData['condition'] ?? 'good', inventoryNumber: $inputData['inventoryNumber'] ?? null, - serialNumber: $result['serial'] !== '' ? $result['serial'] : null, + serialNumber: '' !== $result['serial'] ? $result['serial'] : null, )); return; diff --git a/src/Infrastructure/Persistence/Repository/DoctrineTranslationRepository.php b/src/Infrastructure/Persistence/Repository/DoctrineTranslationRepository.php index 3bd8810..2bbebae 100644 --- a/src/Infrastructure/Persistence/Repository/DoctrineTranslationRepository.php +++ b/src/Infrastructure/Persistence/Repository/DoctrineTranslationRepository.php @@ -10,7 +10,9 @@ use Doctrine\ORM\EntityManagerInterface; final class DoctrineTranslationRepository implements TranslationRepositoryInterface { - public function __construct(private readonly EntityManagerInterface $em) {} + public function __construct(private readonly EntityManagerInterface $em) + { + } public function findMapByLocaleAndDomain(string $locale, string $domain): array { diff --git a/src/Infrastructure/Security/PermissionVoter.php b/src/Infrastructure/Security/PermissionVoter.php index 6ae97ea..ff1821d 100644 --- a/src/Infrastructure/Security/PermissionVoter.php +++ b/src/Infrastructure/Security/PermissionVoter.php @@ -16,10 +16,10 @@ final class PermissionVoter extends Voter public const PREFIX = 'PERM_'; public const ARTICLES_MANAGE = 'articles.manage'; - public const PIPELINE_RUN = 'pipeline.run'; - public const ORDERS_MANAGE = 'orders.manage'; - public const USERS_MANAGE = 'users.manage'; - public const PROMPTS_MANAGE = 'prompts.manage'; + public const PIPELINE_RUN = 'pipeline.run'; + public const ORDERS_MANAGE = 'orders.manage'; + public const USERS_MANAGE = 'users.manage'; + public const PROMPTS_MANAGE = 'prompts.manage'; public const SETTINGS_MANAGE = 'settings.manage'; /** @return list */ diff --git a/src/Infrastructure/Translation/DatabaseTranslator.php b/src/Infrastructure/Translation/DatabaseTranslator.php index 0214d99..0575807 100644 --- a/src/Infrastructure/Translation/DatabaseTranslator.php +++ b/src/Infrastructure/Translation/DatabaseTranslator.php @@ -28,7 +28,7 @@ final class DatabaseTranslator implements TranslatorInterface, LocaleAwareInterf $effectiveDomain = $domain ?? 'messages'; $cacheKey = $effectiveLocale.'.'.$effectiveDomain; - if (!array_key_exists($cacheKey, $this->cache)) { + if (!\array_key_exists($cacheKey, $this->cache)) { try { $this->cache[$cacheKey] = $this->repo->findMapByLocaleAndDomain($effectiveLocale, $effectiveDomain); } catch (\Throwable) { @@ -36,10 +36,10 @@ final class DatabaseTranslator implements TranslatorInterface, LocaleAwareInterf } } - if (array_key_exists($id, $this->cache[$cacheKey])) { + if (\array_key_exists($id, $this->cache[$cacheKey])) { $value = $this->cache[$cacheKey][$id]; - return $parameters !== [] ? strtr($value, $parameters) : $value; + return [] !== $parameters ? strtr($value, $parameters) : $value; } return $this->inner->trans($id, $parameters, $domain, $locale); diff --git a/tests/Integration/Infrastructure/Channel/Ebay/EbayTaxonomyIntegrationTest.php b/tests/Integration/Infrastructure/Channel/Ebay/EbayTaxonomyIntegrationTest.php index abe37c2..01ed085 100644 --- a/tests/Integration/Infrastructure/Channel/Ebay/EbayTaxonomyIntegrationTest.php +++ b/tests/Integration/Infrastructure/Channel/Ebay/EbayTaxonomyIntegrationTest.php @@ -56,7 +56,7 @@ final class EbayTaxonomyIntegrationTest extends TestCase ); } - public function test_fetches_application_token(): void + public function testFetchesApplicationToken(): void { $token = $this->oauth->getAccessToken(); @@ -64,7 +64,7 @@ final class EbayTaxonomyIntegrationTest extends TestCase $this->assertStringStartsWith('v^1.1', $token); } - public function test_fetches_aspects_for_notebooks_category(): void + public function testFetchesAspectsForNotebooksCategory(): void { // 177 = Notebooks & Netbooks in EBAY_DE $aspects = $this->taxonomy->getCategoryAspects('177'); @@ -89,7 +89,7 @@ final class EbayTaxonomyIntegrationTest extends TestCase ); } - public function test_three_tier_aspect_classification(): void + public function testThreeTierAspectClassification(): void { // eBay has three effective tiers: // required=true + usage=RECOMMENDED → hard gate, eBay blocks listing without it @@ -98,15 +98,15 @@ final class EbayTaxonomyIntegrationTest extends TestCase $aspects = $this->taxonomy->getCategoryAspects('177'); $hardRequired = array_filter($aspects, static fn (array $a) => $a['required']); - $recommended = array_filter($aspects, static fn (array $a) => !$a['required'] && 'RECOMMENDED' === $a['usage']); - $optional = array_filter($aspects, static fn (array $a) => !$a['required'] && 'OPTIONAL' === $a['usage']); + $recommended = array_filter($aspects, static fn (array $a) => !$a['required'] && 'RECOMMENDED' === $a['usage']); + $optional = array_filter($aspects, static fn (array $a) => !$a['required'] && 'OPTIONAL' === $a['usage']); $this->assertNotEmpty($hardRequired, 'Should have hard-required aspects'); $this->assertNotEmpty($recommended, 'Should have recommended (ranking-signal) aspects'); $this->assertNotEmpty($optional, 'Should have truly optional aspects'); } - public function test_aspects_with_predefined_values_have_options(): void + public function testAspectsWithPredefinedValuesHaveOptions(): void { $aspects = $this->taxonomy->getCategoryAspects('177'); @@ -115,7 +115,7 @@ final class EbayTaxonomyIntegrationTest extends TestCase $this->assertNotEmpty($withOptions, 'Some aspects should have predefined selectable values'); } - public function test_caches_aspects_on_second_call(): void + public function testCachesAspectsOnSecondCall(): void { // First call hits the API $first = $this->taxonomy->getCategoryAspects('177'); @@ -125,7 +125,7 @@ final class EbayTaxonomyIntegrationTest extends TestCase $this->assertSame($first, $second); } - public function test_fetches_aspects_for_ram_category(): void + public function testFetchesAspectsForRamCategory(): void { // 170083 = RAM/Speicher in EBAY_DE — useful for our memory article types $aspects = $this->taxonomy->getCategoryAspects('170083'); @@ -135,7 +135,7 @@ final class EbayTaxonomyIntegrationTest extends TestCase $this->assertNotEmpty($names); } - public function test_category_suggestions_returns_results(): void + public function testCategorySuggestionsReturnsResults(): void { $results = $this->taxonomy->getCategorySuggestions('Notebook'); diff --git a/tests/Integration/Infrastructure/Channel/Frappe/FrappeCustomerIntegrationTest.php b/tests/Integration/Infrastructure/Channel/Frappe/FrappeCustomerIntegrationTest.php index 6958085..5293f39 100644 --- a/tests/Integration/Infrastructure/Channel/Frappe/FrappeCustomerIntegrationTest.php +++ b/tests/Integration/Infrastructure/Channel/Frappe/FrappeCustomerIntegrationTest.php @@ -49,7 +49,7 @@ final class FrappeCustomerIntegrationTest extends TestCase } } - public function test_create_customer(): void + public function testCreateCustomer(): void { $response = $this->client->post('/api/resource/Customer', [ 'customer_name' => 'Test Superseller Integration', @@ -64,7 +64,7 @@ final class FrappeCustomerIntegrationTest extends TestCase $this->createdCustomerName = $response['data']['name']; } - public function test_find_created_customer(): void + public function testFindCreatedCustomer(): void { // Create first $created = $this->client->post('/api/resource/Customer', [ @@ -82,14 +82,14 @@ final class FrappeCustomerIntegrationTest extends TestCase $this->assertSame('Test Superseller Integration', $response['data']['customer_name']); } - public function test_find_nonexistent_customer_throws(): void + public function testFindNonexistentCustomerThrows(): void { $this->expectException(ClientExceptionInterface::class); $this->client->get('/api/resource/Customer/CUST-DOES-NOT-EXIST-99999'); } - public function test_delete_customer(): void + public function testDeleteCustomer(): void { // Create $created = $this->client->post('/api/resource/Customer', [ diff --git a/tests/Integration/Infrastructure/Channel/Frappe/FrappeErpAdapterIntegrationTest.php b/tests/Integration/Infrastructure/Channel/Frappe/FrappeErpAdapterIntegrationTest.php index 281f092..f8d87bf 100644 --- a/tests/Integration/Infrastructure/Channel/Frappe/FrappeErpAdapterIntegrationTest.php +++ b/tests/Integration/Infrastructure/Channel/Frappe/FrappeErpAdapterIntegrationTest.php @@ -61,7 +61,7 @@ final class FrappeErpAdapterIntegrationTest extends TestCase } } - public function test_find_simon_kuehn_by_name_and_address(): void + public function testFindSimonKuehnByNameAndAddress(): void { $customerId = $this->adapter->findExistingCustomer( 'Simon Kühn', @@ -74,7 +74,7 @@ final class FrappeErpAdapterIntegrationTest extends TestCase $this->assertStringStartsWith('Simon', $customerId); } - public function test_unknown_person_is_not_found(): void + public function testUnknownPersonIsNotFound(): void { $customerId = $this->adapter->findExistingCustomer( 'Voldemort', @@ -86,7 +86,7 @@ final class FrappeErpAdapterIntegrationTest extends TestCase $this->assertNull($customerId); } - public function test_find_simon_and_create_invoice_for_1337(): void + public function testFindSimonAndCreateInvoiceFor1337(): void { $frappeId = $this->adapter->findExistingCustomer( 'Simon Kühn', diff --git a/tests/Unit/Domain/Article/ArticleTypeRequiredAttributesTest.php b/tests/Unit/Domain/Article/ArticleTypeRequiredAttributesTest.php index fb829b9..aac0697 100644 --- a/tests/Unit/Domain/Article/ArticleTypeRequiredAttributesTest.php +++ b/tests/Unit/Domain/Article/ArticleTypeRequiredAttributesTest.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace App\Tests\Unit\Domain\Article; use App\Domain\Article\ArticleType; -use App\Domain\Article\ArticleTypeAttribute; use App\Domain\Article\AttributeDefinition; use App\Domain\Article\AttributeType; use PHPUnit\Framework\TestCase; diff --git a/tests/Unit/Domain/Article/AttributeDefinitionTest.php b/tests/Unit/Domain/Article/AttributeDefinitionTest.php index d29f57f..afb1582 100644 --- a/tests/Unit/Domain/Article/AttributeDefinitionTest.php +++ b/tests/Unit/Domain/Article/AttributeDefinitionTest.php @@ -35,8 +35,8 @@ final class AttributeDefinitionTest extends TestCase public static function allAttributeTypes(): array { return array_combine( - array_map(fn (AttributeType $t) => $t->value, AttributeType::cases()), - array_map(fn (AttributeType $t) => [$t], AttributeType::cases()), + array_map(static fn (AttributeType $t) => $t->value, AttributeType::cases()), + array_map(static fn (AttributeType $t) => [$t], AttributeType::cases()), ); } diff --git a/tests/Unit/Domain/Auth/ApiKeyTest.php b/tests/Unit/Domain/Auth/ApiKeyTest.php index 0d701b8..c21d790 100644 --- a/tests/Unit/Domain/Auth/ApiKeyTest.php +++ b/tests/Unit/Domain/Auth/ApiKeyTest.php @@ -87,7 +87,7 @@ final class ApiKeyTest extends TestCase public function testRawKeyVerifiesAgainstStoredHash(): void { $rawKey = bin2hex(random_bytes(24)); - $hash = password_hash($rawKey, PASSWORD_BCRYPT); + $hash = password_hash($rawKey, \PASSWORD_BCRYPT); $prefix = substr($rawKey, 0, 8); $key = new ApiKey($this->user, 'label', $prefix, $hash); diff --git a/tests/Unit/Infrastructure/AI/Agent/JsonCodingAgentTest.php b/tests/Unit/Infrastructure/AI/Agent/JsonCodingAgentTest.php index 489ca93..b6cd874 100644 --- a/tests/Unit/Infrastructure/AI/Agent/JsonCodingAgentTest.php +++ b/tests/Unit/Infrastructure/AI/Agent/JsonCodingAgentTest.php @@ -4,11 +4,11 @@ declare(strict_types=1); namespace App\Tests\Unit\Infrastructure\AI\Agent; +use App\Domain\AI\PromptTemplate; +use App\Domain\AI\Repository\PromptTemplateRepositoryInterface; use App\Domain\Article\ArticleType; use App\Domain\Article\AttributeDefinition; use App\Domain\Article\AttributeType; -use App\Domain\AI\PromptTemplate; -use App\Domain\AI\Repository\PromptTemplateRepositoryInterface; use App\Infrastructure\AI\Agent\JsonCodingAgent; use App\Infrastructure\AI\OllamaClientInterface; use App\Infrastructure\AI\PromptTemplateService; diff --git a/tests/Unit/Infrastructure/AI/Agent/OllamaVisionAgentTest.php b/tests/Unit/Infrastructure/AI/Agent/OllamaVisionAgentTest.php index fc49c2f..ec3266c 100644 --- a/tests/Unit/Infrastructure/AI/Agent/OllamaVisionAgentTest.php +++ b/tests/Unit/Infrastructure/AI/Agent/OllamaVisionAgentTest.php @@ -28,7 +28,7 @@ final class OllamaVisionAgentTest extends TestCase $this->agent = new OllamaVisionAgent($this->ollama, $prompts, 'llava'); } - public function test_parses_all_fields(): void + public function testParsesAllFields(): void { $this->ollama->method('generateWithImage')->willReturn( "MANUFACTURER: Lenovo\nMODEL_NAME: ThinkBook 14 G6 IRL\nMODEL_NUMBER: 21KG00NQGE\nSERIAL: PNV09SJZ" @@ -42,7 +42,7 @@ final class OllamaVisionAgentTest extends TestCase $this->assertSame('PNV09SJZ', $result['serial']); } - public function test_strips_serial_bleed_into_model_number_leading(): void + public function testStripsSerialBleedIntoModelNumberLeading(): void { // LLM outputs "SERIAL: xyz" as the entire value for MODEL_NUMBER $this->ollama->method('generateWithImage')->willReturn( @@ -55,7 +55,7 @@ final class OllamaVisionAgentTest extends TestCase $this->assertSame('1005NK677594', $result['serial']); } - public function test_strips_serial_bleed_into_model_name_mid_value(): void + public function testStripsSerialBleedIntoModelNameMidValue(): void { // LLM appends serial after the model name $this->ollama->method('generateWithImage')->willReturn( @@ -68,7 +68,7 @@ final class OllamaVisionAgentTest extends TestCase $this->assertSame('PNV09SJZ', $result['serial']); } - public function test_returns_empty_strings_when_fields_missing(): void + public function testReturnsEmptyStringsWhenFieldsMissing(): void { $this->ollama->method('generateWithImage')->willReturn('I cannot read the nameplate.'); diff --git a/tests/Unit/Infrastructure/AI/MistralClientTest.php b/tests/Unit/Infrastructure/AI/MistralClientTest.php index 524bf2c..fa4ebb3 100644 --- a/tests/Unit/Infrastructure/AI/MistralClientTest.php +++ b/tests/Unit/Infrastructure/AI/MistralClientTest.php @@ -49,7 +49,7 @@ final class MistralClientTest extends TestCase public function testGenerateWithImageReturnsParsedContent(): void { - $tmpFile = tempnam(sys_get_temp_dir(), 'test_') . '.jpg'; + $tmpFile = tempnam(sys_get_temp_dir(), 'test_').'.jpg'; file_put_contents($tmpFile, 'fake-image-data'); $body = json_encode([ @@ -66,7 +66,7 @@ final class MistralClientTest extends TestCase public function testGenerateWithImageEncodesImageAsBase64(): void { - $tmpFile = tempnam(sys_get_temp_dir(), 'test_') . '.png'; + $tmpFile = tempnam(sys_get_temp_dir(), 'test_').'.png'; $imageContent = 'fake-png-bytes'; file_put_contents($tmpFile, $imageContent); @@ -92,7 +92,7 @@ final class MistralClientTest extends TestCase */ public function testGuessMimeTypeFromExtension(string $filename, string $expectedMime): void { - $tmpFile = tempnam(sys_get_temp_dir(), 'test_') . '.' . pathinfo($filename, PATHINFO_EXTENSION); + $tmpFile = tempnam(sys_get_temp_dir(), 'test_').'.'.pathinfo($filename, \PATHINFO_EXTENSION); file_put_contents($tmpFile, 'x'); $body = json_encode(['choices' => [['message' => ['content' => 'ok']]]]); @@ -105,7 +105,7 @@ final class MistralClientTest extends TestCase $requestBody = json_decode($response->getRequestOptions()['body'], true); $imageUrl = $requestBody['messages'][0]['content'][1]['image_url']['url']; - self::assertStringStartsWith('data:' . $expectedMime . ';base64,', $imageUrl); + self::assertStringStartsWith('data:'.$expectedMime.';base64,', $imageUrl); } /** @return array */ diff --git a/tests/Unit/Infrastructure/Admin/ArticleTypeCrudControllerTest.php b/tests/Unit/Infrastructure/Admin/ArticleTypeCrudControllerTest.php index 8f7da34..f198587 100644 --- a/tests/Unit/Infrastructure/Admin/ArticleTypeCrudControllerTest.php +++ b/tests/Unit/Infrastructure/Admin/ArticleTypeCrudControllerTest.php @@ -33,7 +33,7 @@ final class ArticleTypeCrudControllerTest extends TestCase public function testConfigureFieldsContainsExpectedProperties(): void { $fields = iterator_to_array($this->controller->configureFields('new')); - $names = array_map(fn ($f) => $f->getAsDto()->getProperty(), $fields); + $names = array_map(static fn ($f) => $f->getAsDto()->getProperty(), $fields); self::assertContains('name', $names); self::assertContains('requiredAttributeDefs', $names); @@ -43,7 +43,7 @@ final class ArticleTypeCrudControllerTest extends TestCase public function testConfigureFieldsForIndexContainsNameAndCount(): void { $fields = iterator_to_array($this->controller->configureFields('index')); - $names = array_map(fn ($f) => $f->getAsDto()->getProperty(), $fields); + $names = array_map(static fn ($f) => $f->getAsDto()->getProperty(), $fields); self::assertContains('name', $names); self::assertContains('attributeAssignments', $names); diff --git a/tests/Unit/Infrastructure/Admin/AttributeDefinitionCrudControllerTest.php b/tests/Unit/Infrastructure/Admin/AttributeDefinitionCrudControllerTest.php index 01be542..3d12b96 100644 --- a/tests/Unit/Infrastructure/Admin/AttributeDefinitionCrudControllerTest.php +++ b/tests/Unit/Infrastructure/Admin/AttributeDefinitionCrudControllerTest.php @@ -36,7 +36,7 @@ final class AttributeDefinitionCrudControllerTest extends TestCase public function testConfigureFieldsYieldsExpectedFieldNames(): void { $fields = iterator_to_array($this->controller->configureFields('new')); - $names = array_map(fn ($f) => $f->getAsDto()->getProperty(), $fields); + $names = array_map(static fn ($f) => $f->getAsDto()->getProperty(), $fields); self::assertContains('name', $names); self::assertContains('type', $names); diff --git a/tests/Unit/Infrastructure/Channel/Ebay/EbayWebhookVerifierTest.php b/tests/Unit/Infrastructure/Channel/Ebay/EbayWebhookVerifierTest.php index 1c716e9..7bb67d4 100644 --- a/tests/Unit/Infrastructure/Channel/Ebay/EbayWebhookVerifierTest.php +++ b/tests/Unit/Infrastructure/Channel/Ebay/EbayWebhookVerifierTest.php @@ -19,7 +19,7 @@ final class EbayWebhookVerifierTest extends TestCase ); } - public function test_valid_signature_passes(): void + public function testValidSignaturePasses(): void { $body = '{"notification":{"data":{"orderId":"123"}}}'; $expected = base64_encode(hash('sha256', $body.'my-secret-tokenhttps://example.com/webhooks/ebay', binary: true)); @@ -27,12 +27,12 @@ final class EbayWebhookVerifierTest extends TestCase $this->assertTrue($this->verifier->verify($body, $expected)); } - public function test_invalid_signature_fails(): void + public function testInvalidSignatureFails(): void { $this->assertFalse($this->verifier->verify('{"body":"x"}', 'invalidsignature')); } - public function test_challenge_response_returns_correct_hash(): void + public function testChallengeResponseReturnsCorrectHash(): void { $challengeCode = 'abc123'; $expected = hash('sha256', $challengeCode.'my-secret-tokenhttps://example.com/webhooks/ebay'); diff --git a/tests/Unit/Infrastructure/Channel/Frappe/FrappeErpAdapterTest.php b/tests/Unit/Infrastructure/Channel/Frappe/FrappeErpAdapterTest.php index cb0bc51..706b954 100644 --- a/tests/Unit/Infrastructure/Channel/Frappe/FrappeErpAdapterTest.php +++ b/tests/Unit/Infrastructure/Channel/Frappe/FrappeErpAdapterTest.php @@ -26,7 +26,7 @@ final class FrappeErpAdapterTest extends TestCase $this->adapter = new FrappeErpAdapter($this->frappe, 'REFURB-HW'); } - public function test_create_customer_returns_frappe_id(): void + public function testCreateCustomerReturnsFrappeId(): void { $this->frappe ->method('post') @@ -41,7 +41,7 @@ final class FrappeErpAdapterTest extends TestCase $this->assertSame('CUST-00001', $result); } - public function test_create_sales_invoice_submits_and_returns_id(): void + public function testCreateSalesInvoiceSubmitsAndReturnsId(): void { $this->frappe ->expects($this->once()) @@ -71,7 +71,7 @@ final class FrappeErpAdapterTest extends TestCase $this->assertSame('SINV-00001', $result); } - public function test_fetch_invoice_pdf_returns_binary(): void + public function testFetchInvoicePdfReturnsBinary(): void { $this->frappe ->method('getContent') @@ -83,7 +83,7 @@ final class FrappeErpAdapterTest extends TestCase $this->assertStringStartsWith('%PDF', $result); } - public function test_find_existing_customer_returns_id_when_address_matches(): void + public function testFindExistingCustomerReturnsIdWhenAddressMatches(): void { $this->frappe ->expects($this->exactly(2)) @@ -98,7 +98,7 @@ final class FrappeErpAdapterTest extends TestCase $this->assertSame('CUST-99999', $result); } - public function test_find_existing_customer_returns_null_when_address_mismatch(): void + public function testFindExistingCustomerReturnsNullWhenAddressMismatch(): void { $this->frappe ->expects($this->exactly(2)) @@ -113,7 +113,7 @@ final class FrappeErpAdapterTest extends TestCase $this->assertNull($result); } - public function test_find_existing_customer_returns_null_when_not_in_erp(): void + public function testFindExistingCustomerReturnsNullWhenNotInErp(): void { $this->frappe ->expects($this->once()) @@ -125,7 +125,7 @@ final class FrappeErpAdapterTest extends TestCase $this->assertNull($result); } - public function test_find_simon_and_create_invoice_for_1337(): void + public function testFindSimonAndCreateInvoiceFor1337(): void { $this->frappe ->expects($this->exactly(2)) diff --git a/tests/Unit/Infrastructure/Console/CreateApiKeyCommandTest.php b/tests/Unit/Infrastructure/Console/CreateApiKeyCommandTest.php index fda97ba..f3a1022 100644 --- a/tests/Unit/Infrastructure/Console/CreateApiKeyCommandTest.php +++ b/tests/Unit/Infrastructure/Console/CreateApiKeyCommandTest.php @@ -69,7 +69,7 @@ final class CreateApiKeyCommandTest extends TestCase $savedKey = null; $this->apiKeys->expects($this->once()) ->method('save') - ->willReturnCallback(function (ApiKey $key) use (&$savedKey): void { + ->willReturnCallback(static function (ApiKey $key) use (&$savedKey): void { $savedKey = $key; }); @@ -84,7 +84,7 @@ final class CreateApiKeyCommandTest extends TestCase self::assertNotNull($savedKey); self::assertSame('dev laptop', $savedKey->getLabel()); - self::assertSame(8, strlen($savedKey->getKeyPrefix())); + self::assertSame(8, \strlen($savedKey->getKeyPrefix())); self::assertStringContainsString($savedKey->getKeyPrefix(), $display); } @@ -95,7 +95,7 @@ final class CreateApiKeyCommandTest extends TestCase $savedKey = null; $this->apiKeys->method('save') - ->willReturnCallback(function (ApiKey $key) use (&$savedKey): void { + ->willReturnCallback(static function (ApiKey $key) use (&$savedKey): void { $savedKey = $key; }); diff --git a/tests/Unit/Infrastructure/Order/CustomerResolverTest.php b/tests/Unit/Infrastructure/Order/CustomerResolverTest.php index 2fff7bf..b761bec 100644 --- a/tests/Unit/Infrastructure/Order/CustomerResolverTest.php +++ b/tests/Unit/Infrastructure/Order/CustomerResolverTest.php @@ -24,7 +24,7 @@ final class CustomerResolverTest extends TestCase $this->resolver = new CustomerResolver($this->customerRepo, $this->erp); } - public function test_stage_1_platform_id_match_returns_existing_customer_without_erp_call(): void + public function testStage1PlatformIdMatchReturnsExistingCustomerWithoutErpCall(): void { $existing = new Customer('Max Mustermann', 'max@test.de', ['street' => 'Musterstr 1', 'city' => 'Berlin', 'zip' => '10115']); $existing->addPlatformId('ebay', 'buyer123'); @@ -46,7 +46,7 @@ final class CustomerResolverTest extends TestCase $this->assertSame($existing, $result); } - public function test_stage_2_address_match_adds_platform_id_and_saves(): void + public function testStage2AddressMatchAddsPlatformIdAndSaves(): void { $existing = new Customer('Max Mustermann', 'max@test.de', ['street' => 'Musterstr 1', 'city' => 'Berlin', 'zip' => '10115']); @@ -69,7 +69,7 @@ final class CustomerResolverTest extends TestCase $this->assertSame('buyer456', $result->getPlatformId('ebay')); } - public function test_no_match_creates_new_customer_via_erp(): void + public function testNoMatchCreatesNewCustomerViaErp(): void { $this->customerRepo->method('findByPlatformId')->willReturn(null); $this->customerRepo->method('findByMatchingKey')->willReturn(null);