diff --git a/src/Services/LabelSystem/LabelHTMLGenerator.php b/src/Services/LabelSystem/LabelHTMLGenerator.php
index 620d7746..b2df055e 100644
--- a/src/Services/LabelSystem/LabelHTMLGenerator.php
+++ b/src/Services/LabelSystem/LabelHTMLGenerator.php
@@ -53,7 +53,14 @@ use Twig\Error\Error;
final class LabelHTMLGenerator
{
- public function __construct(private readonly ElementTypeNameGenerator $elementTypeNameGenerator, private readonly LabelTextReplacer $replacer, private readonly Environment $twig, private readonly LabelBarcodeGenerator $barcodeGenerator, private readonly SandboxedTwigFactory $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 SandboxedTwigFactory $sandboxedTwigProvider,
+ private readonly Security $security,
+ private readonly string $partdb_title)
{
}
diff --git a/src/Services/LabelSystem/LabelTextReplacer.php b/src/Services/LabelSystem/LabelTextReplacer.php
index 034e243f..6f0a9ee8 100644
--- a/src/Services/LabelSystem/LabelTextReplacer.php
+++ b/src/Services/LabelSystem/LabelTextReplacer.php
@@ -64,6 +64,17 @@ final class LabelTextReplacer
* @return string If the placeholder was valid, the replaced info. Otherwise the passed string.
*/
public function handlePlaceholder(string $placeholder, object $target): string
+ {
+ return $this->handlePlaceholderOrReturnNull($placeholder, $target) ?? $placeholder;
+ }
+
+ /**
+ * Similar to handlePlaceholder, but returns null if the placeholder is not known (instead of the original string)
+ * @param string $placeholder
+ * @param object $target
+ * @return string|null
+ */
+ public function handlePlaceholderOrReturnNull(string $placeholder, object $target): ?string
{
foreach ($this->providers as $provider) {
/** @var PlaceholderProviderInterface $provider */
@@ -73,7 +84,7 @@ final class LabelTextReplacer
}
}
- return $placeholder;
+ return null;
}
/**
diff --git a/src/Services/LabelSystem/SandboxedTwigFactory.php b/src/Services/LabelSystem/SandboxedTwigFactory.php
index 1ae5d79d..e8a3a4cf 100644
--- a/src/Services/LabelSystem/SandboxedTwigFactory.php
+++ b/src/Services/LabelSystem/SandboxedTwigFactory.php
@@ -64,6 +64,7 @@ use App\Twig\BarcodeExtension;
use App\Twig\EntityExtension;
use App\Twig\FormatExtension;
use App\Twig\Sandbox\InheritanceSecurityPolicy;
+use App\Twig\Sandbox\SandboxedLabelExtension;
use App\Twig\TwigCoreExtension;
use InvalidArgumentException;
use Twig\Environment;
@@ -92,6 +93,9 @@ final class SandboxedTwigFactory
//FormatExtension:
'format_money', 'format_si', 'format_amount', 'format_bytes',
+
+ //SandboxedLabelExtension
+ 'placeholders',
];
private const ALLOWED_FUNCTIONS = ['country_names', 'country_timezones', 'currency_names', 'cycle',
@@ -103,7 +107,8 @@ final class SandboxedTwigFactory
'entity_type', 'entity_url',
//BarcodeExtension:
'barcode_svg',
-
+ //SandboxedLabelExtension
+ 'placeholder',
];
private const ALLOWED_METHODS = [
@@ -143,6 +148,7 @@ final class SandboxedTwigFactory
private readonly BarcodeExtension $barcodeExtension,
private readonly EntityExtension $entityExtension,
private readonly TwigCoreExtension $twigCoreExtension,
+ private readonly SandboxedLabelExtension $sandboxedLabelExtension,
)
{
}
@@ -172,6 +178,7 @@ final class SandboxedTwigFactory
$twig->addExtension($this->barcodeExtension);
$twig->addExtension($this->entityExtension);
$twig->addExtension($this->twigCoreExtension);
+ $twig->addExtension($this->sandboxedLabelExtension);
return $twig;
}
diff --git a/src/Twig/Sandbox/SandboxedLabelExtension.php b/src/Twig/Sandbox/SandboxedLabelExtension.php
new file mode 100644
index 00000000..540f204f
--- /dev/null
+++ b/src/Twig/Sandbox/SandboxedLabelExtension.php
@@ -0,0 +1,51 @@
+.
+ */
+
+declare(strict_types=1);
+
+
+namespace App\Twig\Sandbox;
+
+use App\Services\LabelSystem\LabelTextReplacer;
+use Twig\Extension\AbstractExtension;
+use Twig\TwigFilter;
+use Twig\TwigFunction;
+
+class SandboxedLabelExtension extends AbstractExtension
+{
+ public function __construct(private readonly LabelTextReplacer $labelTextReplacer)
+ {
+
+ }
+
+ public function getFunctions()
+ {
+ return [
+ new TwigFunction('placeholder', fn(string $text, object $label_target) => $this->labelTextReplacer->handlePlaceholderOrReturnNull($text, $label_target)),
+ ];
+ }
+
+ public function getFilters(): array
+ {
+ return [
+ new TwigFilter('placeholders', fn(string $text, object $label_target) => $this->labelTextReplacer->replace($text, $label_target)),
+ ];
+ }
+}
\ No newline at end of file
diff --git a/tests/Services/LabelSystem/SandboxedTwigFactoryTest.php b/tests/Services/LabelSystem/SandboxedTwigFactoryTest.php
index 2b9a7873..7d43db7a 100644
--- a/tests/Services/LabelSystem/SandboxedTwigFactoryTest.php
+++ b/tests/Services/LabelSystem/SandboxedTwigFactoryTest.php
@@ -88,6 +88,10 @@ class SandboxedTwigFactoryTest extends WebTestCase
'],
['
{{ entity_type(part) is object }}
+ '],
+ ['
+ {% apply placeholders(part) %}[[NAME]]{% endapply %}
+ {{ placeholder("[[NAME]]", part) }}
']
];
}