From 71cd4057a77a5b37394be5940359694b92f19501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Mon, 12 Jun 2023 23:39:30 +0200 Subject: [PATCH] Use enums for LabelOptions --- .../AdminPages/BaseAdminController.php | 2 +- src/Controller/LabelController.php | 15 ++--- src/DataFixtures/LabelProfileFixtures.php | 2 +- src/Doctrine/Types/BigDecimalType.php | 4 +- src/Entity/LabelSystem/BarcodeType.php | 64 +++++++++++++++++++ src/Entity/LabelSystem/LabelOptions.php | 55 ++++++---------- src/Entity/LabelSystem/LabelPictureType.php | 37 +++++++++++ src/Entity/LabelSystem/LabelProcessMode.php | 29 +++++++++ .../LabelSystem/LabelSupportedElement.php | 45 +++++++++++++ src/Form/LabelOptionsType.php | 53 ++++++++------- src/Repository/LabelProfileRepository.php | 25 +++----- src/Services/LabelSystem/BarcodeGenerator.php | 48 ++++++-------- .../LabelExampleElementsGenerator.php | 9 +-- src/Services/LabelSystem/LabelGenerator.php | 15 +---- .../LabelSystem/LabelHTMLGenerator.php | 5 +- .../LabelProfileDropdownHelper.php | 15 ++++- .../LabelSystem/SandboxedTwigProvider.php | 3 +- src/Twig/TwigCoreExtension.php | 18 ++++++ templates/label_system/dialog.html.twig | 4 +- .../label_system/labels/base_label.html.twig | 6 +- .../LabelSystem/BarcodeGeneratorTest.php | 9 +-- .../LabelSystem/LabelGeneratorTest.php | 13 ++-- .../LabelSystem/SandboxedTwigProviderTest.php | 10 +-- 23 files changed, 329 insertions(+), 157 deletions(-) create mode 100644 src/Entity/LabelSystem/BarcodeType.php create mode 100644 src/Entity/LabelSystem/LabelPictureType.php create mode 100644 src/Entity/LabelSystem/LabelProcessMode.php create mode 100644 src/Entity/LabelSystem/LabelSupportedElement.php diff --git a/src/Controller/AdminPages/BaseAdminController.php b/src/Controller/AdminPages/BaseAdminController.php index 8fb35ae0..11f49c92 100644 --- a/src/Controller/AdminPages/BaseAdminController.php +++ b/src/Controller/AdminPages/BaseAdminController.php @@ -159,7 +159,7 @@ abstract class BaseAdminController extends AbstractController //Disable editing of options, if user is not allowed to use twig... if ( $entity instanceof LabelProfile - && 'twig' === $entity->getOptions()->getLinesMode() + && 'twig' === $entity->getOptions()->getProcessMode() && !$this->isGranted('@labels.use_twig') ) { $form_options['disable_options'] = true; diff --git a/src/Controller/LabelController.php b/src/Controller/LabelController.php index 8f55b37c..36f9b669 100644 --- a/src/Controller/LabelController.php +++ b/src/Controller/LabelController.php @@ -44,6 +44,7 @@ namespace App\Controller; use App\Entity\Base\AbstractDBElement; use App\Entity\LabelSystem\LabelOptions; use App\Entity\LabelSystem\LabelProfile; +use App\Entity\LabelSystem\LabelSupportedElement; use App\Exceptions\TwigModeException; use App\Form\LabelSystem\LabelDialogType; use App\Repository\DBElementRepository; @@ -80,18 +81,18 @@ class LabelController extends AbstractController $label_options = $profile instanceof LabelProfile ? $profile->getOptions() : new LabelOptions(); //We have to disable the options, if twig mode is selected and user is not allowed to use it. - $disable_options = 'twig' === $label_options->getLinesMode() && !$this->isGranted('@labels.use_twig'); + $disable_options = 'twig' === $label_options->getProcessMode() && !$this->isGranted('@labels.use_twig'); $form = $this->createForm(LabelDialogType::class, null, [ 'disable_options' => $disable_options, ]); //Try to parse given target_type and target_id - $target_type = $request->query->get('target_type', null); + $target_type = $request->query->getEnum('target_type', LabelSupportedElement::class, null); $target_id = $request->query->get('target_id', null); $generate = $request->query->getBoolean('generate', false); - if (!$profile instanceof LabelProfile && is_string($target_type)) { + if (!$profile instanceof LabelProfile && $target_type instanceof LabelSupportedElement) { $label_options->setSupportedElement($target_type); } if (is_string($target_id)) { @@ -142,16 +143,12 @@ class LabelController extends AbstractController return $ret.'.pdf'; } - protected function findObjects(string $type, string $ids): array + protected function findObjects(LabelSupportedElement $type, string $ids): array { - if (!isset(LabelGenerator::CLASS_SUPPORT_MAPPING[$type])) { - throw new InvalidArgumentException('The given type is not known and can not be mapped to a class!'); - } - $id_array = $this->rangeParser->parse($ids); /** @var DBElementRepository $repo */ - $repo = $this->em->getRepository(LabelGenerator::CLASS_SUPPORT_MAPPING[$type]); + $repo = $this->em->getRepository($type->getEntityClass()); return $repo->getElementsFromIDArray($id_array); } diff --git a/src/DataFixtures/LabelProfileFixtures.php b/src/DataFixtures/LabelProfileFixtures.php index 77ebe791..23f8e4df 100644 --- a/src/DataFixtures/LabelProfileFixtures.php +++ b/src/DataFixtures/LabelProfileFixtures.php @@ -100,7 +100,7 @@ class LabelProfileFixtures extends Fixture $option4->setLines('{{ element.name }}'); $option4->setBarcodeType('code39'); $option4->setSupportedElement('part'); - $option4->setLinesMode('twig'); + $option4->setProcessMode('twig'); $profile4->setOptions($option4); $manager->persist($profile4); diff --git a/src/Doctrine/Types/BigDecimalType.php b/src/Doctrine/Types/BigDecimalType.php index 6c7bf614..ccc1b491 100644 --- a/src/Doctrine/Types/BigDecimalType.php +++ b/src/Doctrine/Types/BigDecimalType.php @@ -38,10 +38,8 @@ class BigDecimalType extends Type /** * @param string|null $value - * - * @return BigDecimal|BigNumber|mixed */ - public function convertToPHPValue($value, AbstractPlatform $platform) + public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?BigNumber { if (null === $value) { return null; diff --git a/src/Entity/LabelSystem/BarcodeType.php b/src/Entity/LabelSystem/BarcodeType.php new file mode 100644 index 00000000..0794b606 --- /dev/null +++ b/src/Entity/LabelSystem/BarcodeType.php @@ -0,0 +1,64 @@ +. + */ + +namespace App\Entity\LabelSystem; + +enum BarcodeType: string +{ + case NONE = 'none'; + case QR = 'qr'; + case CODE39 = 'code39'; + case DATAMATRIX = 'datamatrix'; + case CODE93 = 'code93'; + case CODE128 = 'code128'; + + /** + * Returns true if the barcode is none. (Useful for twig templates) + * @return bool + */ + public function isNone(): bool + { + return $this === self::NONE; + } + + /** + * Returns true if the barcode is a 1D barcode (Code39, etc.). + * @return bool + */ + public function is1D(): bool + { + return match ($this) { + self::CODE39, self::CODE93, self::CODE128 => true, + default => false, + }; + } + + /** + * Returns true if the barcode is a 2D barcode (QR code, datamatrix). + * @return bool + */ + public function is2D(): bool + { + return match ($this) { + self::QR, self::DATAMATRIX => true, + default => false, + }; + } +} diff --git a/src/Entity/LabelSystem/LabelOptions.php b/src/Entity/LabelSystem/LabelOptions.php index 1ee86079..1d15d0f5 100644 --- a/src/Entity/LabelSystem/LabelOptions.php +++ b/src/Entity/LabelSystem/LabelOptions.php @@ -48,12 +48,6 @@ use Symfony\Component\Validator\Constraints as Assert; #[ORM\Embeddable] class LabelOptions { - final public const BARCODE_TYPES = ['none', /*'ean8',*/ 'qr', 'code39', 'datamatrix', 'code93', 'code128']; - final public const SUPPORTED_ELEMENTS = ['part', 'part_lot', 'storelocation']; - final public const PICTURE_TYPES = ['none', 'element_picture', 'main_attachment']; - - final public const LINES_MODES = ['html', 'twig']; - /** * @var float The page size of the label in mm */ @@ -69,25 +63,19 @@ class LabelOptions protected float $height = 30.0; /** - * @var string The type of the barcode that should be used in the label (e.g. 'qr') + * @var BarcodeType The type of the barcode that should be used in the label (e.g. 'qr') */ - #[Assert\Choice(choices: LabelOptions::BARCODE_TYPES)] - #[ORM\Column(type: Types::STRING)] - protected string $barcode_type = 'none'; + #[ORM\Column(type: Types::STRING, enumType: BarcodeType::class)] + protected BarcodeType $barcode_type = BarcodeType::NONE; /** - * @var string What image should be shown along the + * @var LabelPictureType What image should be shown along the label */ - #[Assert\Choice(choices: LabelOptions::PICTURE_TYPES)] - #[ORM\Column(type: Types::STRING)] - protected string $picture_type = 'none'; + #[ORM\Column(type: Types::STRING, enumType: LabelPictureType::class)] + protected LabelPictureType $picture_type = LabelPictureType::NONE; - /** - * @var string - */ - #[Assert\Choice(choices: LabelOptions::SUPPORTED_ELEMENTS)] - #[ORM\Column(type: Types::STRING)] - protected string $supported_element = 'part'; + #[ORM\Column(type: Types::STRING, enumType: LabelSupportedElement::class)] + protected LabelSupportedElement $supported_element = LabelSupportedElement::PART; /** * @var string any additional CSS for the label @@ -95,11 +83,10 @@ class LabelOptions #[ORM\Column(type: Types::TEXT)] protected string $additional_css = ''; - /** @var string The mode that will be used to interpret the lines + /** @var LabelProcessMode The mode that will be used to interpret the lines */ - #[Assert\Choice(choices: LabelOptions::LINES_MODES)] - #[ORM\Column(type: Types::STRING)] - protected string $lines_mode = 'html'; + #[ORM\Column(type: Types::STRING, enumType: LabelProcessMode::class, name: 'lines_mode')] + protected LabelProcessMode $process_mode = LabelProcessMode::PLACEHOLDER; /** * @var string @@ -131,36 +118,36 @@ class LabelOptions return $this; } - public function getBarcodeType(): string + public function getBarcodeType(): BarcodeType { return $this->barcode_type; } - public function setBarcodeType(string $barcode_type): self + public function setBarcodeType(BarcodeType $barcode_type): self { $this->barcode_type = $barcode_type; return $this; } - public function getPictureType(): string + public function getPictureType(): LabelPictureType { return $this->picture_type; } - public function setPictureType(string $picture_type): self + public function setPictureType(LabelPictureType $picture_type): self { $this->picture_type = $picture_type; return $this; } - public function getSupportedElement(): string + public function getSupportedElement(): LabelSupportedElement { return $this->supported_element; } - public function setSupportedElement(string $supported_element): self + public function setSupportedElement(LabelSupportedElement $supported_element): self { $this->supported_element = $supported_element; @@ -194,14 +181,14 @@ class LabelOptions return $this; } - public function getLinesMode(): string + public function getProcessMode(): LabelProcessMode { - return $this->lines_mode; + return $this->process_mode; } - public function setLinesMode(string $lines_mode): self + public function setProcessMode(LabelProcessMode $process_mode): self { - $this->lines_mode = $lines_mode; + $this->process_mode = $process_mode; return $this; } diff --git a/src/Entity/LabelSystem/LabelPictureType.php b/src/Entity/LabelSystem/LabelPictureType.php new file mode 100644 index 00000000..c9183ca6 --- /dev/null +++ b/src/Entity/LabelSystem/LabelPictureType.php @@ -0,0 +1,37 @@ +. + */ + +namespace App\Entity\LabelSystem; + +enum LabelPictureType: string +{ + /** + * Show no picture on the label + */ + case NONE = 'none'; + /** + * Show the preview picture of the element on the label + */ + case ELEMENT_PICTURE = 'element_picture'; + /** + * Show the main attachment of the element on the label + */ + case MAIN_ATTACHMENT = 'main_attachment'; +} \ No newline at end of file diff --git a/src/Entity/LabelSystem/LabelProcessMode.php b/src/Entity/LabelSystem/LabelProcessMode.php new file mode 100644 index 00000000..76bf175f --- /dev/null +++ b/src/Entity/LabelSystem/LabelProcessMode.php @@ -0,0 +1,29 @@ +. + */ + +namespace App\Entity\LabelSystem; + +enum LabelProcessMode: string +{ + /** Use placeholders like [[PLACEHOLDER]] which gets replaced with content */ + case PLACEHOLDER = 'html'; + /** Interpret the given lines as twig template */ + case TWIG = 'twig'; +} \ No newline at end of file diff --git a/src/Entity/LabelSystem/LabelSupportedElement.php b/src/Entity/LabelSystem/LabelSupportedElement.php new file mode 100644 index 00000000..99bac6c9 --- /dev/null +++ b/src/Entity/LabelSystem/LabelSupportedElement.php @@ -0,0 +1,45 @@ +. + */ + +namespace App\Entity\LabelSystem; + +use App\Entity\Parts\Part; +use App\Entity\Parts\PartLot; +use App\Entity\Parts\Storelocation; + +enum LabelSupportedElement: string +{ + case PART = 'part'; + case PART_LOT = 'part_lot'; + case STORELOCATION = 'storelocation'; + + /** + * Returns the entity class for the given element type + * @return string + */ + public function getEntityClass(): string + { + return match ($this) { + self::PART => Part::class, + self::PART_LOT => PartLot::class, + self::STORELOCATION => Storelocation::class, + }; + } +} \ No newline at end of file diff --git a/src/Form/LabelOptionsType.php b/src/Form/LabelOptionsType.php index 38490c2b..0b15046c 100644 --- a/src/Form/LabelOptionsType.php +++ b/src/Form/LabelOptionsType.php @@ -41,11 +41,15 @@ declare(strict_types=1); namespace App\Form; +use App\Entity\LabelSystem\BarcodeType; +use App\Entity\LabelSystem\LabelProcessMode; +use App\Entity\LabelSystem\LabelSupportedElement; use Symfony\Bundle\SecurityBundle\Security; use App\Entity\LabelSystem\LabelOptions; use App\Form\Type\RichTextEditorType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\EnumType; use Symfony\Component\Form\Extension\Core\Type\NumberType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\FormBuilderInterface; @@ -78,31 +82,33 @@ class LabelOptionsType extends AbstractType ], ]); - $builder->add('supported_element', ChoiceType::class, [ + $builder->add('supported_element', EnumType::class, [ 'label' => 'label_options.supported_elements.label', - 'choices' => [ - 'part.label' => 'part', - 'part_lot.label' => 'part_lot', - 'storelocation.label' => 'storelocation', - ], + 'class' => LabelSupportedElement::class, + 'choice_label' => fn(LabelSupportedElement $choice) => match($choice) { + LabelSupportedElement::PART => 'part.label', + LabelSupportedElement::PART_LOT => 'part_lot.label', + LabelSupportedElement::STORELOCATION => 'storelocation.label', + }, ]); - $builder->add('barcode_type', ChoiceType::class, [ + $builder->add('barcode_type', EnumType::class, [ 'label' => 'label_options.barcode_type.label', 'empty_data' => 'none', - 'choices' => [ - 'label_options.barcode_type.none' => 'none', - 'label_options.barcode_type.qr' => 'qr', - 'label_options.barcode_type.code128' => 'code128', - 'label_options.barcode_type.code39' => 'code39', - 'label_options.barcode_type.code93' => 'code93', - 'label_options.barcode_type.datamatrix' => 'datamatrix', - ], - 'group_by' => static function ($choice, $key, $value): ?string { - if (in_array($choice, ['qr', 'datamatrix'], true)) { + 'class' => BarcodeType::class, + 'choice_label' => fn(BarcodeType $choice) => match($choice) { + BarcodeType::NONE => 'label_options.barcode_type.none', + BarcodeType::QR => 'label_options.barcode_type.qr', + BarcodeType::CODE128 => 'label_options.barcode_type.code128', + BarcodeType::CODE39 => 'label_options.barcode_type.code39', + BarcodeType::CODE93 => 'label_options.barcode_type.code93', + BarcodeType::DATAMATRIX => 'label_options.barcode_type.datamatrix', + }, + 'group_by' => static function (BarcodeType $choice, $key, $value): ?string { + if ($choice->is2D()) { return 'label_options.barcode_type.2D'; } - if (in_array($choice, ['code39', 'code93', 'code128'], true)) { + if ($choice->is1D()) { return 'label_options.barcode_type.1D'; } @@ -129,12 +135,13 @@ class LabelOptionsType extends AbstractType 'required' => false, ]); - $builder->add('lines_mode', ChoiceType::class, [ + $builder->add('process_mode', EnumType::class, [ 'label' => 'label_options.lines_mode.label', - 'choices' => [ - 'label_options.lines_mode.html' => 'html', - 'label.options.lines_mode.twig' => 'twig', - ], + 'class' => LabelProcessMode::class, + 'choice_label' => fn(LabelProcessMode $choice) => match($choice) { + LabelProcessMode::PLACEHOLDER => 'label_options.lines_mode.html', + LabelProcessMode::TWIG => 'label.options.lines_mode.twig', + }, 'help' => 'label_options.lines_mode.help', 'help_html' => true, 'expanded' => true, diff --git a/src/Repository/LabelProfileRepository.php b/src/Repository/LabelProfileRepository.php index f3459af9..1f8ac4fe 100644 --- a/src/Repository/LabelProfileRepository.php +++ b/src/Repository/LabelProfileRepository.php @@ -43,6 +43,7 @@ namespace App\Repository; use App\Entity\LabelSystem\LabelOptions; use App\Entity\LabelSystem\LabelProfile; +use App\Entity\LabelSystem\LabelSupportedElement; use App\Helpers\Trees\TreeViewNode; use InvalidArgumentException; @@ -52,12 +53,8 @@ class LabelProfileRepository extends NamedDBElementRepository * Find the profiles that are shown in the dropdown for the given type. * You should maybe use the cached version of this in LabelProfileDropdownHelper. */ - public function getDropdownProfiles(string $type): array + public function getDropdownProfiles(LabelSupportedElement $type): array { - if (!in_array($type, LabelOptions::SUPPORTED_ELEMENTS, true)) { - throw new InvalidArgumentException('Invalid supported_element type given.'); - } - return $this->findBy([ 'options.supported_element' => $type, 'show_in_dropdown' => true, @@ -74,7 +71,7 @@ class LabelProfileRepository extends NamedDBElementRepository { $result = []; - foreach (LabelOptions::SUPPORTED_ELEMENTS as $type) { + foreach (LabelSupportedElement::cases() as $type) { $type_children = []; $entities = $this->findForSupportedElement($type); foreach ($entities as $entity) { @@ -86,7 +83,7 @@ class LabelProfileRepository extends NamedDBElementRepository if ($type_children !== []) { //Use default label e.g. 'part_label'. $$ marks that it will be translated in TreeViewGenerator - $tmp = new TreeViewNode('$$'.$type.'.label', null, $type_children); + $tmp = new TreeViewNode('$$'.$type->value.'.label', null, $type_children); $result[] = $tmp; } @@ -98,15 +95,11 @@ class LabelProfileRepository extends NamedDBElementRepository /** * Find all LabelProfiles that can be used with the given type. * - * @param string $type see LabelOptions::SUPPORTED_ELEMENTS for valid values + * @param LabelSupportedElement $type see LabelOptions::SUPPORTED_ELEMENTS for valid values * @param array $order_by The way the results should be sorted. By default ordered by */ - public function findForSupportedElement(string $type, array $order_by = ['name' => 'ASC']): array + public function findForSupportedElement(LabelSupportedElement $type, array $order_by = ['name' => 'ASC']): array { - if (!in_array($type, LabelOptions::SUPPORTED_ELEMENTS, true)) { - throw new InvalidArgumentException('Invalid supported_element type given.'); - } - return $this->findBy(['options.supported_element' => $type], $order_by); } @@ -115,7 +108,7 @@ class LabelProfileRepository extends NamedDBElementRepository */ public function getPartLabelProfiles(): array { - return $this->getDropdownProfiles('part'); + return $this->getDropdownProfiles(LabelSupportedElement::PART); } /** @@ -123,7 +116,7 @@ class LabelProfileRepository extends NamedDBElementRepository */ public function getPartLotsLabelProfiles(): array { - return $this->getDropdownProfiles('part_lot'); + return $this->getDropdownProfiles(LabelSupportedElement::PART_LOT); } /** @@ -131,6 +124,6 @@ class LabelProfileRepository extends NamedDBElementRepository */ public function getStorelocationsLabelProfiles(): array { - return $this->getDropdownProfiles('storelocation'); + return $this->getDropdownProfiles(LabelSupportedElement::STORELOCATION); } } diff --git a/src/Services/LabelSystem/BarcodeGenerator.php b/src/Services/LabelSystem/BarcodeGenerator.php index b8ab099e..03eca1f6 100644 --- a/src/Services/LabelSystem/BarcodeGenerator.php +++ b/src/Services/LabelSystem/BarcodeGenerator.php @@ -43,6 +43,7 @@ namespace App\Services\LabelSystem; use App\Entity\Base\AbstractDBElement; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\LabelSystem\BarcodeType; use App\Entity\LabelSystem\LabelOptions; use App\Services\LabelSystem\Barcodes\BarcodeContentGenerator; use Com\Tecnick\Barcode\Barcode; @@ -91,44 +92,31 @@ final class BarcodeGenerator { $barcode = new Barcode(); - switch ($options->getBarcodeType()) { - case 'qr': - $type = 'QRCODE'; + $type = match ($options->getBarcodeType()) { + BarcodeType::NONE => null, + BarcodeType::QR => 'QRCODE', + BarcodeType::DATAMATRIX => 'DATAMATRIX', + BarcodeType::CODE39 => 'C39', + BarcodeType::CODE93 => 'C93', + BarcodeType::CODE128 => 'C128A', + default => throw new InvalidArgumentException('Unknown label type!'), + }; - break; - case 'datamatrix': - $type = 'DATAMATRIX'; - - break; - case 'code39': - $type = 'C39'; - - break; - case 'code93': - $type = 'C93'; - - break; - case 'code128': - $type = 'C128A'; - - break; - case 'none': - return null; - default: - throw new InvalidArgumentException('Unknown label type!'); + if ($type === null) { + return null; } - $bobj = $barcode->getBarcodeObj($type, $this->getContent($options, $target)); - return $bobj->getSvgCode(); + return $barcode->getBarcodeObj($type, $this->getContent($options, $target))->getSvgCode(); } public function getContent(LabelOptions $options, AbstractDBElement $target): ?string { - return match ($options->getBarcodeType()) { - 'qr', 'datamatrix' => $this->barcodeContentGenerator->getURLContent($target), - 'code39', 'code93', 'code128' => $this->barcodeContentGenerator->get1DBarcodeContent($target), - 'none' => null, + $barcode = $options->getBarcodeType(); + return match (true) { + $barcode->is2D() => $this->barcodeContentGenerator->getURLContent($target), + $barcode->is1D() => $this->barcodeContentGenerator->get1DBarcodeContent($target), + $barcode === BarcodeType::NONE => null, default => throw new InvalidArgumentException('Unknown label type!'), }; } diff --git a/src/Services/LabelSystem/LabelExampleElementsGenerator.php b/src/Services/LabelSystem/LabelExampleElementsGenerator.php index d3717208..40ebafa0 100644 --- a/src/Services/LabelSystem/LabelExampleElementsGenerator.php +++ b/src/Services/LabelSystem/LabelExampleElementsGenerator.php @@ -42,6 +42,7 @@ declare(strict_types=1); namespace App\Services\LabelSystem; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\LabelSystem\LabelSupportedElement; use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; @@ -55,12 +56,12 @@ use ReflectionClass; final class LabelExampleElementsGenerator { - public function getElement(string $type): object + public function getElement(LabelSupportedElement $type): object { return match ($type) { - 'part' => $this->getExamplePart(), - 'part_lot' => $this->getExamplePartLot(), - 'storelocation' => $this->getStorelocation(), + LabelSupportedElement::PART => $this->getExamplePart(), + LabelSupportedElement::PART_LOT => $this->getExamplePartLot(), + LabelSupportedElement::STORELOCATION => $this->getStorelocation(), default => throw new InvalidArgumentException('Unknown $type.'), }; } diff --git a/src/Services/LabelSystem/LabelGenerator.php b/src/Services/LabelSystem/LabelGenerator.php index 9f5d666b..41a5235e 100644 --- a/src/Services/LabelSystem/LabelGenerator.php +++ b/src/Services/LabelSystem/LabelGenerator.php @@ -53,12 +53,6 @@ use InvalidArgumentException; */ final class LabelGenerator { - public const CLASS_SUPPORT_MAPPING = [ - 'part' => Part::class, - 'part_lot' => PartLot::class, - 'storelocation' => Storelocation::class, - ]; - public const MM_TO_POINTS_FACTOR = 2.83465; public function __construct(private readonly LabelHTMLGenerator $labelHTMLGenerator) @@ -66,9 +60,9 @@ final class LabelGenerator } /** - * @param object|object[] $elements An element or an array of elements for which labels should be generated + * @param object|object[] $elements An element or an array of elements for which labels should be generated */ - public function generateLabel(LabelOptions $options, $elements): string + public function generateLabel(LabelOptions $options, object|array $elements): string { if (!is_array($elements) && !is_object($elements)) { throw new InvalidArgumentException('$element must be an object or an array of objects!'); @@ -98,11 +92,8 @@ final class LabelGenerator public function supports(LabelOptions $options, object $element): bool { $supported_type = $options->getSupportedElement(); - if (!isset(static::CLASS_SUPPORT_MAPPING[$supported_type])) { - throw new InvalidArgumentException('Supported type name of the Label options not known!'); - } - return is_a($element, static::CLASS_SUPPORT_MAPPING[$supported_type]); + return is_a($element, $supported_type->getEntityClass()); } /** diff --git a/src/Services/LabelSystem/LabelHTMLGenerator.php b/src/Services/LabelSystem/LabelHTMLGenerator.php index 98c3423a..7b6defa6 100644 --- a/src/Services/LabelSystem/LabelHTMLGenerator.php +++ b/src/Services/LabelSystem/LabelHTMLGenerator.php @@ -41,6 +41,7 @@ declare(strict_types=1); namespace App\Services\LabelSystem; +use App\Entity\LabelSystem\LabelProcessMode; use Symfony\Bundle\SecurityBundle\Security; use App\Entity\Contracts\NamedElementInterface; use App\Entity\LabelSystem\LabelOptions; @@ -64,14 +65,14 @@ final class LabelHTMLGenerator $twig_elements = []; - if ('twig' === $options->getLinesMode()) { + if (LabelProcessMode::TWIG === $options->getProcessMode()) { $sandboxed_twig = $this->sandboxedTwigProvider->getTwig($options); $current_user = $this->security->getUser(); } $page = 1; foreach ($elements as $element) { - if (isset($sandboxed_twig, $current_user) && 'twig' === $options->getLinesMode()) { + if (isset($sandboxed_twig, $current_user) && LabelProcessMode::TWIG === $options->getProcessMode()) { try { $lines = $sandboxed_twig->render( 'lines', diff --git a/src/Services/LabelSystem/LabelProfileDropdownHelper.php b/src/Services/LabelSystem/LabelProfileDropdownHelper.php index 4dadd36f..d7f1120d 100644 --- a/src/Services/LabelSystem/LabelProfileDropdownHelper.php +++ b/src/Services/LabelSystem/LabelProfileDropdownHelper.php @@ -42,6 +42,7 @@ declare(strict_types=1); namespace App\Services\LabelSystem; use App\Entity\LabelSystem\LabelProfile; +use App\Entity\LabelSystem\LabelSupportedElement; use App\Repository\LabelProfileRepository; use App\Services\UserSystem\UserCacheKeyGenerator; use Doctrine\ORM\EntityManagerInterface; @@ -54,10 +55,20 @@ final class LabelProfileDropdownHelper { } - public function getDropdownProfiles(string $type): array + /** + * Return all label profiles for the given supported element type + * @param LabelSupportedElement|string $type + * @return array + */ + public function getDropdownProfiles(LabelSupportedElement|string $type): array { + //Useful for the twig templates, where we use the string representation of the enum + if (is_string($type)) { + $type = LabelSupportedElement::from($type); + } + $secure_class_name = str_replace('\\', '_', LabelProfile::class); - $key = 'profile_dropdown_'.$this->keyGenerator->generateKey().'_'.$secure_class_name.'_'.$type; + $key = 'profile_dropdown_'.$this->keyGenerator->generateKey().'_'.$secure_class_name.'_'.$type->value; /** @var LabelProfileRepository $repo */ $repo = $this->entityManager->getRepository(LabelProfile::class); diff --git a/src/Services/LabelSystem/SandboxedTwigProvider.php b/src/Services/LabelSystem/SandboxedTwigProvider.php index 6c1bbce1..a0426cd1 100644 --- a/src/Services/LabelSystem/SandboxedTwigProvider.php +++ b/src/Services/LabelSystem/SandboxedTwigProvider.php @@ -49,6 +49,7 @@ use App\Entity\Base\AbstractStructuralDBElement; use App\Entity\Contracts\NamedElementInterface; use App\Entity\Contracts\TimeStampableInterface; use App\Entity\LabelSystem\LabelOptions; +use App\Entity\LabelSystem\LabelProcessMode; use App\Entity\Parameters\AbstractParameter; use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\Part; @@ -123,7 +124,7 @@ final class SandboxedTwigProvider public function getTwig(LabelOptions $options): Environment { - if ('twig' !== $options->getLinesMode()) { + if (LabelProcessMode::TWIG !== $options->getProcessMode()) { throw new InvalidArgumentException('The LabelOptions must explicitly allow twig via lines_mode = "twig"!'); } diff --git a/src/Twig/TwigCoreExtension.php b/src/Twig/TwigCoreExtension.php index 0443b847..2ff6911a 100644 --- a/src/Twig/TwigCoreExtension.php +++ b/src/Twig/TwigCoreExtension.php @@ -25,6 +25,7 @@ namespace App\Twig; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Twig\Extension\AbstractExtension; use Twig\TwigFilter; +use Twig\TwigFunction; use Twig\TwigTest; /** @@ -37,6 +38,14 @@ final class TwigCoreExtension extends AbstractExtension { } + public function getFunctions() + { + return [ + /* Returns the enum cases as values */ + new TwigFunction('enum_cases', [$this, 'getEnumCases']), + ]; + } + public function getTests(): array { return [ @@ -49,6 +58,15 @@ final class TwigCoreExtension extends AbstractExtension ]; } + public function getEnumCases(string $enum_class): array + { + if (!enum_exists($enum_class)) { + throw new \InvalidArgumentException(sprintf('The given class "%s" is not an enum!', $enum_class)); + } + + return ($enum_class)::cases(); + } + public function getFilters(): array { return [ diff --git a/templates/label_system/dialog.html.twig b/templates/label_system/dialog.html.twig index eb4b0da5..a845d12e 100644 --- a/templates/label_system/dialog.html.twig +++ b/templates/label_system/dialog.html.twig @@ -77,10 +77,10 @@