mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-20 17:15:51 +02:00
Use enums for LabelOptions
This commit is contained in:
parent
485b35fbd4
commit
71cd4057a7
23 changed files with 329 additions and 157 deletions
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
64
src/Entity/LabelSystem/BarcodeType.php
Normal file
64
src/Entity/LabelSystem/BarcodeType.php
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
37
src/Entity/LabelSystem/LabelPictureType.php
Normal file
37
src/Entity/LabelSystem/LabelPictureType.php
Normal 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';
|
||||
}
|
29
src/Entity/LabelSystem/LabelProcessMode.php
Normal file
29
src/Entity/LabelSystem/LabelProcessMode.php
Normal 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';
|
||||
}
|
45
src/Entity/LabelSystem/LabelSupportedElement.php
Normal file
45
src/Entity/LabelSystem/LabelSupportedElement.php
Normal 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,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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!'),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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.'),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"!');
|
||||
}
|
||||
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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', [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue