From bc3264891819642072f34a39b80c9a18744104bb Mon Sep 17 00:00:00 2001 From: Matthieu Date: Mon, 11 May 2026 16:22:52 +0200 Subject: [PATCH] fix(custom-fields) : supporte les caracteres accentues dans les placeholders de formule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La regex \w+ ne capturait pas les caracteres accentues (ex. {Diametre} avec 'è'), le placeholder restait litteral dans la reference auto. Remplace par [^}]+ avec le flag u/gu cote PHP et JS pour matcher n'importe quel caractere entre les accolades. --- .../components/model-types/ModelTypeForm.vue | 2 +- .../model-types/ReferenceFormulaBuilder.vue | 2 +- src/Service/ReferenceAutoGenerator.php | 2 +- tests/Service/ReferenceAutoGeneratorTest.php | 63 +++++++++++++++++++ 4 files changed, 66 insertions(+), 3 deletions(-) diff --git a/frontend/app/components/model-types/ModelTypeForm.vue b/frontend/app/components/model-types/ModelTypeForm.vue index f07afba..f070b15 100644 --- a/frontend/app/components/model-types/ModelTypeForm.vue +++ b/frontend/app/components/model-types/ModelTypeForm.vue @@ -204,7 +204,7 @@ const formulaBuilderCustomFields = computed(() => { const extractFormulaFields = (formula: string | null | undefined): string[] => { if (!formula) return [] - const matches = [...formula.matchAll(/\{(\w+)\}/g)] + const matches = [...formula.matchAll(/\{([^}]+)\}/gu)] return [...new Set(matches.map(m => m[1]).filter((n): n is string => n !== undefined))] } diff --git a/frontend/app/components/model-types/ReferenceFormulaBuilder.vue b/frontend/app/components/model-types/ReferenceFormulaBuilder.vue index 5587f68..42a3c98 100644 --- a/frontend/app/components/model-types/ReferenceFormulaBuilder.vue +++ b/frontend/app/components/model-types/ReferenceFormulaBuilder.vue @@ -91,7 +91,7 @@ const preview = computed(() => { fieldMap.set(f.name, previewExamples[f.type] ?? 'VALEUR') } } - return props.modelValue.replace(/\{(\w+)\}/g, (_, name) => fieldMap.get(name) ?? '???') + return props.modelValue.replace(/\{([^}]+)\}/gu, (_, name) => fieldMap.get(name) ?? '???') }) const insertField = (fieldName: string) => { diff --git a/src/Service/ReferenceAutoGenerator.php b/src/Service/ReferenceAutoGenerator.php index a1e8e7b..31a31db 100644 --- a/src/Service/ReferenceAutoGenerator.php +++ b/src/Service/ReferenceAutoGenerator.php @@ -32,7 +32,7 @@ class ReferenceAutoGenerator } } - return preg_replace_callback('/\{(\w+)\}/', static function (array $matches) use ($valueMap): string { + return preg_replace_callback('/\{([^}]+)\}/u', static function (array $matches) use ($valueMap): string { return $valueMap[$matches[1]] ?? ''; }, $modelType->getReferenceFormula()); } diff --git a/tests/Service/ReferenceAutoGeneratorTest.php b/tests/Service/ReferenceAutoGeneratorTest.php index ac3e8da..d8798ec 100644 --- a/tests/Service/ReferenceAutoGeneratorTest.php +++ b/tests/Service/ReferenceAutoGeneratorTest.php @@ -145,6 +145,69 @@ class ReferenceAutoGeneratorTest extends AbstractApiTestCase self::assertSame('U507', $result); } + public function testGenerateWithAccentedFieldName(): void + { + $mt = $this->createModelType('Palier', 'PAL-ACCENT', ModelCategory::PIECE); + $mt->setReferenceFormula('PA-{Diamètre}-33'); + $mt->setRequiredFieldsForReference(['Diamètre']); + + $em = $this->getEntityManager(); + $em->flush(); + + $cf = $this->createCustomField('Diamètre', 'number', typePiece: $mt); + $piece = $this->createPiece('Palier 70', null, $mt); + $this->createCustomFieldValue($cf, '70', piece: $piece); + + $em->refresh($piece); + + $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator'); + $result = $generator->generate($piece); + + self::assertSame('PA-70-33', $result); + } + + public function testGenerateWithNumberTypeField(): void + { + $mt = $this->createModelType('NumberField', 'NUM-001', ModelCategory::PIECE); + $mt->setReferenceFormula('R-{taille}'); + $mt->setRequiredFieldsForReference(['taille']); + + $em = $this->getEntityManager(); + $em->flush(); + + $cf = $this->createCustomField('taille', 'number', typePiece: $mt); + $piece = $this->createPiece('Piece Number', null, $mt); + $this->createCustomFieldValue($cf, '42', piece: $piece); + + $em->refresh($piece); + + $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator'); + $result = $generator->generate($piece); + + self::assertSame('R-42', $result); + } + + public function testGenerateWithDecimalNumberField(): void + { + $mt = $this->createModelType('NumberDec', 'NUM-002', ModelCategory::PIECE); + $mt->setReferenceFormula('R-{taille}'); + $mt->setRequiredFieldsForReference(['taille']); + + $em = $this->getEntityManager(); + $em->flush(); + + $cf = $this->createCustomField('taille', 'number', typePiece: $mt); + $piece = $this->createPiece('Piece Dec', null, $mt); + $this->createCustomFieldValue($cf, '12.5', piece: $piece); + + $em->refresh($piece); + + $generator = self::getContainer()->get('App\Service\ReferenceAutoGenerator'); + $result = $generator->generate($piece); + + self::assertSame('R-12.5', $result); + } + public function testGenerateWithSpaceInFormula(): void { $mt = $this->createModelType('Palier2', 'PAL-002', ModelCategory::PIECE);