initial commit

This commit is contained in:
boris
2025-09-30 09:24:25 +01:00
committed by boris
parent a783a12c97
commit c7770ea03b
4695 changed files with 525784 additions and 0 deletions

View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\Twig\Validator\Constraints;
use Symfony\Component\Validator\Attribute\HasNamedArguments;
use Symfony\Component\Validator\Constraint;
/**
* @author Mokhtar Tlili <tlili.mokhtar@gmail.com>
*/
#[\Attribute(\Attribute::TARGET_PROPERTY | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
class Twig extends Constraint
{
public const INVALID_TWIG_ERROR = 'e7fc55d5-e586-4cc1-924e-d27ee7fcd1b5';
protected const ERROR_NAMES = [
self::INVALID_TWIG_ERROR => 'INVALID_TWIG_ERROR',
];
#[HasNamedArguments]
public function __construct(
public string $message = 'This value is not a valid Twig template.',
public bool $skipDeprecations = true,
?array $groups = null,
mixed $payload = null,
) {
parent::__construct(null, $groups, $payload);
}
}

View File

@@ -0,0 +1,85 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bridge\Twig\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
use Twig\Environment;
use Twig\Error\Error;
use Twig\Loader\ArrayLoader;
use Twig\Source;
/**
* @author Mokhtar Tlili <tlili.mokhtar@gmail.com>
*/
class TwigValidator extends ConstraintValidator
{
public function __construct(private Environment $twig)
{
}
public function validate(mixed $value, Constraint $constraint): void
{
if (!$constraint instanceof Twig) {
throw new UnexpectedTypeException($constraint, Twig::class);
}
if (null === $value || '' === $value) {
return;
}
if (!\is_scalar($value) && !$value instanceof \Stringable) {
throw new UnexpectedValueException($value, 'string');
}
$value = (string) $value;
$realLoader = $this->twig->getLoader();
try {
$temporaryLoader = new ArrayLoader([$value]);
$this->twig->setLoader($temporaryLoader);
if (!$constraint->skipDeprecations) {
$prevErrorHandler = set_error_handler(static function ($level, $message, $file, $line) use (&$prevErrorHandler) {
if (\E_USER_DEPRECATED !== $level) {
return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false;
}
$templateLine = 0;
if (preg_match('/ at line (\d+)[ .]/', $message, $matches)) {
$templateLine = $matches[1];
}
throw new Error($message, $templateLine);
});
}
try {
$this->twig->parse($this->twig->tokenize(new Source($value, '')));
} finally {
if (!$constraint->skipDeprecations) {
restore_error_handler();
}
}
} catch (Error $e) {
$this->context->buildViolation($constraint->message)
->setParameter('{{ error }}', $e->getMessage())
->setParameter('{{ line }}', $e->getTemplateLine())
->setCode(Twig::INVALID_TWIG_ERROR)
->addViolation();
} finally {
$this->twig->setLoader($realLoader);
}
}
}