Use enums for LabelOptions

This commit is contained in:
Jan Böhmer 2023-06-12 23:39:30 +02:00
parent 485b35fbd4
commit 71cd4057a7
23 changed files with 329 additions and 157 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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;

View file

@ -0,0 +1,64 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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,
};
}
}

View file

@ -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;
}

View file

@ -0,0 +1,37 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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';
}

View file

@ -0,0 +1,29 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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';
}

View file

@ -0,0 +1,45 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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,
};
}
}

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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!'),
};
}

View file

@ -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.'),
};
}

View file

@ -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());
}
/**

View file

@ -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',

View file

@ -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);

View file

@ -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"!');
}

View file

@ -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 [

View file

@ -77,10 +77,10 @@
</button>
<div class="dropdown-menu" aria-labelledby="loadProfilesButton">
{% if is_granted("@labels.create_labels") %}
{% for type in constant("App\\Entity\\LabelSystem\\LabelOptions::SUPPORTED_ELEMENTS") %}
{% for type in enum_cases("App\\Entity\\LabelSystem\\LabelSupportedElement") %}
{% set profiles = label_profile_dropdown_helper.dropdownProfiles(type) %}
{% if profiles is not empty %}
<h6 class="dropdown-header">{{ (type~'.label') | trans }}</h6>
<h6 class="dropdown-header">{{ (type.value~'.label') | trans }}</h6>
{% endif %}
{% for profile in profiles %}
<a class="dropdown-item" href="{{ path('label_dialog_profile', {'profile': profile.id }) }}">{{ profile.name }}</a>

View file

@ -14,11 +14,11 @@
<body>
{% for element in elements %}
<div class="page">
{% if options.barcodeType == 'none' %}
{% if options.barcodeType.none %}
{% include "label_system/labels/label_page_none.html.twig" %}
{% elseif options.barcodeType in ['qr', 'datamatrix'] %}
{% elseif options.barcodeType.is2D() %}
{% include "label_system/labels/label_page_qr.html.twig" %}
{% elseif options.barcodeType in ['code39', 'code93', 'code128'] %}
{% elseif options.barcodeType.is1D() %}
{% include "label_system/labels/label_page_1d.html.twig" %}
{% endif %}
</div>

View file

@ -41,6 +41,7 @@ declare(strict_types=1);
namespace App\Tests\Services\LabelSystem;
use App\Entity\LabelSystem\BarcodeType;
use App\Entity\LabelSystem\LabelOptions;
use App\Entity\Parts\Part;
use App\Services\LabelSystem\BarcodeGenerator;
@ -65,13 +66,13 @@ final class BarcodeGeneratorTest extends WebTestCase
$part->setName('Test');
//Test that all barcodes types are supported
foreach (LabelOptions::BARCODE_TYPES as $type) {
foreach (BarcodeType::cases() as $type) {
$options = new LabelOptions();
$options->setBarcodeType($type);
$content = $this->services->generateSVG($options, $part);
//When type is none, service must return null.
if ('none' === $type) {
if (BarcodeType::NONE === $type) {
$this->assertNull($content);
} else {
$this->assertIsString($content);
@ -85,13 +86,13 @@ final class BarcodeGeneratorTest extends WebTestCase
$part->setName('Test');
//Test that all barcodes types are supported
foreach (LabelOptions::BARCODE_TYPES as $type) {
foreach (BarcodeType::cases() as $type) {
$options = new LabelOptions();
$options->setBarcodeType($type);
$svg = $this->services->generateSVG($options, $part);
//When type is none, service must return null.
if ('none' === $type) {
if (BarcodeType::NONE === $type) {
$this->assertNull($svg);
} else {
$this->assertStringContainsStringIgnoringCase('SVG', $svg);

View file

@ -43,6 +43,7 @@ namespace App\Tests\Services\LabelSystem;
use App\Entity\Base\AbstractDBElement;
use App\Entity\LabelSystem\LabelOptions;
use App\Entity\LabelSystem\LabelSupportedElement;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\Storelocation;
@ -62,19 +63,19 @@ class LabelGeneratorTest extends WebTestCase
$this->service = self::getContainer()->get(LabelGenerator::class);
}
public function supportsDataProvider(): array
public static function supportsDataProvider(): array
{
return [
['part', Part::class],
['part_lot', PartLot::class],
['storelocation', Storelocation::class],
[LabelSupportedElement::PART, Part::class],
[LabelSupportedElement::PART_LOT, PartLot::class],
[LabelSupportedElement::STORELOCATION, Storelocation::class],
];
}
/**
* @dataProvider supportsDataProvider
*/
public function testSupports(string $type, string $class): void
public function testSupports(LabelSupportedElement $type, string $class): void
{
$options = new LabelOptions();
$options->setSupportedElement($type);
@ -102,7 +103,7 @@ class LabelGeneratorTest extends WebTestCase
$part = new Part();
$options = new LabelOptions();
$options->setLines('Test');
$options->setSupportedElement('part');
$options->setSupportedElement(LabelSupportedElement::PART);
//Test for a single passed element:
$pdf = $this->service->generateLabel($options, $part);

View file

@ -42,6 +42,8 @@ declare(strict_types=1);
namespace App\Tests\Services\LabelSystem;
use App\Entity\LabelSystem\LabelOptions;
use App\Entity\LabelSystem\LabelProcessMode;
use App\Entity\LabelSystem\LabelSupportedElement;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartLot;
use App\Entity\Parts\Storelocation;
@ -104,9 +106,9 @@ class SandboxedTwigProviderTest extends WebTestCase
public function testTwigFeatures(string $twig): void
{
$options = new LabelOptions();
$options->setSupportedElement('part');
$options->setSupportedElement(LabelSupportedElement::PART);
$options->setLines($twig);
$options->setLinesMode('twig');
$options->setProcessMode(LabelProcessMode::TWIG);
$twig = $this->service->getTwig($options);
$str = $twig->render('lines', [
@ -126,9 +128,9 @@ class SandboxedTwigProviderTest extends WebTestCase
$this->expectException(SecurityError::class);
$options = new LabelOptions();
$options->setSupportedElement('part');
$options->setSupportedElement(LabelSupportedElement::PART);
$options->setLines($twig);
$options->setLinesMode('twig');
$options->setProcessMode(LabelProcessMode::TWIG);
$twig = $this->service->getTwig($options);
$str = $twig->render('lines', [