diff --git a/assets/ckeditor/plugins/PartDBLabel/PartDBLabelUI.js b/assets/ckeditor/plugins/PartDBLabel/PartDBLabelUI.js
index 03737dae..aa29e889 100644
--- a/assets/ckeditor/plugins/PartDBLabel/PartDBLabelUI.js
+++ b/assets/ckeditor/plugins/PartDBLabel/PartDBLabelUI.js
@@ -85,6 +85,9 @@ const PLACEHOLDERS = [
['[[COMMENT_T]]', 'Comment (plain text)'],
['[[LAST_MODIFIED]]', 'Last modified datetime'],
['[[CREATION_DATE]]', 'Creation datetime'],
+ ['[[IPN_BARCODE_QR]]', 'IPN as QR code'],
+ ['[[IPN_BARCODE_C128]]', 'IPN as Code 128 barcode'],
+ ['[[IPN_BARCODE_C39]]', 'IPN as Code 39 barcode'],
]
},
{
diff --git a/assets/ckeditor/plugins/PartDBLabel/lang/de.js b/assets/ckeditor/plugins/PartDBLabel/lang/de.js
index 53007a0a..2220cc0b 100644
--- a/assets/ckeditor/plugins/PartDBLabel/lang/de.js
+++ b/assets/ckeditor/plugins/PartDBLabel/lang/de.js
@@ -48,6 +48,9 @@ Object.assign( window.CKEDITOR_TRANSLATIONS[ 'de' ].dictionary, {
'Comment (plain text)': 'Kommentar (Nur-Text)',
'Last modified datetime': 'Zuletzt geändert',
'Creation datetime': 'Erstellt',
+ 'IPN as QR code': 'IPN als QR Code',
+ 'IPN as Code 128 barcode': 'IPN als Code 128 Barcode',
+ 'IPN as Code 39 barcode': 'IPN als Code 39 Barcode',
'Lot ID': 'Lot ID',
'Lot name': 'Lot Name',
diff --git a/src/Services/LabelSystem/Barcodes/BarcodeContentGenerator.php b/src/Services/LabelSystem/Barcodes/BarcodeContentGenerator.php
index 33743e4f..7ceb30dd 100644
--- a/src/Services/LabelSystem/Barcodes/BarcodeContentGenerator.php
+++ b/src/Services/LabelSystem/Barcodes/BarcodeContentGenerator.php
@@ -76,11 +76,11 @@ final class BarcodeContentGenerator
{
$type = $this->classToString(self::URL_MAP, $target);
- return $this->urlGenerator->generate('scan_qr', [
- 'type' => $type,
+ return $this->urlGenerator->generate('scan_qr', [
+ 'type' => $type,
'id' => $target->getID() ?? 0,
'_locale' => null,
-], UrlGeneratorInterface::ABSOLUTE_URL);
+ ], UrlGeneratorInterface::ABSOLUTE_URL);
}
/**
diff --git a/src/Services/LabelSystem/Barcodes/BarcodeHelper.php b/src/Services/LabelSystem/Barcodes/BarcodeHelper.php
new file mode 100644
index 00000000..d13da589
--- /dev/null
+++ b/src/Services/LabelSystem/Barcodes/BarcodeHelper.php
@@ -0,0 +1,96 @@
+.
+ */
+
+declare(strict_types=1);
+
+
+namespace App\Services\LabelSystem\Barcodes;
+
+use App\Entity\LabelSystem\BarcodeType;
+use Com\Tecnick\Barcode\Barcode;
+
+/**
+ * This function is used to generate barcodes of various types using arbitrary (text) content.
+ */
+class BarcodeHelper
+{
+
+ /**
+ * Generates a barcode with the given content and type and returns it as SVG string.
+ * @param string $content
+ * @param BarcodeType $type
+ * @return string
+ */
+ public function barcodeAsSVG(string $content, BarcodeType $type): string
+ {
+ $barcode = new Barcode();
+
+ $type_str = match ($type) {
+ BarcodeType::NONE => throw new \InvalidArgumentException('Barcode type must not be NONE! This would make no sense...'),
+ BarcodeType::QR => 'QRCODE',
+ BarcodeType::DATAMATRIX => 'DATAMATRIX',
+ BarcodeType::CODE39 => 'C39',
+ BarcodeType::CODE93 => 'C93',
+ BarcodeType::CODE128 => 'C128A',
+ };
+
+ return $barcode->getBarcodeObj($type_str, $content)->getSvgCode();
+ }
+
+ /**
+ * Generates a barcode with the given content and type and returns it as HTML image tag.
+ * @param string $content
+ * @param BarcodeType $type
+ * @param string $width Width of the image tag
+ * @param string|null $alt_text The alt text of the image tag. If null, the content is used.
+ * @return string
+ */
+ public function barcodeAsHTML(string $content, BarcodeType $type, string $width = '100%', ?string $alt_text = null): string
+ {
+ $svg = $this->barcodeAsSVG($content, $type);
+ $base64 = $this->dataUri($svg, 'image/svg+xml');
+ $alt_text = $alt_text ?? $content;
+
+ return '
';
+ }
+
+ /**
+ * Creates a data URI (RFC 2397).
+ * Based on the Twig implementation from HTMLExtension
+ *
+ * Length validation is not performed on purpose, validation should
+ * be done before calling this filter.
+ *
+ * @return string The generated data URI
+ */
+ private function dataUri(string $data, string $mime): string
+ {
+ $repr = 'data:';
+
+ $repr .= $mime;
+ if (str_starts_with($mime, 'text/')) {
+ $repr .= ','.rawurlencode($data);
+ } else {
+ $repr .= ';base64,'.base64_encode($data);
+ }
+
+ return $repr;
+ }
+}
\ No newline at end of file
diff --git a/src/Services/LabelSystem/BarcodeGenerator.php b/src/Services/LabelSystem/LabelBarcodeGenerator.php
similarity index 64%
rename from src/Services/LabelSystem/BarcodeGenerator.php
rename to src/Services/LabelSystem/LabelBarcodeGenerator.php
index f955955a..ea0d8f44 100644
--- a/src/Services/LabelSystem/BarcodeGenerator.php
+++ b/src/Services/LabelSystem/LabelBarcodeGenerator.php
@@ -46,67 +46,47 @@ use App\Entity\Base\AbstractStructuralDBElement;
use App\Entity\LabelSystem\BarcodeType;
use App\Entity\LabelSystem\LabelOptions;
use App\Services\LabelSystem\Barcodes\BarcodeContentGenerator;
+use App\Services\LabelSystem\Barcodes\BarcodeHelper;
use Com\Tecnick\Barcode\Barcode;
use InvalidArgumentException;
/**
* @see \App\Tests\Services\LabelSystem\BarcodeGeneratorTest
*/
-final class BarcodeGenerator
+final class LabelBarcodeGenerator
{
- public function __construct(private readonly BarcodeContentGenerator $barcodeContentGenerator)
+ public function __construct(private readonly BarcodeContentGenerator $barcodeContentGenerator, private readonly BarcodeHelper $barcodeHelper)
{
}
- public function generateHTMLBarcode(LabelOptions $options, object $target): ?string
- {
- $svg = $this->generateSVG($options, $target);
- $base64 = $this->dataUri($svg, 'image/svg+xml');
- return '
';
- }
-
- /**
- * Creates a data URI (RFC 2397).
- * Based on the Twig implementaion from HTMLExtension
- *
- * Length validation is not performed on purpose, validation should
- * be done before calling this filter.
- *
- * @return string The generated data URI
+ /**
+ * Generate the barcode for the given label as HTML image tag.
+ * @param LabelOptions $options
+ * @param AbstractDBElement $target
+ * @return string|null
*/
- private function dataUri(string $data, string $mime): string
+ public function generateHTMLBarcode(LabelOptions $options, AbstractDBElement $target): ?string
{
- $repr = 'data:';
-
- $repr .= $mime;
- if (str_starts_with($mime, 'text/')) {
- $repr .= ','.rawurlencode($data);
- } else {
- $repr .= ';base64,'.base64_encode($data);
- }
-
- return $repr;
- }
-
- public function generateSVG(LabelOptions $options, object $target): ?string
- {
- $barcode = new Barcode();
-
- $type = match ($options->getBarcodeType()) {
- BarcodeType::NONE => null,
- BarcodeType::QR => 'QRCODE',
- BarcodeType::DATAMATRIX => 'DATAMATRIX',
- BarcodeType::CODE39 => 'C39',
- BarcodeType::CODE93 => 'C93',
- BarcodeType::CODE128 => 'C128A',
- };
-
- if ($type === null) {
+ if ($options->getBarcodeType() === BarcodeType::NONE) {
return null;
}
+ return $this->barcodeHelper->barcodeAsHTML($this->getContent($options, $target), $options->getBarcodeType());
+ }
- return $barcode->getBarcodeObj($type, $this->getContent($options, $target))->getSvgCode();
+ /**
+ * Generate the barcode for the given label as SVG string.
+ * @param LabelOptions $options
+ * @param AbstractDBElement $target
+ * @return string|null
+ */
+ public function generateSVG(LabelOptions $options, AbstractDBElement $target): ?string
+ {
+ if ($options->getBarcodeType() === BarcodeType::NONE) {
+ return null;
+ }
+
+ return $this->barcodeHelper->barcodeAsSVG($this->getContent($options, $target), $options->getBarcodeType());
}
public function getContent(LabelOptions $options, AbstractDBElement $target): ?string
diff --git a/src/Services/LabelSystem/LabelHTMLGenerator.php b/src/Services/LabelSystem/LabelHTMLGenerator.php
index 7b6defa6..b4184646 100644
--- a/src/Services/LabelSystem/LabelHTMLGenerator.php
+++ b/src/Services/LabelSystem/LabelHTMLGenerator.php
@@ -53,7 +53,7 @@ use Twig\Error\Error;
final class LabelHTMLGenerator
{
- public function __construct(private readonly ElementTypeNameGenerator $elementTypeNameGenerator, private readonly LabelTextReplacer $replacer, private readonly Environment $twig, private readonly BarcodeGenerator $barcodeGenerator, private readonly SandboxedTwigProvider $sandboxedTwigProvider, private readonly Security $security, private readonly string $partdb_title)
+ public function __construct(private readonly ElementTypeNameGenerator $elementTypeNameGenerator, private readonly LabelTextReplacer $replacer, private readonly Environment $twig, private readonly LabelBarcodeGenerator $barcodeGenerator, private readonly SandboxedTwigProvider $sandboxedTwigProvider, private readonly Security $security, private readonly string $partdb_title)
{
}
diff --git a/src/Services/LabelSystem/PlaceholderProviders/BarcodeProvider.php b/src/Services/LabelSystem/PlaceholderProviders/BarcodeProvider.php
index 11824054..80685e86 100644
--- a/src/Services/LabelSystem/PlaceholderProviders/BarcodeProvider.php
+++ b/src/Services/LabelSystem/PlaceholderProviders/BarcodeProvider.php
@@ -24,12 +24,18 @@ namespace App\Services\LabelSystem\PlaceholderProviders;
use App\Entity\LabelSystem\BarcodeType;
use App\Entity\LabelSystem\LabelOptions;
-use App\Services\LabelSystem\BarcodeGenerator;
+use App\Entity\Parts\Part;
+use App\Entity\Parts\PartLot;
+use App\Services\LabelSystem\Barcodes\BarcodeHelper;
+use App\Services\LabelSystem\LabelBarcodeGenerator;
use App\Services\LabelSystem\Barcodes\BarcodeContentGenerator;
+use Com\Tecnick\Barcode\Exception;
final class BarcodeProvider implements PlaceholderProviderInterface
{
- public function __construct(private readonly BarcodeGenerator $barcodeGenerator, private readonly BarcodeContentGenerator $barcodeContentGenerator)
+ public function __construct(private readonly LabelBarcodeGenerator $barcodeGenerator,
+ private readonly BarcodeContentGenerator $barcodeContentGenerator,
+ private readonly BarcodeHelper $barcodeHelper)
{
}
@@ -69,6 +75,36 @@ final class BarcodeProvider implements PlaceholderProviderInterface
return $this->barcodeGenerator->generateHTMLBarcode($label_options, $label_target);
}
+ if ($label_target instanceof Part || $label_target instanceof PartLot) {
+ if ($label_target instanceof PartLot) {
+ $label_target = $label_target->getPart();
+ }
+
+ if ($label_target === null || $label_target->getIPN() === null || $label_target->getIPN() === '') {
+ //Replace with empty result, if no IPN is set
+ return '';
+ }
+
+ try {
+ //Add placeholders for the IPN barcode
+ if ('[[IPN_BARCODE_C39]]' === $placeholder) {
+ return $this->barcodeHelper->barcodeAsHTML($label_target->getIPN(), BarcodeType::CODE39);
+ }
+ if ('[[IPN_BARCODE_C128]]' === $placeholder) {
+ return $this->barcodeHelper->barcodeAsHTML($label_target->getIPN(), BarcodeType::CODE128);
+ }
+ if ('[[IPN_BARCODE_QR]]' === $placeholder) {
+ return $this->barcodeHelper->barcodeAsHTML($label_target->getIPN(), BarcodeType::QR);
+ }
+ } catch (Exception $e) {
+ //If an error occurs, output it
+ return 'IPN Barcode ERROR!: '.$e->getMessage();
+ }
+ }
+
+
+
+
return null;
}
}
diff --git a/tests/Services/LabelSystem/Barcodes/BarcodeHelperTest.php b/tests/Services/LabelSystem/Barcodes/BarcodeHelperTest.php
new file mode 100644
index 00000000..e0639427
--- /dev/null
+++ b/tests/Services/LabelSystem/Barcodes/BarcodeHelperTest.php
@@ -0,0 +1,68 @@
+.
+ */
+
+namespace App\Tests\Services\LabelSystem\Barcodes;
+
+use App\Entity\LabelSystem\BarcodeType;
+use App\Services\LabelSystem\Barcodes\BarcodeHelper;
+use PHPUnit\Framework\TestCase;
+use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
+
+class BarcodeHelperTest extends WebTestCase
+{
+
+ protected ?BarcodeHelper $service = null;
+
+ protected function setUp(): void
+ {
+ self::bootKernel();
+ $this->service = self::getContainer()->get(BarcodeHelper::class);
+ }
+
+ public function testBarcodeAsHTML(): void
+ {
+ $html = $this->service->barcodeAsHTML('Test', BarcodeType::QR);
+ $this->assertStringStartsWith('
assertStringContainsString('alt="Test"', $html);
+ }
+
+ public function testBarcodeAsSVG(): void
+ {
+ //Test that all barcodes types are supported
+ foreach (BarcodeType::cases() as $type) {
+ //Skip NONE type
+ if (BarcodeType::NONE === $type) {
+ continue;
+ }
+
+ $svg = $this->service->barcodeAsSVG('1234', $type);
+
+ $this->assertStringContainsStringIgnoringCase('SVG', $svg);
+ }
+ }
+
+ public function testBarcodeAsSVGNoneType(): void
+ {
+ //On NONE type, service must throw an exception.
+ $this->expectException(\InvalidArgumentException::class);
+
+ $this->service->barcodeAsSVG('test', BarcodeType::NONE);
+ }
+}
diff --git a/tests/Services/LabelSystem/BarcodeGeneratorTest.php b/tests/Services/LabelSystem/LabelBarcodeGeneratorTest.php
similarity index 89%
rename from tests/Services/LabelSystem/BarcodeGeneratorTest.php
rename to tests/Services/LabelSystem/LabelBarcodeGeneratorTest.php
index 0677b48e..4afdd9d2 100644
--- a/tests/Services/LabelSystem/BarcodeGeneratorTest.php
+++ b/tests/Services/LabelSystem/LabelBarcodeGeneratorTest.php
@@ -44,20 +44,17 @@ 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;
+use App\Services\LabelSystem\LabelBarcodeGenerator;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
-final class BarcodeGeneratorTest extends WebTestCase
+final class LabelBarcodeGeneratorTest extends WebTestCase
{
- /**
- * @var BarcodeGenerator
- */
- protected $services;
+ protected ?LabelBarcodeGenerator $service = null;
protected function setUp(): void
{
self::bootKernel();
- $this->services = self::getContainer()->get(BarcodeGenerator::class);
+ $this->service = self::getContainer()->get(LabelBarcodeGenerator::class);
}
public function testGetContent(): void
@@ -69,7 +66,7 @@ final class BarcodeGeneratorTest extends WebTestCase
foreach (BarcodeType::cases() as $type) {
$options = new LabelOptions();
$options->setBarcodeType($type);
- $content = $this->services->generateSVG($options, $part);
+ $content = $this->service->generateSVG($options, $part);
//When type is none, service must return null.
if (BarcodeType::NONE === $type) {
@@ -89,7 +86,7 @@ final class BarcodeGeneratorTest extends WebTestCase
foreach (BarcodeType::cases() as $type) {
$options = new LabelOptions();
$options->setBarcodeType($type);
- $svg = $this->services->generateSVG($options, $part);
+ $svg = $this->service->generateSVG($options, $part);
//When type is none, service must return null.
if (BarcodeType::NONE === $type) {