feat: admin editable email templates
addresses #869eg7ptr
This commit is contained in:
1 parent
804dab335f
commit
3e08965e48
49 files changed
+1760
-276
No files matched your search
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
/**
|
||||
* Rejects {tokens} the mail being edited does not know.
|
||||
*
|
||||
* Without this a typo like {destinaton} would reach a teamer's inbox as a literal token
|
||||
* or, worse, silently as a dash.
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::IS_REPEATABLE)]
|
||||
class KnownPlaceholders extends Constraint
|
||||
{
|
||||
public string $message = 'Unbekannter Platzhalter: {{ placeholder }}. Erlaubt sind: {{ allowed }}';
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
public array $allowed = [];
|
||||
|
||||
/**
|
||||
* @param string[] $allowed
|
||||
*/
|
||||
public function __construct(array $allowed = [], ?string $message = null, ?array $groups = null, mixed $payload = null)
|
||||
{
|
||||
parent::__construct([], $groups, $payload);
|
||||
|
||||
$this->allowed = $allowed;
|
||||
$this->message = $message ?? $this->message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Validator;
|
||||
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
class KnownPlaceholdersValidator extends ConstraintValidator
|
||||
{
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (!$constraint instanceof KnownPlaceholders) {
|
||||
throw new UnexpectedTypeException($constraint, KnownPlaceholders::class);
|
||||
}
|
||||
|
||||
if (null === $value || '' === $value) {
|
||||
return;
|
||||
}
|
||||
|
||||
preg_match_all('/\{(\w+)\}/', (string) $value, $matches);
|
||||
|
||||
foreach (array_unique($matches[1]) as $placeholder) {
|
||||
if (in_array($placeholder, $constraint->allowed, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->context
|
||||
->buildViolation($constraint->message)
|
||||
->setParameter('{{ placeholder }}', '{'.$placeholder.'}')
|
||||
->setParameter('{{ allowed }}', implode(', ', array_map(
|
||||
static fn (string $name): string => '{'.$name.'}',
|
||||
$constraint->allowed
|
||||
)))
|
||||
->addViolation()
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user