login consent app sql
This commit is contained in:
182
vendor/symfony/twig-bridge/AppVariable.php
vendored
Normal file
182
vendor/symfony/twig-bridge/AppVariable.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?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;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
/**
|
||||
* Exposes some Symfony parameters and services as an "app" global variable.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class AppVariable
|
||||
{
|
||||
private $tokenStorage;
|
||||
private $requestStack;
|
||||
private $environment;
|
||||
private $debug;
|
||||
|
||||
public function setTokenStorage(TokenStorageInterface $tokenStorage)
|
||||
{
|
||||
$this->tokenStorage = $tokenStorage;
|
||||
}
|
||||
|
||||
public function setRequestStack(RequestStack $requestStack)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
public function setEnvironment(string $environment)
|
||||
{
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
public function setDebug(bool $debug)
|
||||
{
|
||||
$this->debug = $debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current token.
|
||||
*
|
||||
* @return TokenInterface|null
|
||||
*
|
||||
* @throws \RuntimeException When the TokenStorage is not available
|
||||
*/
|
||||
public function getToken()
|
||||
{
|
||||
if (null === $tokenStorage = $this->tokenStorage) {
|
||||
throw new \RuntimeException('The "app.token" variable is not available.');
|
||||
}
|
||||
|
||||
return $tokenStorage->getToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current user.
|
||||
*
|
||||
* @return UserInterface|null
|
||||
*
|
||||
* @see TokenInterface::getUser()
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
if (null === $tokenStorage = $this->tokenStorage) {
|
||||
throw new \RuntimeException('The "app.user" variable is not available.');
|
||||
}
|
||||
|
||||
if (!$token = $tokenStorage->getToken()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$user = $token->getUser();
|
||||
|
||||
// @deprecated since Symfony 5.4, $user will always be a UserInterface instance
|
||||
return \is_object($user) ? $user : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current request.
|
||||
*
|
||||
* @return Request|null
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
if (null === $this->requestStack) {
|
||||
throw new \RuntimeException('The "app.request" variable is not available.');
|
||||
}
|
||||
|
||||
return $this->requestStack->getCurrentRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current session.
|
||||
*
|
||||
* @return Session|null
|
||||
*/
|
||||
public function getSession()
|
||||
{
|
||||
if (null === $this->requestStack) {
|
||||
throw new \RuntimeException('The "app.session" variable is not available.');
|
||||
}
|
||||
$request = $this->getRequest();
|
||||
|
||||
return $request && $request->hasSession() ? $request->getSession() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current app environment.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEnvironment()
|
||||
{
|
||||
if (null === $this->environment) {
|
||||
throw new \RuntimeException('The "app.environment" variable is not available.');
|
||||
}
|
||||
|
||||
return $this->environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current app debug mode.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getDebug()
|
||||
{
|
||||
if (null === $this->debug) {
|
||||
throw new \RuntimeException('The "app.debug" variable is not available.');
|
||||
}
|
||||
|
||||
return $this->debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns some or all the existing flash messages:
|
||||
* * getFlashes() returns all the flash messages
|
||||
* * getFlashes('notice') returns a simple array with flash messages of that type
|
||||
* * getFlashes(['notice', 'error']) returns a nested array of type => messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFlashes($types = null)
|
||||
{
|
||||
try {
|
||||
if (null === $session = $this->getSession()) {
|
||||
return [];
|
||||
}
|
||||
} catch (\RuntimeException $e) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (null === $types || '' === $types || [] === $types) {
|
||||
return $session->getFlashBag()->all();
|
||||
}
|
||||
|
||||
if (\is_string($types)) {
|
||||
return $session->getFlashBag()->get($types);
|
||||
}
|
||||
|
||||
$result = [];
|
||||
foreach ($types as $type) {
|
||||
$result[$type] = $session->getFlashBag()->get($type);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
169
vendor/symfony/twig-bridge/CHANGELOG.md
vendored
Normal file
169
vendor/symfony/twig-bridge/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,169 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
5.4
|
||||
---
|
||||
|
||||
* Add `github` format & autodetection to render errors as annotations when
|
||||
running the Twig linter command in a Github Actions environment.
|
||||
|
||||
5.3
|
||||
---
|
||||
|
||||
* Add a new `markAsPublic` method on `NotificationEmail` to change the `importance` context option to null after creation
|
||||
* Add a new `fragment_uri()` helper to generate the URI of a fragment
|
||||
* Add support of Bootstrap 5 for form theming
|
||||
* Add a new `serialize` filter to serialize objects using the Serializer component
|
||||
|
||||
5.2.0
|
||||
-----
|
||||
|
||||
* added the `impersonation_exit_url()` and `impersonation_exit_path()` functions. They return a URL that allows to switch back to the original user.
|
||||
* added the `workflow_transition()` function to easily retrieve a specific transition object
|
||||
* added support for translating `TranslatableInterface` objects
|
||||
* added the `t()` function to easily create `TranslatableMessage` objects
|
||||
* Added support for extracting messages from the `t()` function
|
||||
* Added `field_*` Twig functions to access string values from Form fields
|
||||
* changed the `importance` context option of `NotificationEmail` to allow `null`
|
||||
|
||||
5.0.0
|
||||
-----
|
||||
|
||||
* removed `TwigEngine` class, use `\Twig\Environment` instead.
|
||||
* removed `transChoice` filter and token
|
||||
* `HttpFoundationExtension` requires a `UrlHelper` on instantiation
|
||||
* removed support for implicit STDIN usage in the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit.
|
||||
* added form theme for Foundation 6
|
||||
* added support for Foundation 6 switches: add the `switch-input` class to the attributes of a `CheckboxType`
|
||||
|
||||
4.4.0
|
||||
-----
|
||||
|
||||
* added a new `TwigErrorRenderer` for `html` format, integrated with the `ErrorHandler` component
|
||||
* marked all classes extending twig as `@final`
|
||||
* deprecated to pass `$rootDir` and `$fileLinkFormatter` as 5th and 6th argument respectively to the
|
||||
`DebugCommand::__construct()` method, swap the variables position.
|
||||
* the `LintCommand` lints all the templates stored in all configured Twig paths if none argument is provided
|
||||
* deprecated accepting STDIN implicitly when using the `lint:twig` command, use `lint:twig -` (append a dash) instead to make it explicit.
|
||||
* added `--show-deprecations` option to the `lint:twig` command
|
||||
* added support for Bootstrap4 switches: add the `switch-custom` class to the label attributes of a `CheckboxType`
|
||||
* Marked the `TwigDataCollector` class as `@final`.
|
||||
|
||||
4.3.0
|
||||
-----
|
||||
|
||||
* added the `form_parent()` function that allows to reliably retrieve the parent form in Twig templates
|
||||
* added the `workflow_transition_blockers()` function
|
||||
* deprecated the `$requestStack` and `$requestContext` arguments of the
|
||||
`HttpFoundationExtension`, pass a `Symfony\Component\HttpFoundation\UrlHelper`
|
||||
instance as the only argument instead
|
||||
|
||||
4.2.0
|
||||
-----
|
||||
|
||||
* add bundle name suggestion on wrongly overridden templates paths
|
||||
* added `name` argument in `debug:twig` command and changed `filter` argument as `--filter` option
|
||||
* deprecated the `transchoice` tag and filter, use the `trans` ones instead with a `%count%` parameter
|
||||
|
||||
4.1.0
|
||||
-----
|
||||
|
||||
* add a `workflow_metadata` function
|
||||
|
||||
3.4.0
|
||||
-----
|
||||
|
||||
* added an `only` keyword to `form_theme` tag to disable usage of default themes when rendering a form
|
||||
* deprecated `Symfony\Bridge\Twig\Form\TwigRenderer`
|
||||
* deprecated `DebugCommand::set/getTwigEnvironment`. Pass an instance of
|
||||
`Twig\Environment` as first argument of the constructor instead
|
||||
* deprecated `LintCommand::set/getTwigEnvironment`. Pass an instance of
|
||||
`Twig\Environment` as first argument of the constructor instead
|
||||
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* added a `workflow_has_marked_place` function
|
||||
* added a `workflow_marked_places` function
|
||||
|
||||
3.2.0
|
||||
-----
|
||||
|
||||
* added `AppVariable::getToken()`
|
||||
* Deprecated the possibility to inject the Form `TwigRenderer` into the `FormExtension`.
|
||||
* [BC BREAK] Registering the `FormExtension` without configuring a runtime loader for the `TwigRenderer`
|
||||
doesn't work anymore.
|
||||
|
||||
Before:
|
||||
|
||||
```php
|
||||
use Symfony\Bridge\Twig\Extension\FormExtension;
|
||||
use Symfony\Bridge\Twig\Form\TwigRenderer;
|
||||
use Symfony\Bridge\Twig\Form\TwigRendererEngine;
|
||||
|
||||
// ...
|
||||
$rendererEngine = new TwigRendererEngine(['form_div_layout.html.twig']);
|
||||
$rendererEngine->setEnvironment($twig);
|
||||
$twig->addExtension(new FormExtension(new TwigRenderer($rendererEngine, $csrfTokenManager)));
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```php
|
||||
// ...
|
||||
$rendererEngine = new TwigRendererEngine(['form_div_layout.html.twig'], $twig);
|
||||
// require Twig 1.30+
|
||||
$twig->addRuntimeLoader(new \Twig\RuntimeLoader\FactoryRuntimeLoader([
|
||||
TwigRenderer::class => function () use ($rendererEngine, $csrfTokenManager) {
|
||||
return new TwigRenderer($rendererEngine, $csrfTokenManager);
|
||||
},
|
||||
]));
|
||||
$twig->addExtension(new FormExtension());
|
||||
```
|
||||
* Deprecated the `TwigRendererEngineInterface` interface.
|
||||
* added WorkflowExtension (provides `workflow_can` and `workflow_transitions`)
|
||||
|
||||
2.7.0
|
||||
-----
|
||||
|
||||
* added LogoutUrlExtension (provides `logout_url` and `logout_path`)
|
||||
* added an HttpFoundation extension (provides the `absolute_url` and the `relative_path` functions)
|
||||
* added AssetExtension (provides the `asset` and `asset_version` functions)
|
||||
* Added possibility to extract translation messages from a file or files besides extracting from a directory
|
||||
|
||||
2.5.0
|
||||
-----
|
||||
|
||||
* moved command `twig:lint` from `TwigBundle`
|
||||
|
||||
2.4.0
|
||||
-----
|
||||
|
||||
* added stopwatch tag to time templates with the WebProfilerBundle
|
||||
|
||||
2.3.0
|
||||
-----
|
||||
|
||||
* added helpers form(), form_start() and form_end()
|
||||
* deprecated form_enctype() in favor of form_start()
|
||||
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* added a `controller` function to help generating controller references
|
||||
* added a `render_esi` and a `render_hinclude` function
|
||||
* [BC BREAK] restricted the `render` tag to only accept URIs or ControllerReference instances (the signature changed)
|
||||
* added a `render` function to render a request
|
||||
* The `app` global variable is now injected even when using the twig service directly.
|
||||
* Added an optional parameter to the `path` and `url` function which allows to generate
|
||||
relative paths (e.g. "../parent-file") and scheme-relative URLs (e.g. "//example.com/dir/file").
|
||||
|
||||
2.1.0
|
||||
-----
|
||||
|
||||
* added global variables access in a form theme
|
||||
* added TwigEngine
|
||||
* added TwigExtractor
|
||||
* added a csrf_token function
|
||||
* added a way to specify a default domain for a Twig template (via the
|
||||
'trans_default_domain' tag)
|
600
vendor/symfony/twig-bridge/Command/DebugCommand.php
vendored
Normal file
600
vendor/symfony/twig-bridge/Command/DebugCommand.php
vendored
Normal file
@ -0,0 +1,600 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
|
||||
use Twig\Environment;
|
||||
use Twig\Loader\ChainLoader;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
|
||||
/**
|
||||
* Lists twig functions, filters, globals and tests present in the current project.
|
||||
*
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
*/
|
||||
class DebugCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'debug:twig';
|
||||
protected static $defaultDescription = 'Show a list of twig functions, filters, globals and tests';
|
||||
|
||||
private $twig;
|
||||
private $projectDir;
|
||||
private $bundlesMetadata;
|
||||
private $twigDefaultPath;
|
||||
private $filesystemLoaders;
|
||||
private $fileLinkFormatter;
|
||||
|
||||
public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = [], string $twigDefaultPath = null, FileLinkFormatter $fileLinkFormatter = null)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->twig = $twig;
|
||||
$this->projectDir = $projectDir;
|
||||
$this->bundlesMetadata = $bundlesMetadata;
|
||||
$this->twigDefaultPath = $twigDefaultPath;
|
||||
$this->fileLinkFormatter = $fileLinkFormatter;
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setDefinition([
|
||||
new InputArgument('name', InputArgument::OPTIONAL, 'The template name'),
|
||||
new InputOption('filter', null, InputOption::VALUE_REQUIRED, 'Show details for all entries matching this filter'),
|
||||
new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'),
|
||||
])
|
||||
->setDescription(self::$defaultDescription)
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command outputs a list of twig functions,
|
||||
filters, globals and tests.
|
||||
|
||||
<info>php %command.full_name%</info>
|
||||
|
||||
The command lists all functions, filters, etc.
|
||||
|
||||
<info>php %command.full_name% @Twig/Exception/error.html.twig</info>
|
||||
|
||||
The command lists all paths that match the given template name.
|
||||
|
||||
<info>php %command.full_name% --filter=date</info>
|
||||
|
||||
The command lists everything that contains the word date.
|
||||
|
||||
<info>php %command.full_name% --format=json</info>
|
||||
|
||||
The command lists everything in a machine readable json format.
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$name = $input->getArgument('name');
|
||||
$filter = $input->getOption('filter');
|
||||
|
||||
if (null !== $name && [] === $this->getFilesystemLoaders()) {
|
||||
throw new InvalidArgumentException(sprintf('Argument "name" not supported, it requires the Twig loader "%s".', FilesystemLoader::class));
|
||||
}
|
||||
|
||||
switch ($input->getOption('format')) {
|
||||
case 'text':
|
||||
$name ? $this->displayPathsText($io, $name) : $this->displayGeneralText($io, $filter);
|
||||
break;
|
||||
case 'json':
|
||||
$name ? $this->displayPathsJson($io, $name) : $this->displayGeneralJson($io, $filter);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestArgumentValuesFor('name')) {
|
||||
$suggestions->suggestValues(array_keys($this->getLoaderPaths()));
|
||||
}
|
||||
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$suggestions->suggestValues(['text', 'json']);
|
||||
}
|
||||
}
|
||||
|
||||
private function displayPathsText(SymfonyStyle $io, string $name)
|
||||
{
|
||||
$file = new \ArrayIterator($this->findTemplateFiles($name));
|
||||
$paths = $this->getLoaderPaths($name);
|
||||
|
||||
$io->section('Matched File');
|
||||
if ($file->valid()) {
|
||||
if ($fileLink = $this->getFileLink($file->key())) {
|
||||
$io->block($file->current(), 'OK', sprintf('fg=black;bg=green;href=%s', $fileLink), ' ', true);
|
||||
} else {
|
||||
$io->success($file->current());
|
||||
}
|
||||
$file->next();
|
||||
|
||||
if ($file->valid()) {
|
||||
$io->section('Overridden Files');
|
||||
do {
|
||||
if ($fileLink = $this->getFileLink($file->key())) {
|
||||
$io->text(sprintf('* <href=%s>%s</>', $fileLink, $file->current()));
|
||||
} else {
|
||||
$io->text(sprintf('* %s', $file->current()));
|
||||
}
|
||||
$file->next();
|
||||
} while ($file->valid());
|
||||
}
|
||||
} else {
|
||||
$alternatives = [];
|
||||
|
||||
if ($paths) {
|
||||
$shortnames = [];
|
||||
$dirs = [];
|
||||
foreach (current($paths) as $path) {
|
||||
$dirs[] = $this->isAbsolutePath($path) ? $path : $this->projectDir.'/'.$path;
|
||||
}
|
||||
foreach (Finder::create()->files()->followLinks()->in($dirs) as $file) {
|
||||
$shortnames[] = str_replace('\\', '/', $file->getRelativePathname());
|
||||
}
|
||||
|
||||
[$namespace, $shortname] = $this->parseTemplateName($name);
|
||||
$alternatives = $this->findAlternatives($shortname, $shortnames);
|
||||
if (FilesystemLoader::MAIN_NAMESPACE !== $namespace) {
|
||||
$alternatives = array_map(function ($shortname) use ($namespace) {
|
||||
return '@'.$namespace.'/'.$shortname;
|
||||
}, $alternatives);
|
||||
}
|
||||
}
|
||||
|
||||
$this->error($io, sprintf('Template name "%s" not found', $name), $alternatives);
|
||||
}
|
||||
|
||||
$io->section('Configured Paths');
|
||||
if ($paths) {
|
||||
$io->table(['Namespace', 'Paths'], $this->buildTableRows($paths));
|
||||
} else {
|
||||
$alternatives = [];
|
||||
$namespace = $this->parseTemplateName($name)[0];
|
||||
|
||||
if (FilesystemLoader::MAIN_NAMESPACE === $namespace) {
|
||||
$message = 'No template paths configured for your application';
|
||||
} else {
|
||||
$message = sprintf('No template paths configured for "@%s" namespace', $namespace);
|
||||
foreach ($this->getFilesystemLoaders() as $loader) {
|
||||
$namespaces = $loader->getNamespaces();
|
||||
foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) {
|
||||
$alternatives[] = '@'.$namespace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->error($io, $message, $alternatives);
|
||||
|
||||
if (!$alternatives && $paths = $this->getLoaderPaths()) {
|
||||
$io->table(['Namespace', 'Paths'], $this->buildTableRows($paths));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function displayPathsJson(SymfonyStyle $io, string $name)
|
||||
{
|
||||
$files = $this->findTemplateFiles($name);
|
||||
$paths = $this->getLoaderPaths($name);
|
||||
|
||||
if ($files) {
|
||||
$data['matched_file'] = array_shift($files);
|
||||
if ($files) {
|
||||
$data['overridden_files'] = $files;
|
||||
}
|
||||
} else {
|
||||
$data['matched_file'] = sprintf('Template name "%s" not found', $name);
|
||||
}
|
||||
$data['loader_paths'] = $paths;
|
||||
|
||||
$io->writeln(json_encode($data));
|
||||
}
|
||||
|
||||
private function displayGeneralText(SymfonyStyle $io, string $filter = null)
|
||||
{
|
||||
$decorated = $io->isDecorated();
|
||||
$types = ['functions', 'filters', 'tests', 'globals'];
|
||||
foreach ($types as $index => $type) {
|
||||
$items = [];
|
||||
foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
|
||||
if (!$filter || str_contains($name, $filter)) {
|
||||
$items[$name] = $name.$this->getPrettyMetadata($type, $entity, $decorated);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$items) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$io->section(ucfirst($type));
|
||||
|
||||
ksort($items);
|
||||
$io->listing($items);
|
||||
}
|
||||
|
||||
if (!$filter && $paths = $this->getLoaderPaths()) {
|
||||
$io->section('Loader Paths');
|
||||
$io->table(['Namespace', 'Paths'], $this->buildTableRows($paths));
|
||||
}
|
||||
|
||||
if ($wrongBundles = $this->findWrongBundleOverrides()) {
|
||||
foreach ($this->buildWarningMessages($wrongBundles) as $message) {
|
||||
$io->warning($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function displayGeneralJson(SymfonyStyle $io, ?string $filter)
|
||||
{
|
||||
$decorated = $io->isDecorated();
|
||||
$types = ['functions', 'filters', 'tests', 'globals'];
|
||||
$data = [];
|
||||
foreach ($types as $type) {
|
||||
foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) {
|
||||
if (!$filter || str_contains($name, $filter)) {
|
||||
$data[$type][$name] = $this->getMetadata($type, $entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($data['tests'])) {
|
||||
$data['tests'] = array_keys($data['tests']);
|
||||
}
|
||||
|
||||
if (!$filter && $paths = $this->getLoaderPaths($filter)) {
|
||||
$data['loader_paths'] = $paths;
|
||||
}
|
||||
|
||||
if ($wrongBundles = $this->findWrongBundleOverrides()) {
|
||||
$data['warnings'] = $this->buildWarningMessages($wrongBundles);
|
||||
}
|
||||
|
||||
$data = json_encode($data, \JSON_PRETTY_PRINT);
|
||||
$io->writeln($decorated ? OutputFormatter::escape($data) : $data);
|
||||
}
|
||||
|
||||
private function getLoaderPaths(string $name = null): array
|
||||
{
|
||||
$loaderPaths = [];
|
||||
foreach ($this->getFilesystemLoaders() as $loader) {
|
||||
$namespaces = $loader->getNamespaces();
|
||||
if (null !== $name) {
|
||||
$namespace = $this->parseTemplateName($name)[0];
|
||||
$namespaces = array_intersect([$namespace], $namespaces);
|
||||
}
|
||||
|
||||
foreach ($namespaces as $namespace) {
|
||||
$paths = array_map([$this, 'getRelativePath'], $loader->getPaths($namespace));
|
||||
|
||||
if (FilesystemLoader::MAIN_NAMESPACE === $namespace) {
|
||||
$namespace = '(None)';
|
||||
} else {
|
||||
$namespace = '@'.$namespace;
|
||||
}
|
||||
|
||||
$loaderPaths[$namespace] = array_merge($loaderPaths[$namespace] ?? [], $paths);
|
||||
}
|
||||
}
|
||||
|
||||
return $loaderPaths;
|
||||
}
|
||||
|
||||
private function getMetadata(string $type, $entity)
|
||||
{
|
||||
if ('globals' === $type) {
|
||||
return $entity;
|
||||
}
|
||||
if ('tests' === $type) {
|
||||
return null;
|
||||
}
|
||||
if ('functions' === $type || 'filters' === $type) {
|
||||
$cb = $entity->getCallable();
|
||||
if (null === $cb) {
|
||||
return null;
|
||||
}
|
||||
if (\is_array($cb)) {
|
||||
if (!method_exists($cb[0], $cb[1])) {
|
||||
return null;
|
||||
}
|
||||
$refl = new \ReflectionMethod($cb[0], $cb[1]);
|
||||
} elseif (\is_object($cb) && method_exists($cb, '__invoke')) {
|
||||
$refl = new \ReflectionMethod($cb, '__invoke');
|
||||
} elseif (\function_exists($cb)) {
|
||||
$refl = new \ReflectionFunction($cb);
|
||||
} elseif (\is_string($cb) && preg_match('{^(.+)::(.+)$}', $cb, $m) && method_exists($m[1], $m[2])) {
|
||||
$refl = new \ReflectionMethod($m[1], $m[2]);
|
||||
} else {
|
||||
throw new \UnexpectedValueException('Unsupported callback type.');
|
||||
}
|
||||
|
||||
$args = $refl->getParameters();
|
||||
|
||||
// filter out context/environment args
|
||||
if ($entity->needsEnvironment()) {
|
||||
array_shift($args);
|
||||
}
|
||||
if ($entity->needsContext()) {
|
||||
array_shift($args);
|
||||
}
|
||||
|
||||
if ('filters' === $type) {
|
||||
// remove the value the filter is applied on
|
||||
array_shift($args);
|
||||
}
|
||||
|
||||
// format args
|
||||
$args = array_map(function (\ReflectionParameter $param) {
|
||||
if ($param->isDefaultValueAvailable()) {
|
||||
return $param->getName().' = '.json_encode($param->getDefaultValue());
|
||||
}
|
||||
|
||||
return $param->getName();
|
||||
}, $args);
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getPrettyMetadata(string $type, $entity, bool $decorated): ?string
|
||||
{
|
||||
if ('tests' === $type) {
|
||||
return '';
|
||||
}
|
||||
|
||||
try {
|
||||
$meta = $this->getMetadata($type, $entity);
|
||||
if (null === $meta) {
|
||||
return '(unknown?)';
|
||||
}
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
return sprintf(' <error>%s</error>', $decorated ? OutputFormatter::escape($e->getMessage()) : $e->getMessage());
|
||||
}
|
||||
|
||||
if ('globals' === $type) {
|
||||
if (\is_object($meta)) {
|
||||
return ' = object('.\get_class($meta).')';
|
||||
}
|
||||
|
||||
$description = substr(@json_encode($meta), 0, 50);
|
||||
|
||||
return sprintf(' = %s', $decorated ? OutputFormatter::escape($description) : $description);
|
||||
}
|
||||
|
||||
if ('functions' === $type) {
|
||||
return '('.implode(', ', $meta).')';
|
||||
}
|
||||
|
||||
if ('filters' === $type) {
|
||||
return $meta ? '('.implode(', ', $meta).')' : '';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function findWrongBundleOverrides(): array
|
||||
{
|
||||
$alternatives = [];
|
||||
$bundleNames = [];
|
||||
|
||||
if ($this->twigDefaultPath && $this->projectDir) {
|
||||
$folders = glob($this->twigDefaultPath.'/bundles/*', \GLOB_ONLYDIR);
|
||||
$relativePath = ltrim(substr($this->twigDefaultPath.'/bundles/', \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
|
||||
$bundleNames = array_reduce($folders, function ($carry, $absolutePath) use ($relativePath) {
|
||||
if (str_starts_with($absolutePath, $this->projectDir)) {
|
||||
$name = basename($absolutePath);
|
||||
$path = ltrim($relativePath.$name, \DIRECTORY_SEPARATOR);
|
||||
$carry[$name] = $path;
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}, $bundleNames);
|
||||
}
|
||||
|
||||
if ($notFoundBundles = array_diff_key($bundleNames, $this->bundlesMetadata)) {
|
||||
$alternatives = [];
|
||||
foreach ($notFoundBundles as $notFoundBundle => $path) {
|
||||
$alternatives[$path] = $this->findAlternatives($notFoundBundle, array_keys($this->bundlesMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
return $alternatives;
|
||||
}
|
||||
|
||||
private function buildWarningMessages(array $wrongBundles): array
|
||||
{
|
||||
$messages = [];
|
||||
foreach ($wrongBundles as $path => $alternatives) {
|
||||
$message = sprintf('Path "%s" not matching any bundle found', $path);
|
||||
if ($alternatives) {
|
||||
if (1 === \count($alternatives)) {
|
||||
$message .= sprintf(", did you mean \"%s\"?\n", $alternatives[0]);
|
||||
} else {
|
||||
$message .= ", did you mean one of these:\n";
|
||||
foreach ($alternatives as $bundle) {
|
||||
$message .= sprintf(" - %s\n", $bundle);
|
||||
}
|
||||
}
|
||||
}
|
||||
$messages[] = trim($message);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
private function error(SymfonyStyle $io, string $message, array $alternatives = []): void
|
||||
{
|
||||
if ($alternatives) {
|
||||
if (1 === \count($alternatives)) {
|
||||
$message .= "\n\nDid you mean this?\n ";
|
||||
} else {
|
||||
$message .= "\n\nDid you mean one of these?\n ";
|
||||
}
|
||||
$message .= implode("\n ", $alternatives);
|
||||
}
|
||||
|
||||
$io->block($message, null, 'fg=white;bg=red', ' ', true);
|
||||
}
|
||||
|
||||
private function findTemplateFiles(string $name): array
|
||||
{
|
||||
[$namespace, $shortname] = $this->parseTemplateName($name);
|
||||
|
||||
$files = [];
|
||||
foreach ($this->getFilesystemLoaders() as $loader) {
|
||||
foreach ($loader->getPaths($namespace) as $path) {
|
||||
if (!$this->isAbsolutePath($path)) {
|
||||
$path = $this->projectDir.'/'.$path;
|
||||
}
|
||||
$filename = $path.'/'.$shortname;
|
||||
|
||||
if (is_file($filename)) {
|
||||
if (false !== $realpath = realpath($filename)) {
|
||||
$files[$realpath] = $this->getRelativePath($realpath);
|
||||
} else {
|
||||
$files[$filename] = $this->getRelativePath($filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
private function parseTemplateName(string $name, string $default = FilesystemLoader::MAIN_NAMESPACE): array
|
||||
{
|
||||
if (isset($name[0]) && '@' === $name[0]) {
|
||||
if (false === ($pos = strpos($name, '/')) || $pos === \strlen($name) - 1) {
|
||||
throw new InvalidArgumentException(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
|
||||
}
|
||||
|
||||
$namespace = substr($name, 1, $pos - 1);
|
||||
$shortname = substr($name, $pos + 1);
|
||||
|
||||
return [$namespace, $shortname];
|
||||
}
|
||||
|
||||
return [$default, $name];
|
||||
}
|
||||
|
||||
private function buildTableRows(array $loaderPaths): array
|
||||
{
|
||||
$rows = [];
|
||||
$firstNamespace = true;
|
||||
$prevHasSeparator = false;
|
||||
|
||||
foreach ($loaderPaths as $namespace => $paths) {
|
||||
if (!$firstNamespace && !$prevHasSeparator && \count($paths) > 1) {
|
||||
$rows[] = ['', ''];
|
||||
}
|
||||
$firstNamespace = false;
|
||||
foreach ($paths as $path) {
|
||||
$rows[] = [$namespace, $path.\DIRECTORY_SEPARATOR];
|
||||
$namespace = '';
|
||||
}
|
||||
if (\count($paths) > 1) {
|
||||
$rows[] = ['', ''];
|
||||
$prevHasSeparator = true;
|
||||
} else {
|
||||
$prevHasSeparator = false;
|
||||
}
|
||||
}
|
||||
if ($prevHasSeparator) {
|
||||
array_pop($rows);
|
||||
}
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
private function findAlternatives(string $name, array $collection): array
|
||||
{
|
||||
$alternatives = [];
|
||||
foreach ($collection as $item) {
|
||||
$lev = levenshtein($name, $item);
|
||||
if ($lev <= \strlen($name) / 3 || str_contains($item, $name)) {
|
||||
$alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
|
||||
}
|
||||
}
|
||||
|
||||
$threshold = 1e3;
|
||||
$alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
|
||||
ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE);
|
||||
|
||||
return array_keys($alternatives);
|
||||
}
|
||||
|
||||
private function getRelativePath(string $path): string
|
||||
{
|
||||
if (null !== $this->projectDir && str_starts_with($path, $this->projectDir)) {
|
||||
return ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
private function isAbsolutePath(string $file): bool
|
||||
{
|
||||
return strspn($file, '/\\', 0, 1) || (\strlen($file) > 3 && ctype_alpha($file[0]) && ':' === $file[1] && strspn($file, '/\\', 2, 1)) || null !== parse_url($file, \PHP_URL_SCHEME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FilesystemLoader[]
|
||||
*/
|
||||
private function getFilesystemLoaders(): array
|
||||
{
|
||||
if (null !== $this->filesystemLoaders) {
|
||||
return $this->filesystemLoaders;
|
||||
}
|
||||
$this->filesystemLoaders = [];
|
||||
|
||||
$loader = $this->twig->getLoader();
|
||||
if ($loader instanceof FilesystemLoader) {
|
||||
$this->filesystemLoaders[] = $loader;
|
||||
} elseif ($loader instanceof ChainLoader) {
|
||||
foreach ($loader->getLoaders() as $l) {
|
||||
if ($l instanceof FilesystemLoader) {
|
||||
$this->filesystemLoaders[] = $l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->filesystemLoaders;
|
||||
}
|
||||
|
||||
private function getFileLink(string $absolutePath): string
|
||||
{
|
||||
if (null === $this->fileLinkFormatter) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return (string) $this->fileLinkFormatter->format($absolutePath, 1);
|
||||
}
|
||||
}
|
296
vendor/symfony/twig-bridge/Command/LintCommand.php
vendored
Normal file
296
vendor/symfony/twig-bridge/Command/LintCommand.php
vendored
Normal file
@ -0,0 +1,296 @@
|
||||
<?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\Command;
|
||||
|
||||
use Symfony\Component\Console\CI\GithubActionReporter;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Completion\CompletionInput;
|
||||
use Symfony\Component\Console\Completion\CompletionSuggestions;
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\Error;
|
||||
use Twig\Loader\ArrayLoader;
|
||||
use Twig\Loader\FilesystemLoader;
|
||||
use Twig\Source;
|
||||
|
||||
/**
|
||||
* Command that will validate your template syntax and output encountered errors.
|
||||
*
|
||||
* @author Marc Weistroff <marc.weistroff@sensiolabs.com>
|
||||
* @author Jérôme Tamarelle <jerome@tamarelle.net>
|
||||
*/
|
||||
class LintCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'lint:twig';
|
||||
protected static $defaultDescription = 'Lint a Twig template and outputs encountered errors';
|
||||
|
||||
private $twig;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $format;
|
||||
|
||||
public function __construct(Environment $twig)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->twig = $twig;
|
||||
}
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setDescription(self::$defaultDescription)
|
||||
->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format')
|
||||
->addOption('show-deprecations', null, InputOption::VALUE_NONE, 'Show deprecations as errors')
|
||||
->addArgument('filename', InputArgument::IS_ARRAY, 'A file, a directory or "-" for reading from STDIN')
|
||||
->setHelp(<<<'EOF'
|
||||
The <info>%command.name%</info> command lints a template and outputs to STDOUT
|
||||
the first encountered syntax error.
|
||||
|
||||
You can validate the syntax of contents passed from STDIN:
|
||||
|
||||
<info>cat filename | php %command.full_name% -</info>
|
||||
|
||||
Or the syntax of a file:
|
||||
|
||||
<info>php %command.full_name% filename</info>
|
||||
|
||||
Or of a whole directory:
|
||||
|
||||
<info>php %command.full_name% dirname</info>
|
||||
<info>php %command.full_name% dirname --format=json</info>
|
||||
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
$filenames = $input->getArgument('filename');
|
||||
$showDeprecations = $input->getOption('show-deprecations');
|
||||
$this->format = $input->getOption('format');
|
||||
|
||||
if (null === $this->format) {
|
||||
$this->format = GithubActionReporter::isGithubActionEnvironment() ? 'github' : 'txt';
|
||||
}
|
||||
|
||||
if (['-'] === $filenames) {
|
||||
return $this->display($input, $output, $io, [$this->validate(file_get_contents('php://stdin'), uniqid('sf_', true))]);
|
||||
}
|
||||
|
||||
if (!$filenames) {
|
||||
$loader = $this->twig->getLoader();
|
||||
if ($loader instanceof FilesystemLoader) {
|
||||
$paths = [];
|
||||
foreach ($loader->getNamespaces() as $namespace) {
|
||||
$paths[] = $loader->getPaths($namespace);
|
||||
}
|
||||
$filenames = array_merge(...$paths);
|
||||
}
|
||||
|
||||
if (!$filenames) {
|
||||
throw new RuntimeException('Please provide a filename or pipe template content to STDIN.');
|
||||
}
|
||||
}
|
||||
|
||||
if ($showDeprecations) {
|
||||
$prevErrorHandler = set_error_handler(static function ($level, $message, $file, $line) use (&$prevErrorHandler) {
|
||||
if (\E_USER_DEPRECATED === $level) {
|
||||
$templateLine = 0;
|
||||
if (preg_match('/ at line (\d+)[ .]/', $message, $matches)) {
|
||||
$templateLine = $matches[1];
|
||||
}
|
||||
|
||||
throw new Error($message, $templateLine);
|
||||
}
|
||||
|
||||
return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false;
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
$filesInfo = $this->getFilesInfo($filenames);
|
||||
} finally {
|
||||
if ($showDeprecations) {
|
||||
restore_error_handler();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->display($input, $output, $io, $filesInfo);
|
||||
}
|
||||
|
||||
private function getFilesInfo(array $filenames): array
|
||||
{
|
||||
$filesInfo = [];
|
||||
foreach ($filenames as $filename) {
|
||||
foreach ($this->findFiles($filename) as $file) {
|
||||
$filesInfo[] = $this->validate(file_get_contents($file), $file);
|
||||
}
|
||||
}
|
||||
|
||||
return $filesInfo;
|
||||
}
|
||||
|
||||
protected function findFiles(string $filename)
|
||||
{
|
||||
if (is_file($filename)) {
|
||||
return [$filename];
|
||||
} elseif (is_dir($filename)) {
|
||||
return Finder::create()->files()->in($filename)->name('*.twig');
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('File or directory "%s" is not readable.', $filename));
|
||||
}
|
||||
|
||||
private function validate(string $template, string $file): array
|
||||
{
|
||||
$realLoader = $this->twig->getLoader();
|
||||
try {
|
||||
$temporaryLoader = new ArrayLoader([$file => $template]);
|
||||
$this->twig->setLoader($temporaryLoader);
|
||||
$nodeTree = $this->twig->parse($this->twig->tokenize(new Source($template, $file)));
|
||||
$this->twig->compile($nodeTree);
|
||||
$this->twig->setLoader($realLoader);
|
||||
} catch (Error $e) {
|
||||
$this->twig->setLoader($realLoader);
|
||||
|
||||
return ['template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e];
|
||||
}
|
||||
|
||||
return ['template' => $template, 'file' => $file, 'valid' => true];
|
||||
}
|
||||
|
||||
private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, array $files)
|
||||
{
|
||||
switch ($this->format) {
|
||||
case 'txt':
|
||||
return $this->displayTxt($output, $io, $files);
|
||||
case 'json':
|
||||
return $this->displayJson($output, $files);
|
||||
case 'github':
|
||||
return $this->displayTxt($output, $io, $files, true);
|
||||
default:
|
||||
throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format')));
|
||||
}
|
||||
}
|
||||
|
||||
private function displayTxt(OutputInterface $output, SymfonyStyle $io, array $filesInfo, bool $errorAsGithubAnnotations = false)
|
||||
{
|
||||
$errors = 0;
|
||||
$githubReporter = $errorAsGithubAnnotations ? new GithubActionReporter($output) : null;
|
||||
|
||||
foreach ($filesInfo as $info) {
|
||||
if ($info['valid'] && $output->isVerbose()) {
|
||||
$io->comment('<info>OK</info>'.($info['file'] ? sprintf(' in %s', $info['file']) : ''));
|
||||
} elseif (!$info['valid']) {
|
||||
++$errors;
|
||||
$this->renderException($io, $info['template'], $info['exception'], $info['file'], $githubReporter);
|
||||
}
|
||||
}
|
||||
|
||||
if (0 === $errors) {
|
||||
$io->success(sprintf('All %d Twig files contain valid syntax.', \count($filesInfo)));
|
||||
} else {
|
||||
$io->warning(sprintf('%d Twig files have valid syntax and %d contain errors.', \count($filesInfo) - $errors, $errors));
|
||||
}
|
||||
|
||||
return min($errors, 1);
|
||||
}
|
||||
|
||||
private function displayJson(OutputInterface $output, array $filesInfo)
|
||||
{
|
||||
$errors = 0;
|
||||
|
||||
array_walk($filesInfo, function (&$v) use (&$errors) {
|
||||
$v['file'] = (string) $v['file'];
|
||||
unset($v['template']);
|
||||
if (!$v['valid']) {
|
||||
$v['message'] = $v['exception']->getMessage();
|
||||
unset($v['exception']);
|
||||
++$errors;
|
||||
}
|
||||
});
|
||||
|
||||
$output->writeln(json_encode($filesInfo, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
|
||||
|
||||
return min($errors, 1);
|
||||
}
|
||||
|
||||
private function renderException(SymfonyStyle $output, string $template, Error $exception, string $file = null, GithubActionReporter $githubReporter = null)
|
||||
{
|
||||
$line = $exception->getTemplateLine();
|
||||
|
||||
if ($githubReporter) {
|
||||
$githubReporter->error($exception->getRawMessage(), $file, $line <= 0 ? null : $line);
|
||||
}
|
||||
|
||||
if ($file) {
|
||||
$output->text(sprintf('<error> ERROR </error> in %s (line %s)', $file, $line));
|
||||
} else {
|
||||
$output->text(sprintf('<error> ERROR </error> (line %s)', $line));
|
||||
}
|
||||
|
||||
// If the line is not known (this might happen for deprecations if we fail at detecting the line for instance),
|
||||
// we render the message without context, to ensure the message is displayed.
|
||||
if ($line <= 0) {
|
||||
$output->text(sprintf('<error> >> %s</error> ', $exception->getRawMessage()));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->getContext($template, $line) as $lineNumber => $code) {
|
||||
$output->text(sprintf(
|
||||
'%s %-6s %s',
|
||||
$lineNumber === $line ? '<error> >> </error>' : ' ',
|
||||
$lineNumber,
|
||||
$code
|
||||
));
|
||||
if ($lineNumber === $line) {
|
||||
$output->text(sprintf('<error> >> %s</error> ', $exception->getRawMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getContext(string $template, int $line, int $context = 3)
|
||||
{
|
||||
$lines = explode("\n", $template);
|
||||
|
||||
$position = max(0, $line - $context);
|
||||
$max = min(\count($lines), $line - 1 + $context);
|
||||
|
||||
$result = [];
|
||||
while ($position < $max) {
|
||||
$result[$position + 1] = $lines[$position];
|
||||
++$position;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void
|
||||
{
|
||||
if ($input->mustSuggestOptionValuesFor('format')) {
|
||||
$suggestions->suggestValues(['txt', 'json', 'github']);
|
||||
}
|
||||
}
|
||||
}
|
203
vendor/symfony/twig-bridge/DataCollector/TwigDataCollector.php
vendored
Normal file
203
vendor/symfony/twig-bridge/DataCollector/TwigDataCollector.php
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
<?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\DataCollector;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
|
||||
use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\LoaderError;
|
||||
use Twig\Markup;
|
||||
use Twig\Profiler\Dumper\HtmlDumper;
|
||||
use Twig\Profiler\Profile;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
class TwigDataCollector extends DataCollector implements LateDataCollectorInterface
|
||||
{
|
||||
private $profile;
|
||||
private $twig;
|
||||
private $computed;
|
||||
|
||||
public function __construct(Profile $profile, Environment $twig = null)
|
||||
{
|
||||
$this->profile = $profile;
|
||||
$this->twig = $twig;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function collect(Request $request, Response $response, \Throwable $exception = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->profile->reset();
|
||||
$this->computed = null;
|
||||
$this->data = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function lateCollect()
|
||||
{
|
||||
$this->data['profile'] = serialize($this->profile);
|
||||
$this->data['template_paths'] = [];
|
||||
|
||||
if (null === $this->twig) {
|
||||
return;
|
||||
}
|
||||
|
||||
$templateFinder = function (Profile $profile) use (&$templateFinder) {
|
||||
if ($profile->isTemplate()) {
|
||||
try {
|
||||
$template = $this->twig->load($name = $profile->getName());
|
||||
} catch (LoaderError $e) {
|
||||
$template = null;
|
||||
}
|
||||
|
||||
if (null !== $template && '' !== $path = $template->getSourceContext()->getPath()) {
|
||||
$this->data['template_paths'][$name] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($profile as $p) {
|
||||
$templateFinder($p);
|
||||
}
|
||||
};
|
||||
$templateFinder($this->profile);
|
||||
}
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->getProfile()->getDuration() * 1000;
|
||||
}
|
||||
|
||||
public function getTemplateCount()
|
||||
{
|
||||
return $this->getComputedData('template_count');
|
||||
}
|
||||
|
||||
public function getTemplatePaths()
|
||||
{
|
||||
return $this->data['template_paths'];
|
||||
}
|
||||
|
||||
public function getTemplates()
|
||||
{
|
||||
return $this->getComputedData('templates');
|
||||
}
|
||||
|
||||
public function getBlockCount()
|
||||
{
|
||||
return $this->getComputedData('block_count');
|
||||
}
|
||||
|
||||
public function getMacroCount()
|
||||
{
|
||||
return $this->getComputedData('macro_count');
|
||||
}
|
||||
|
||||
public function getHtmlCallGraph()
|
||||
{
|
||||
$dumper = new HtmlDumper();
|
||||
$dump = $dumper->dump($this->getProfile());
|
||||
|
||||
// needed to remove the hardcoded CSS styles
|
||||
$dump = str_replace([
|
||||
'<span style="background-color: #ffd">',
|
||||
'<span style="color: #d44">',
|
||||
'<span style="background-color: #dfd">',
|
||||
'<span style="background-color: #ddf">',
|
||||
], [
|
||||
'<span class="status-warning">',
|
||||
'<span class="status-error">',
|
||||
'<span class="status-success">',
|
||||
'<span class="status-info">',
|
||||
], $dump);
|
||||
|
||||
return new Markup($dump, 'UTF-8');
|
||||
}
|
||||
|
||||
public function getProfile()
|
||||
{
|
||||
if (null === $this->profile) {
|
||||
$this->profile = unserialize($this->data['profile'], ['allowed_classes' => ['Twig_Profiler_Profile', 'Twig\Profiler\Profile']]);
|
||||
}
|
||||
|
||||
return $this->profile;
|
||||
}
|
||||
|
||||
private function getComputedData(string $index)
|
||||
{
|
||||
if (null === $this->computed) {
|
||||
$this->computed = $this->computeData($this->getProfile());
|
||||
}
|
||||
|
||||
return $this->computed[$index];
|
||||
}
|
||||
|
||||
private function computeData(Profile $profile)
|
||||
{
|
||||
$data = [
|
||||
'template_count' => 0,
|
||||
'block_count' => 0,
|
||||
'macro_count' => 0,
|
||||
];
|
||||
|
||||
$templates = [];
|
||||
foreach ($profile as $p) {
|
||||
$d = $this->computeData($p);
|
||||
|
||||
$data['template_count'] += ($p->isTemplate() ? 1 : 0) + $d['template_count'];
|
||||
$data['block_count'] += ($p->isBlock() ? 1 : 0) + $d['block_count'];
|
||||
$data['macro_count'] += ($p->isMacro() ? 1 : 0) + $d['macro_count'];
|
||||
|
||||
if ($p->isTemplate()) {
|
||||
if (!isset($templates[$p->getTemplate()])) {
|
||||
$templates[$p->getTemplate()] = 1;
|
||||
} else {
|
||||
++$templates[$p->getTemplate()];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($d['templates'] as $template => $count) {
|
||||
if (!isset($templates[$template])) {
|
||||
$templates[$template] = $count;
|
||||
} else {
|
||||
$templates[$template] += $count;
|
||||
}
|
||||
}
|
||||
}
|
||||
$data['templates'] = $templates;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'twig';
|
||||
}
|
||||
}
|
90
vendor/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php
vendored
Normal file
90
vendor/symfony/twig-bridge/ErrorRenderer/TwigErrorRenderer.php
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
<?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\ErrorRenderer;
|
||||
|
||||
use Symfony\Component\ErrorHandler\ErrorRenderer\ErrorRendererInterface;
|
||||
use Symfony\Component\ErrorHandler\ErrorRenderer\HtmlErrorRenderer;
|
||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Twig\Environment;
|
||||
|
||||
/**
|
||||
* Provides the ability to render custom Twig-based HTML error pages
|
||||
* in non-debug mode, otherwise falls back to HtmlErrorRenderer.
|
||||
*
|
||||
* @author Yonel Ceruto <yonelceruto@gmail.com>
|
||||
*/
|
||||
class TwigErrorRenderer implements ErrorRendererInterface
|
||||
{
|
||||
private $twig;
|
||||
private $fallbackErrorRenderer;
|
||||
private $debug;
|
||||
|
||||
/**
|
||||
* @param bool|callable $debug The debugging mode as a boolean or a callable that should return it
|
||||
*/
|
||||
public function __construct(Environment $twig, HtmlErrorRenderer $fallbackErrorRenderer = null, $debug = false)
|
||||
{
|
||||
if (!\is_bool($debug) && !\is_callable($debug)) {
|
||||
throw new \TypeError(sprintf('Argument 3 passed to "%s()" must be a boolean or a callable, "%s" given.', __METHOD__, get_debug_type($debug)));
|
||||
}
|
||||
|
||||
$this->twig = $twig;
|
||||
$this->fallbackErrorRenderer = $fallbackErrorRenderer ?? new HtmlErrorRenderer();
|
||||
$this->debug = $debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render(\Throwable $exception): FlattenException
|
||||
{
|
||||
$exception = $this->fallbackErrorRenderer->render($exception);
|
||||
$debug = \is_bool($this->debug) ? $this->debug : ($this->debug)($exception);
|
||||
|
||||
if ($debug || !$template = $this->findTemplate($exception->getStatusCode())) {
|
||||
return $exception;
|
||||
}
|
||||
|
||||
return $exception->setAsString($this->twig->render($template, [
|
||||
'exception' => $exception,
|
||||
'status_code' => $exception->getStatusCode(),
|
||||
'status_text' => $exception->getStatusText(),
|
||||
]));
|
||||
}
|
||||
|
||||
public static function isDebug(RequestStack $requestStack, bool $debug): \Closure
|
||||
{
|
||||
return static function () use ($requestStack, $debug): bool {
|
||||
if (!$request = $requestStack->getCurrentRequest()) {
|
||||
return $debug;
|
||||
}
|
||||
|
||||
return $debug && $request->attributes->getBoolean('showException', true);
|
||||
};
|
||||
}
|
||||
|
||||
private function findTemplate(int $statusCode): ?string
|
||||
{
|
||||
$template = sprintf('@Twig/Exception/error%s.html.twig', $statusCode);
|
||||
if ($this->twig->getLoader()->exists($template)) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
$template = '@Twig/Exception/error.html.twig';
|
||||
if ($this->twig->getLoader()->exists($template)) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
61
vendor/symfony/twig-bridge/Extension/AssetExtension.php
vendored
Normal file
61
vendor/symfony/twig-bridge/Extension/AssetExtension.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Asset\Packages;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Twig extension for the Symfony Asset component.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class AssetExtension extends AbstractExtension
|
||||
{
|
||||
private $packages;
|
||||
|
||||
public function __construct(Packages $packages)
|
||||
{
|
||||
$this->packages = $packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('asset', [$this, 'getAssetUrl']),
|
||||
new TwigFunction('asset_version', [$this, 'getAssetVersion']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the public url/path of an asset.
|
||||
*
|
||||
* If the package used to generate the path is an instance of
|
||||
* UrlPackage, you will always get a URL and not a path.
|
||||
*/
|
||||
public function getAssetUrl(string $path, string $packageName = null): string
|
||||
{
|
||||
return $this->packages->getUrl($path, $packageName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of an asset.
|
||||
*/
|
||||
public function getAssetVersion(string $path, string $packageName = null): string
|
||||
{
|
||||
return $this->packages->getVersion($path, $packageName);
|
||||
}
|
||||
}
|
246
vendor/symfony/twig-bridge/Extension/CodeExtension.php
vendored
Normal file
246
vendor/symfony/twig-bridge/Extension/CodeExtension.php
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
||||
/**
|
||||
* Twig extension relate to PHP code and used by the profiler and the default exception templates.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class CodeExtension extends AbstractExtension
|
||||
{
|
||||
private $fileLinkFormat;
|
||||
private $charset;
|
||||
private $projectDir;
|
||||
|
||||
/**
|
||||
* @param string|FileLinkFormatter $fileLinkFormat The format for links to source files
|
||||
*/
|
||||
public function __construct($fileLinkFormat, string $projectDir, string $charset)
|
||||
{
|
||||
$this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
|
||||
$this->projectDir = str_replace('\\', '/', $projectDir).'/';
|
||||
$this->charset = $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('abbr_class', [$this, 'abbrClass'], ['is_safe' => ['html']]),
|
||||
new TwigFilter('abbr_method', [$this, 'abbrMethod'], ['is_safe' => ['html']]),
|
||||
new TwigFilter('format_args', [$this, 'formatArgs'], ['is_safe' => ['html']]),
|
||||
new TwigFilter('format_args_as_text', [$this, 'formatArgsAsText']),
|
||||
new TwigFilter('file_excerpt', [$this, 'fileExcerpt'], ['is_safe' => ['html']]),
|
||||
new TwigFilter('format_file', [$this, 'formatFile'], ['is_safe' => ['html']]),
|
||||
new TwigFilter('format_file_from_text', [$this, 'formatFileFromText'], ['is_safe' => ['html']]),
|
||||
new TwigFilter('format_log_message', [$this, 'formatLogMessage'], ['is_safe' => ['html']]),
|
||||
new TwigFilter('file_link', [$this, 'getFileLink']),
|
||||
new TwigFilter('file_relative', [$this, 'getFileRelative']),
|
||||
];
|
||||
}
|
||||
|
||||
public function abbrClass(string $class): string
|
||||
{
|
||||
$parts = explode('\\', $class);
|
||||
$short = array_pop($parts);
|
||||
|
||||
return sprintf('<abbr title="%s">%s</abbr>', $class, $short);
|
||||
}
|
||||
|
||||
public function abbrMethod(string $method): string
|
||||
{
|
||||
if (str_contains($method, '::')) {
|
||||
[$class, $method] = explode('::', $method, 2);
|
||||
$result = sprintf('%s::%s()', $this->abbrClass($class), $method);
|
||||
} elseif ('Closure' === $method) {
|
||||
$result = sprintf('<abbr title="%s">%1$s</abbr>', $method);
|
||||
} else {
|
||||
$result = sprintf('<abbr title="%s">%1$s</abbr>()', $method);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an array as a string.
|
||||
*/
|
||||
public function formatArgs(array $args): string
|
||||
{
|
||||
$result = [];
|
||||
foreach ($args as $key => $item) {
|
||||
if ('object' === $item[0]) {
|
||||
$parts = explode('\\', $item[1]);
|
||||
$short = array_pop($parts);
|
||||
$formattedValue = sprintf('<em>object</em>(<abbr title="%s">%s</abbr>)', $item[1], $short);
|
||||
} elseif ('array' === $item[0]) {
|
||||
$formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
|
||||
} elseif ('null' === $item[0]) {
|
||||
$formattedValue = '<em>null</em>';
|
||||
} elseif ('boolean' === $item[0]) {
|
||||
$formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
|
||||
} elseif ('resource' === $item[0]) {
|
||||
$formattedValue = '<em>resource</em>';
|
||||
} else {
|
||||
$formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset));
|
||||
}
|
||||
|
||||
$result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue);
|
||||
}
|
||||
|
||||
return implode(', ', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats an array as a string.
|
||||
*/
|
||||
public function formatArgsAsText(array $args): string
|
||||
{
|
||||
return strip_tags($this->formatArgs($args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an excerpt of a code file around the given line number.
|
||||
*/
|
||||
public function fileExcerpt(string $file, int $line, int $srcContext = 3): ?string
|
||||
{
|
||||
if (is_file($file) && is_readable($file)) {
|
||||
// highlight_file could throw warnings
|
||||
// see https://bugs.php.net/25725
|
||||
$code = @highlight_file($file, true);
|
||||
// remove main code/span tags
|
||||
$code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code);
|
||||
// split multiline spans
|
||||
$code = preg_replace_callback('#<span ([^>]++)>((?:[^<]*+<br \/>)++[^<]*+)</span>#', function ($m) {
|
||||
return "<span $m[1]>".str_replace('<br />', "</span><br /><span $m[1]>", $m[2]).'</span>';
|
||||
}, $code);
|
||||
$content = explode('<br />', $code);
|
||||
|
||||
$lines = [];
|
||||
if (0 > $srcContext) {
|
||||
$srcContext = \count($content);
|
||||
}
|
||||
|
||||
for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) {
|
||||
$lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><a class="anchor" id="line'.$i.'"></a><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>';
|
||||
}
|
||||
|
||||
return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a file path.
|
||||
*/
|
||||
public function formatFile(string $file, int $line, string $text = null): string
|
||||
{
|
||||
$file = trim($file);
|
||||
|
||||
if (null === $text) {
|
||||
$text = $file;
|
||||
if (null !== $rel = $this->getFileRelative($text)) {
|
||||
$rel = explode('/', $rel, 2);
|
||||
$text = sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->projectDir, $rel[0], '/'.($rel[1] ?? ''));
|
||||
}
|
||||
}
|
||||
|
||||
if (0 < $line) {
|
||||
$text .= ' at line '.$line;
|
||||
}
|
||||
|
||||
if (false !== $link = $this->getFileLink($file, $line)) {
|
||||
return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', htmlspecialchars($link, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset), $text);
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the link for a given file/line pair.
|
||||
*
|
||||
* @return string|false
|
||||
*/
|
||||
public function getFileLink(string $file, int $line)
|
||||
{
|
||||
if ($fmt = $this->fileLinkFormat) {
|
||||
return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getFileRelative(string $file): ?string
|
||||
{
|
||||
$file = str_replace('\\', '/', $file);
|
||||
|
||||
if (null !== $this->projectDir && str_starts_with($file, $this->projectDir)) {
|
||||
return ltrim(substr($file, \strlen($this->projectDir)), '/');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function formatFileFromText(string $text): string
|
||||
{
|
||||
return preg_replace_callback('/in ("|")?(.+?)\1(?: +(?:on|at))? +line (\d+)/s', function ($match) {
|
||||
return 'in '.$this->formatFile($match[2], $match[3]);
|
||||
}, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function formatLogMessage(string $message, array $context): string
|
||||
{
|
||||
if ($context && str_contains($message, '{')) {
|
||||
$replacements = [];
|
||||
foreach ($context as $key => $val) {
|
||||
if (is_scalar($val)) {
|
||||
$replacements['{'.$key.'}'] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
if ($replacements) {
|
||||
$message = strtr($message, $replacements);
|
||||
}
|
||||
}
|
||||
|
||||
return htmlspecialchars($message, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset);
|
||||
}
|
||||
|
||||
protected static function fixCodeMarkup(string $line): string
|
||||
{
|
||||
// </span> ending tag from previous line
|
||||
$opening = strpos($line, '<span');
|
||||
$closing = strpos($line, '</span>');
|
||||
if (false !== $closing && (false === $opening || $closing < $opening)) {
|
||||
$line = substr_replace($line, '', $closing, 7);
|
||||
}
|
||||
|
||||
// missing </span> tag at the end of line
|
||||
$opening = strpos($line, '<span');
|
||||
$closing = strpos($line, '</span>');
|
||||
if (false !== $opening && (false === $closing || $closing > $opening)) {
|
||||
$line .= '</span>';
|
||||
}
|
||||
|
||||
return trim($line);
|
||||
}
|
||||
}
|
32
vendor/symfony/twig-bridge/Extension/CsrfExtension.php
vendored
Normal file
32
vendor/symfony/twig-bridge/Extension/CsrfExtension.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
* @author Titouan Galopin <galopintitouan@gmail.com>
|
||||
*/
|
||||
final class CsrfExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('csrf_token', [CsrfRuntime::class, 'getCsrfToken']),
|
||||
];
|
||||
}
|
||||
}
|
33
vendor/symfony/twig-bridge/Extension/CsrfRuntime.php
vendored
Normal file
33
vendor/symfony/twig-bridge/Extension/CsrfRuntime.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
|
||||
/**
|
||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||
* @author Titouan Galopin <galopintitouan@gmail.com>
|
||||
*/
|
||||
final class CsrfRuntime
|
||||
{
|
||||
private $csrfTokenManager;
|
||||
|
||||
public function __construct(CsrfTokenManagerInterface $csrfTokenManager)
|
||||
{
|
||||
$this->csrfTokenManager = $csrfTokenManager;
|
||||
}
|
||||
|
||||
public function getCsrfToken(string $tokenId): string
|
||||
{
|
||||
return $this->csrfTokenManager->getToken($tokenId)->getValue();
|
||||
}
|
||||
}
|
86
vendor/symfony/twig-bridge/Extension/DumpExtension.php
vendored
Normal file
86
vendor/symfony/twig-bridge/Extension/DumpExtension.php
vendored
Normal file
@ -0,0 +1,86 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\TokenParser\DumpTokenParser;
|
||||
use Symfony\Component\VarDumper\Cloner\ClonerInterface;
|
||||
use Symfony\Component\VarDumper\Dumper\HtmlDumper;
|
||||
use Twig\Environment;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\Template;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Provides integration of the dump() function with Twig.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
final class DumpExtension extends AbstractExtension
|
||||
{
|
||||
private $cloner;
|
||||
private $dumper;
|
||||
|
||||
public function __construct(ClonerInterface $cloner, HtmlDumper $dumper = null)
|
||||
{
|
||||
$this->cloner = $cloner;
|
||||
$this->dumper = $dumper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('dump', [$this, 'dump'], ['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenParsers(): array
|
||||
{
|
||||
return [new DumpTokenParser()];
|
||||
}
|
||||
|
||||
public function dump(Environment $env, array $context): ?string
|
||||
{
|
||||
if (!$env->isDebug()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (2 === \func_num_args()) {
|
||||
$vars = [];
|
||||
foreach ($context as $key => $value) {
|
||||
if (!$value instanceof Template) {
|
||||
$vars[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$vars = [$vars];
|
||||
} else {
|
||||
$vars = \func_get_args();
|
||||
unset($vars[0], $vars[1]);
|
||||
}
|
||||
|
||||
$dump = fopen('php://memory', 'r+');
|
||||
$this->dumper = $this->dumper ?? new HtmlDumper();
|
||||
$this->dumper->setCharset($env->getCharset());
|
||||
|
||||
foreach ($vars as $value) {
|
||||
$this->dumper->dump($this->cloner->cloneVar($value), $dump);
|
||||
}
|
||||
|
||||
return stream_get_contents($dump, -1, 0);
|
||||
}
|
||||
}
|
39
vendor/symfony/twig-bridge/Extension/ExpressionExtension.php
vendored
Normal file
39
vendor/symfony/twig-bridge/Extension/ExpressionExtension.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* ExpressionExtension gives a way to create Expressions from a template.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class ExpressionExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('expression', [$this, 'createExpression']),
|
||||
];
|
||||
}
|
||||
|
||||
public function createExpression(string $expression): Expression
|
||||
{
|
||||
return new Expression($expression);
|
||||
}
|
||||
}
|
219
vendor/symfony/twig-bridge/Extension/FormExtension.php
vendored
Normal file
219
vendor/symfony/twig-bridge/Extension/FormExtension.php
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
|
||||
use Symfony\Component\Form\ChoiceList\View\ChoiceGroupView;
|
||||
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
|
||||
use Symfony\Component\Form\FormError;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
use Twig\TwigTest;
|
||||
|
||||
/**
|
||||
* FormExtension extends Twig with form capabilities.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
final class FormExtension extends AbstractExtension
|
||||
{
|
||||
private $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator = null)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenParsers(): array
|
||||
{
|
||||
return [
|
||||
// {% form_theme form "SomeBundle::widgets.twig" %}
|
||||
new FormThemeTokenParser(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('form_widget', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form_errors', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form_label', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form_help', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form_row', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form_rest', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form_start', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('form_end', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]),
|
||||
new TwigFunction('csrf_token', ['Symfony\Component\Form\FormRenderer', 'renderCsrfToken']),
|
||||
new TwigFunction('form_parent', 'Symfony\Bridge\Twig\Extension\twig_get_form_parent'),
|
||||
new TwigFunction('field_name', [$this, 'getFieldName']),
|
||||
new TwigFunction('field_value', [$this, 'getFieldValue']),
|
||||
new TwigFunction('field_label', [$this, 'getFieldLabel']),
|
||||
new TwigFunction('field_help', [$this, 'getFieldHelp']),
|
||||
new TwigFunction('field_errors', [$this, 'getFieldErrors']),
|
||||
new TwigFunction('field_choices', [$this, 'getFieldChoices']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('humanize', ['Symfony\Component\Form\FormRenderer', 'humanize']),
|
||||
new TwigFilter('form_encode_currency', ['Symfony\Component\Form\FormRenderer', 'encodeCurrency'], ['is_safe' => ['html'], 'needs_environment' => true]),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTests(): array
|
||||
{
|
||||
return [
|
||||
new TwigTest('selectedchoice', 'Symfony\Bridge\Twig\Extension\twig_is_selected_choice'),
|
||||
new TwigTest('rootform', 'Symfony\Bridge\Twig\Extension\twig_is_root_form'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getFieldName(FormView $view): string
|
||||
{
|
||||
$view->setRendered();
|
||||
|
||||
return $view->vars['full_name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|array
|
||||
*/
|
||||
public function getFieldValue(FormView $view)
|
||||
{
|
||||
return $view->vars['value'];
|
||||
}
|
||||
|
||||
public function getFieldLabel(FormView $view): ?string
|
||||
{
|
||||
if (false === $label = $view->vars['label']) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$label && $labelFormat = $view->vars['label_format']) {
|
||||
$label = str_replace(['%id%', '%name%'], [$view->vars['id'], $view->vars['name']], $labelFormat);
|
||||
} elseif (!$label) {
|
||||
$label = ucfirst(strtolower(trim(preg_replace(['/([A-Z])/', '/[_\s]+/'], ['_$1', ' '], $view->vars['name']))));
|
||||
}
|
||||
|
||||
return $this->createFieldTranslation(
|
||||
$label,
|
||||
$view->vars['label_translation_parameters'] ?: [],
|
||||
$view->vars['translation_domain']
|
||||
);
|
||||
}
|
||||
|
||||
public function getFieldHelp(FormView $view): ?string
|
||||
{
|
||||
return $this->createFieldTranslation(
|
||||
$view->vars['help'],
|
||||
$view->vars['help_translation_parameters'] ?: [],
|
||||
$view->vars['translation_domain']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getFieldErrors(FormView $view): iterable
|
||||
{
|
||||
/** @var FormError $error */
|
||||
foreach ($view->vars['errors'] as $error) {
|
||||
yield $error->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]|string[][]
|
||||
*/
|
||||
public function getFieldChoices(FormView $view): iterable
|
||||
{
|
||||
yield from $this->createFieldChoicesList($view->vars['choices'], $view->vars['choice_translation_domain']);
|
||||
}
|
||||
|
||||
private function createFieldChoicesList(iterable $choices, $translationDomain): iterable
|
||||
{
|
||||
foreach ($choices as $choice) {
|
||||
$translatableLabel = $this->createFieldTranslation($choice->label, [], $translationDomain);
|
||||
|
||||
if ($choice instanceof ChoiceGroupView) {
|
||||
yield $translatableLabel => $this->createFieldChoicesList($choice, $translationDomain);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* @var ChoiceView $choice */
|
||||
yield $translatableLabel => $choice->value;
|
||||
}
|
||||
}
|
||||
|
||||
private function createFieldTranslation(?string $value, array $parameters, $domain): ?string
|
||||
{
|
||||
if (!$this->translator || !$value || false === $domain) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $this->translator->trans($value, $parameters, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a choice is selected for a given form value.
|
||||
*
|
||||
* This is a function and not callable due to performance reasons.
|
||||
*
|
||||
* @param string|array $selectedValue The selected value to compare
|
||||
*
|
||||
* @see ChoiceView::isSelected()
|
||||
*/
|
||||
function twig_is_selected_choice(ChoiceView $choice, $selectedValue): bool
|
||||
{
|
||||
if (\is_array($selectedValue)) {
|
||||
return \in_array($choice->value, $selectedValue, true);
|
||||
}
|
||||
|
||||
return $choice->value === $selectedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function twig_is_root_form(FormView $formView): bool
|
||||
{
|
||||
return null === $formView->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function twig_get_form_parent(FormView $formView): ?FormView
|
||||
{
|
||||
return $formView->parent;
|
||||
}
|
67
vendor/symfony/twig-bridge/Extension/HttpFoundationExtension.php
vendored
Normal file
67
vendor/symfony/twig-bridge/Extension/HttpFoundationExtension.php
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\UrlHelper;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Twig extension for the Symfony HttpFoundation component.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class HttpFoundationExtension extends AbstractExtension
|
||||
{
|
||||
private $urlHelper;
|
||||
|
||||
public function __construct(UrlHelper $urlHelper)
|
||||
{
|
||||
$this->urlHelper = $urlHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('absolute_url', [$this, 'generateAbsoluteUrl']),
|
||||
new TwigFunction('relative_path', [$this, 'generateRelativePath']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute URL for the given absolute or relative path.
|
||||
*
|
||||
* This method returns the path unchanged if no request is available.
|
||||
*
|
||||
* @see Request::getUriForPath()
|
||||
*/
|
||||
public function generateAbsoluteUrl(string $path): string
|
||||
{
|
||||
return $this->urlHelper->getAbsoluteUrl($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a relative path based on the current Request.
|
||||
*
|
||||
* This method returns the path unchanged if no request is available.
|
||||
*
|
||||
* @see Request::getRelativeUriForPath()
|
||||
*/
|
||||
public function generateRelativePath(string $path): string
|
||||
{
|
||||
return $this->urlHelper->getRelativePath($path);
|
||||
}
|
||||
}
|
42
vendor/symfony/twig-bridge/Extension/HttpKernelExtension.php
vendored
Normal file
42
vendor/symfony/twig-bridge/Extension/HttpKernelExtension.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\HttpKernel\Controller\ControllerReference;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Provides integration with the HttpKernel component.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class HttpKernelExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('render', [HttpKernelRuntime::class, 'renderFragment'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('render_*', [HttpKernelRuntime::class, 'renderFragmentStrategy'], ['is_safe' => ['html']]),
|
||||
new TwigFunction('fragment_uri', [HttpKernelRuntime::class, 'generateFragmentUri']),
|
||||
new TwigFunction('controller', static::class.'::controller'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function controller(string $controller, array $attributes = [], array $query = []): ControllerReference
|
||||
{
|
||||
return new ControllerReference($controller, $attributes, $query);
|
||||
}
|
||||
}
|
69
vendor/symfony/twig-bridge/Extension/HttpKernelRuntime.php
vendored
Normal file
69
vendor/symfony/twig-bridge/Extension/HttpKernelRuntime.php
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\HttpKernel\Controller\ControllerReference;
|
||||
use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
|
||||
use Symfony\Component\HttpKernel\Fragment\FragmentUriGeneratorInterface;
|
||||
|
||||
/**
|
||||
* Provides integration with the HttpKernel component.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class HttpKernelRuntime
|
||||
{
|
||||
private $handler;
|
||||
private $fragmentUriGenerator;
|
||||
|
||||
public function __construct(FragmentHandler $handler, FragmentUriGeneratorInterface $fragmentUriGenerator = null)
|
||||
{
|
||||
$this->handler = $handler;
|
||||
$this->fragmentUriGenerator = $fragmentUriGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a fragment.
|
||||
*
|
||||
* @param string|ControllerReference $uri A URI as a string or a ControllerReference instance
|
||||
*
|
||||
* @see FragmentHandler::render()
|
||||
*/
|
||||
public function renderFragment($uri, array $options = []): string
|
||||
{
|
||||
$strategy = $options['strategy'] ?? 'inline';
|
||||
unset($options['strategy']);
|
||||
|
||||
return $this->handler->render($uri, $strategy, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a fragment.
|
||||
*
|
||||
* @param string|ControllerReference $uri A URI as a string or a ControllerReference instance
|
||||
*
|
||||
* @see FragmentHandler::render()
|
||||
*/
|
||||
public function renderFragmentStrategy(string $strategy, $uri, array $options = []): string
|
||||
{
|
||||
return $this->handler->render($uri, $strategy, $options);
|
||||
}
|
||||
|
||||
public function generateFragmentUri(ControllerReference $controller, bool $absolute = false, bool $strict = true, bool $sign = true): string
|
||||
{
|
||||
if (null === $this->fragmentUriGenerator) {
|
||||
throw new \LogicException(sprintf('An instance of "%s" must be provided to use "%s()".', FragmentUriGeneratorInterface::class, __METHOD__));
|
||||
}
|
||||
|
||||
return $this->fragmentUriGenerator->generate($controller, null, $absolute, $strict, $sign);
|
||||
}
|
||||
}
|
62
vendor/symfony/twig-bridge/Extension/LogoutUrlExtension.php
vendored
Normal file
62
vendor/symfony/twig-bridge/Extension/LogoutUrlExtension.php
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* LogoutUrlHelper provides generator functions for the logout URL to Twig.
|
||||
*
|
||||
* @author Jeremy Mikola <jmikola@gmail.com>
|
||||
*/
|
||||
final class LogoutUrlExtension extends AbstractExtension
|
||||
{
|
||||
private $generator;
|
||||
|
||||
public function __construct(LogoutUrlGenerator $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('logout_url', [$this, 'getLogoutUrl']),
|
||||
new TwigFunction('logout_path', [$this, 'getLogoutPath']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the relative logout URL for the firewall.
|
||||
*
|
||||
* @param string|null $key The firewall key or null to use the current firewall key
|
||||
*/
|
||||
public function getLogoutPath(string $key = null): string
|
||||
{
|
||||
return $this->generator->getLogoutPath($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the absolute logout URL for the firewall.
|
||||
*
|
||||
* @param string|null $key The firewall key or null to use the current firewall key
|
||||
*/
|
||||
public function getLogoutUrl(string $key = null): string
|
||||
{
|
||||
return $this->generator->getLogoutUrl($key);
|
||||
}
|
||||
}
|
57
vendor/symfony/twig-bridge/Extension/ProfilerExtension.php
vendored
Normal file
57
vendor/symfony/twig-bridge/Extension/ProfilerExtension.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Symfony\Component\Stopwatch\StopwatchEvent;
|
||||
use Twig\Extension\ProfilerExtension as BaseProfilerExtension;
|
||||
use Twig\Profiler\Profile;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class ProfilerExtension extends BaseProfilerExtension
|
||||
{
|
||||
private $stopwatch;
|
||||
|
||||
/**
|
||||
* @var \SplObjectStorage<Profile, StopwatchEvent>
|
||||
*/
|
||||
private $events;
|
||||
|
||||
public function __construct(Profile $profile, Stopwatch $stopwatch = null)
|
||||
{
|
||||
parent::__construct($profile);
|
||||
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->events = new \SplObjectStorage();
|
||||
}
|
||||
|
||||
public function enter(Profile $profile): void
|
||||
{
|
||||
if ($this->stopwatch && $profile->isTemplate()) {
|
||||
$this->events[$profile] = $this->stopwatch->start($profile->getName(), 'template');
|
||||
}
|
||||
|
||||
parent::enter($profile);
|
||||
}
|
||||
|
||||
public function leave(Profile $profile): void
|
||||
{
|
||||
parent::leave($profile);
|
||||
|
||||
if ($this->stopwatch && $profile->isTemplate()) {
|
||||
$this->events[$profile]->stop();
|
||||
unset($this->events[$profile]);
|
||||
}
|
||||
}
|
||||
}
|
93
vendor/symfony/twig-bridge/Extension/RoutingExtension.php
vendored
Normal file
93
vendor/symfony/twig-bridge/Extension/RoutingExtension.php
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\Node\Expression\ArrayExpression;
|
||||
use Twig\Node\Expression\ConstantExpression;
|
||||
use Twig\Node\Node;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Provides integration of the Routing component with Twig.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class RoutingExtension extends AbstractExtension
|
||||
{
|
||||
private $generator;
|
||||
|
||||
public function __construct(UrlGeneratorInterface $generator)
|
||||
{
|
||||
$this->generator = $generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]),
|
||||
new TwigFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]),
|
||||
];
|
||||
}
|
||||
|
||||
public function getPath(string $name, array $parameters = [], bool $relative = false): string
|
||||
{
|
||||
return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
|
||||
}
|
||||
|
||||
public function getUrl(string $name, array $parameters = [], bool $schemeRelative = false): string
|
||||
{
|
||||
return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines at compile time whether the generated URL will be safe and thus
|
||||
* saving the unneeded automatic escaping for performance reasons.
|
||||
*
|
||||
* The URL generation process percent encodes non-alphanumeric characters. So there is no risk
|
||||
* that malicious/invalid characters are part of the URL. The only character within an URL that
|
||||
* must be escaped in html is the ampersand ("&") which separates query params. So we cannot mark
|
||||
* the URL generation as always safe, but only when we are sure there won't be multiple query
|
||||
* params. This is the case when there are none or only one constant parameter given.
|
||||
* E.g. we know beforehand this will be safe:
|
||||
* - path('route')
|
||||
* - path('route', {'param': 'value'})
|
||||
* But the following may not:
|
||||
* - path('route', var)
|
||||
* - path('route', {'param': ['val1', 'val2'] }) // a sub-array
|
||||
* - path('route', {'param1': 'value1', 'param2': 'value2'})
|
||||
* If param1 and param2 reference placeholder in the route, it would still be safe. But we don't know.
|
||||
*
|
||||
* @param Node $argsNode The arguments of the path/url function
|
||||
*
|
||||
* @return array An array with the contexts the URL is safe
|
||||
*/
|
||||
public function isUrlGenerationSafe(Node $argsNode): array
|
||||
{
|
||||
// support named arguments
|
||||
$paramsNode = $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : (
|
||||
$argsNode->hasNode(1) ? $argsNode->getNode(1) : null
|
||||
);
|
||||
|
||||
if (null === $paramsNode || $paramsNode instanceof ArrayExpression && \count($paramsNode) <= 2 &&
|
||||
(!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof ConstantExpression)
|
||||
) {
|
||||
return ['html'];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
87
vendor/symfony/twig-bridge/Extension/SecurityExtension.php
vendored
Normal file
87
vendor/symfony/twig-bridge/Extension/SecurityExtension.php
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Security\Acl\Voter\FieldVote;
|
||||
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
|
||||
use Symfony\Component\Security\Http\Impersonate\ImpersonateUrlGenerator;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* SecurityExtension exposes security context features.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class SecurityExtension extends AbstractExtension
|
||||
{
|
||||
private $securityChecker;
|
||||
|
||||
private $impersonateUrlGenerator;
|
||||
|
||||
public function __construct(AuthorizationCheckerInterface $securityChecker = null, ImpersonateUrlGenerator $impersonateUrlGenerator = null)
|
||||
{
|
||||
$this->securityChecker = $securityChecker;
|
||||
$this->impersonateUrlGenerator = $impersonateUrlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $object
|
||||
*/
|
||||
public function isGranted($role, $object = null, string $field = null): bool
|
||||
{
|
||||
if (null === $this->securityChecker) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (null !== $field) {
|
||||
$object = new FieldVote($object, $field);
|
||||
}
|
||||
|
||||
try {
|
||||
return $this->securityChecker->isGranted($role, $object);
|
||||
} catch (AuthenticationCredentialsNotFoundException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getImpersonateExitUrl(string $exitTo = null): string
|
||||
{
|
||||
if (null === $this->impersonateUrlGenerator) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->impersonateUrlGenerator->generateExitUrl($exitTo);
|
||||
}
|
||||
|
||||
public function getImpersonateExitPath(string $exitTo = null): string
|
||||
{
|
||||
if (null === $this->impersonateUrlGenerator) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $this->impersonateUrlGenerator->generateExitPath($exitTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('is_granted', [$this, 'isGranted']),
|
||||
new TwigFunction('impersonation_exit_url', [$this, 'getImpersonateExitUrl']),
|
||||
new TwigFunction('impersonation_exit_path', [$this, 'getImpersonateExitPath']),
|
||||
];
|
||||
}
|
||||
}
|
28
vendor/symfony/twig-bridge/Extension/SerializerExtension.php
vendored
Normal file
28
vendor/symfony/twig-bridge/Extension/SerializerExtension.php
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
||||
/**
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*/
|
||||
final class SerializerExtension extends AbstractExtension
|
||||
{
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('serialize', [SerializerRuntime::class, 'serialize']),
|
||||
];
|
||||
}
|
||||
}
|
33
vendor/symfony/twig-bridge/Extension/SerializerRuntime.php
vendored
Normal file
33
vendor/symfony/twig-bridge/Extension/SerializerRuntime.php
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Twig\Extension\RuntimeExtensionInterface;
|
||||
|
||||
/**
|
||||
* @author Jesse Rushlow <jr@rushlow.dev>
|
||||
*/
|
||||
final class SerializerRuntime implements RuntimeExtensionInterface
|
||||
{
|
||||
private $serializer;
|
||||
|
||||
public function __construct(SerializerInterface $serializer)
|
||||
{
|
||||
$this->serializer = $serializer;
|
||||
}
|
||||
|
||||
public function serialize($data, string $format = 'json', array $context = []): string
|
||||
{
|
||||
return $this->serializer->serialize($data, $format, $context);
|
||||
}
|
||||
}
|
54
vendor/symfony/twig-bridge/Extension/StopwatchExtension.php
vendored
Normal file
54
vendor/symfony/twig-bridge/Extension/StopwatchExtension.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser;
|
||||
use Symfony\Component\Stopwatch\Stopwatch;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TokenParser\TokenParserInterface;
|
||||
|
||||
/**
|
||||
* Twig extension for the stopwatch helper.
|
||||
*
|
||||
* @author Wouter J <wouter@wouterj.nl>
|
||||
*/
|
||||
final class StopwatchExtension extends AbstractExtension
|
||||
{
|
||||
private $stopwatch;
|
||||
private $enabled;
|
||||
|
||||
public function __construct(Stopwatch $stopwatch = null, bool $enabled = true)
|
||||
{
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->enabled = $enabled;
|
||||
}
|
||||
|
||||
public function getStopwatch(): Stopwatch
|
||||
{
|
||||
return $this->stopwatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TokenParserInterface[]
|
||||
*/
|
||||
public function getTokenParsers(): array
|
||||
{
|
||||
return [
|
||||
/*
|
||||
* {% stopwatch foo %}
|
||||
* Some stuff which will be recorded on the timeline
|
||||
* {% endstopwatch %}
|
||||
*/
|
||||
new StopwatchTokenParser(null !== $this->stopwatch && $this->enabled),
|
||||
];
|
||||
}
|
||||
}
|
145
vendor/symfony/twig-bridge/Extension/TranslationExtension.php
vendored
Normal file
145
vendor/symfony/twig-bridge/Extension/TranslationExtension.php
vendored
Normal file
@ -0,0 +1,145 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor;
|
||||
use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor;
|
||||
use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser;
|
||||
use Symfony\Bridge\Twig\TokenParser\TransTokenParser;
|
||||
use Symfony\Component\Translation\TranslatableMessage;
|
||||
use Symfony\Contracts\Translation\TranslatableInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorTrait;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
// Help opcache.preload discover always-needed symbols
|
||||
class_exists(TranslatorInterface::class);
|
||||
class_exists(TranslatorTrait::class);
|
||||
|
||||
/**
|
||||
* Provides integration of the Translation component with Twig.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class TranslationExtension extends AbstractExtension
|
||||
{
|
||||
private $translator;
|
||||
private $translationNodeVisitor;
|
||||
|
||||
public function __construct(TranslatorInterface $translator = null, TranslationNodeVisitor $translationNodeVisitor = null)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
$this->translationNodeVisitor = $translationNodeVisitor;
|
||||
}
|
||||
|
||||
public function getTranslator(): TranslatorInterface
|
||||
{
|
||||
if (null === $this->translator) {
|
||||
if (!interface_exists(TranslatorInterface::class)) {
|
||||
throw new \LogicException(sprintf('You cannot use the "%s" if the Translation Contracts are not available. Try running "composer require symfony/translation".', __CLASS__));
|
||||
}
|
||||
|
||||
$this->translator = new class() implements TranslatorInterface {
|
||||
use TranslatorTrait;
|
||||
};
|
||||
}
|
||||
|
||||
return $this->translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('t', [$this, 'createTranslatable']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('trans', [$this, 'trans']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenParsers(): array
|
||||
{
|
||||
return [
|
||||
// {% trans %}Symfony is great!{% endtrans %}
|
||||
new TransTokenParser(),
|
||||
|
||||
// {% trans_default_domain "foobar" %}
|
||||
new TransDefaultDomainTokenParser(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeVisitors(): array
|
||||
{
|
||||
return [$this->getTranslationNodeVisitor(), new TranslationDefaultDomainNodeVisitor()];
|
||||
}
|
||||
|
||||
public function getTranslationNodeVisitor(): TranslationNodeVisitor
|
||||
{
|
||||
return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|\Stringable|TranslatableInterface|null $message
|
||||
* @param array|string $arguments Can be the locale as a string when $message is a TranslatableInterface
|
||||
*/
|
||||
public function trans($message, $arguments = [], string $domain = null, string $locale = null, int $count = null): string
|
||||
{
|
||||
if ($message instanceof TranslatableInterface) {
|
||||
if ([] !== $arguments && !\is_string($arguments)) {
|
||||
throw new \TypeError(sprintf('Argument 2 passed to "%s()" must be a locale passed as a string when the message is a "%s", "%s" given.', __METHOD__, TranslatableInterface::class, get_debug_type($arguments)));
|
||||
}
|
||||
|
||||
return $message->trans($this->getTranslator(), $locale ?? (\is_string($arguments) ? $arguments : null));
|
||||
}
|
||||
|
||||
if (!\is_array($arguments)) {
|
||||
throw new \TypeError(sprintf('Unless the message is a "%s", argument 2 passed to "%s()" must be an array of parameters, "%s" given.', TranslatableInterface::class, __METHOD__, get_debug_type($arguments)));
|
||||
}
|
||||
|
||||
if ('' === $message = (string) $message) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (null !== $count) {
|
||||
$arguments['%count%'] = $count;
|
||||
}
|
||||
|
||||
return $this->getTranslator()->trans($message, $arguments, $domain, $locale);
|
||||
}
|
||||
|
||||
public function createTranslatable(string $message, array $parameters = [], string $domain = null): TranslatableMessage
|
||||
{
|
||||
if (!class_exists(TranslatableMessage::class)) {
|
||||
throw new \LogicException(sprintf('You cannot use the "%s" as the Translation Component is not installed. Try running "composer require symfony/translation".', __CLASS__));
|
||||
}
|
||||
|
||||
return new TranslatableMessage($message, $parameters, $domain);
|
||||
}
|
||||
}
|
133
vendor/symfony/twig-bridge/Extension/WebLinkExtension.php
vendored
Normal file
133
vendor/symfony/twig-bridge/Extension/WebLinkExtension.php
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\WebLink\GenericLinkProvider;
|
||||
use Symfony\Component\WebLink\Link;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* Twig extension for the Symfony WebLink component.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
final class WebLinkExtension extends AbstractExtension
|
||||
{
|
||||
private $requestStack;
|
||||
|
||||
public function __construct(RequestStack $requestStack)
|
||||
{
|
||||
$this->requestStack = $requestStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('link', [$this, 'link']),
|
||||
new TwigFunction('preload', [$this, 'preload']),
|
||||
new TwigFunction('dns_prefetch', [$this, 'dnsPrefetch']),
|
||||
new TwigFunction('preconnect', [$this, 'preconnect']),
|
||||
new TwigFunction('prefetch', [$this, 'prefetch']),
|
||||
new TwigFunction('prerender', [$this, 'prerender']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a "Link" HTTP header.
|
||||
*
|
||||
* @param string $rel The relation type (e.g. "preload", "prefetch", "prerender" or "dns-prefetch")
|
||||
* @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]")
|
||||
*
|
||||
* @return string The relation URI
|
||||
*/
|
||||
public function link(string $uri, string $rel, array $attributes = []): string
|
||||
{
|
||||
if (!$request = $this->requestStack->getMainRequest()) {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
$link = new Link($rel, $uri);
|
||||
foreach ($attributes as $key => $value) {
|
||||
$link = $link->withAttribute($key, $value);
|
||||
}
|
||||
|
||||
$linkProvider = $request->attributes->get('_links', new GenericLinkProvider());
|
||||
$request->attributes->set('_links', $linkProvider->withLink($link));
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads a resource.
|
||||
*
|
||||
* @param array $attributes The attributes of this link (e.g. "['as' => true]", "['crossorigin' => 'use-credentials']")
|
||||
*
|
||||
* @return string The path of the asset
|
||||
*/
|
||||
public function preload(string $uri, array $attributes = []): string
|
||||
{
|
||||
return $this->link($uri, 'preload', $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a resource origin as early as possible.
|
||||
*
|
||||
* @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]")
|
||||
*
|
||||
* @return string The path of the asset
|
||||
*/
|
||||
public function dnsPrefetch(string $uri, array $attributes = []): string
|
||||
{
|
||||
return $this->link($uri, 'dns-prefetch', $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates a early connection to a resource (DNS resolution, TCP handshake, TLS negotiation).
|
||||
*
|
||||
* @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]")
|
||||
*
|
||||
* @return string The path of the asset
|
||||
*/
|
||||
public function preconnect(string $uri, array $attributes = []): string
|
||||
{
|
||||
return $this->link($uri, 'preconnect', $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates to the client that it should prefetch this resource.
|
||||
*
|
||||
* @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]")
|
||||
*
|
||||
* @return string The path of the asset
|
||||
*/
|
||||
public function prefetch(string $uri, array $attributes = []): string
|
||||
{
|
||||
return $this->link($uri, 'prefetch', $attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates to the client that it should prerender this resource .
|
||||
*
|
||||
* @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]")
|
||||
*
|
||||
* @return string The path of the asset
|
||||
*/
|
||||
public function prerender(string $uri, array $attributes = []): string
|
||||
{
|
||||
return $this->link($uri, 'prerender', $attributes);
|
||||
}
|
||||
}
|
121
vendor/symfony/twig-bridge/Extension/WorkflowExtension.php
vendored
Normal file
121
vendor/symfony/twig-bridge/Extension/WorkflowExtension.php
vendored
Normal file
@ -0,0 +1,121 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use Symfony\Component\Workflow\Transition;
|
||||
use Symfony\Component\Workflow\TransitionBlockerList;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* WorkflowExtension.
|
||||
*
|
||||
* @author Grégoire Pineau <lyrixx@lyrixx.info>
|
||||
* @author Carlos Pereira De Amorim <carlos@shauri.fr>
|
||||
*/
|
||||
final class WorkflowExtension extends AbstractExtension
|
||||
{
|
||||
private $workflowRegistry;
|
||||
|
||||
public function __construct(Registry $workflowRegistry)
|
||||
{
|
||||
$this->workflowRegistry = $workflowRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions(): array
|
||||
{
|
||||
return [
|
||||
new TwigFunction('workflow_can', [$this, 'canTransition']),
|
||||
new TwigFunction('workflow_transitions', [$this, 'getEnabledTransitions']),
|
||||
new TwigFunction('workflow_transition', [$this, 'getEnabledTransition']),
|
||||
new TwigFunction('workflow_has_marked_place', [$this, 'hasMarkedPlace']),
|
||||
new TwigFunction('workflow_marked_places', [$this, 'getMarkedPlaces']),
|
||||
new TwigFunction('workflow_metadata', [$this, 'getMetadata']),
|
||||
new TwigFunction('workflow_transition_blockers', [$this, 'buildTransitionBlockerList']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the transition is enabled.
|
||||
*/
|
||||
public function canTransition(object $subject, string $transitionName, string $name = null): bool
|
||||
{
|
||||
return $this->workflowRegistry->get($subject, $name)->can($subject, $transitionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all enabled transitions.
|
||||
*
|
||||
* @return Transition[]
|
||||
*/
|
||||
public function getEnabledTransitions(object $subject, string $name = null): array
|
||||
{
|
||||
return $this->workflowRegistry->get($subject, $name)->getEnabledTransitions($subject);
|
||||
}
|
||||
|
||||
public function getEnabledTransition(object $subject, string $transition, string $name = null): ?Transition
|
||||
{
|
||||
return $this->workflowRegistry->get($subject, $name)->getEnabledTransition($subject, $transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the place is marked.
|
||||
*/
|
||||
public function hasMarkedPlace(object $subject, string $placeName, string $name = null): bool
|
||||
{
|
||||
return $this->workflowRegistry->get($subject, $name)->getMarking($subject)->has($placeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns marked places.
|
||||
*
|
||||
* @return string[]|int[]
|
||||
*/
|
||||
public function getMarkedPlaces(object $subject, bool $placesNameOnly = true, string $name = null): array
|
||||
{
|
||||
$places = $this->workflowRegistry->get($subject, $name)->getMarking($subject)->getPlaces();
|
||||
|
||||
if ($placesNameOnly) {
|
||||
return array_keys($places);
|
||||
}
|
||||
|
||||
return $places;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the metadata for a specific subject.
|
||||
*
|
||||
* @param string|Transition|null $metadataSubject Use null to get workflow metadata
|
||||
* Use a string (the place name) to get place metadata
|
||||
* Use a Transition instance to get transition metadata
|
||||
*/
|
||||
public function getMetadata(object $subject, string $key, $metadataSubject = null, string $name = null)
|
||||
{
|
||||
return $this
|
||||
->workflowRegistry
|
||||
->get($subject, $name)
|
||||
->getMetadataStore()
|
||||
->getMetadata($key, $metadataSubject)
|
||||
;
|
||||
}
|
||||
|
||||
public function buildTransitionBlockerList(object $subject, string $transitionName, string $name = null): TransitionBlockerList
|
||||
{
|
||||
$workflow = $this->workflowRegistry->get($subject, $name);
|
||||
|
||||
return $workflow->buildTransitionBlockerList($subject, $transitionName);
|
||||
}
|
||||
}
|
63
vendor/symfony/twig-bridge/Extension/YamlExtension.php
vendored
Normal file
63
vendor/symfony/twig-bridge/Extension/YamlExtension.php
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
<?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\Extension;
|
||||
|
||||
use Symfony\Component\Yaml\Dumper as YamlDumper;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
|
||||
/**
|
||||
* Provides integration of the Yaml component with Twig.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class YamlExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters(): array
|
||||
{
|
||||
return [
|
||||
new TwigFilter('yaml_encode', [$this, 'encode']),
|
||||
new TwigFilter('yaml_dump', [$this, 'dump']),
|
||||
];
|
||||
}
|
||||
|
||||
public function encode($input, int $inline = 0, int $dumpObjects = 0): string
|
||||
{
|
||||
static $dumper;
|
||||
|
||||
if (null === $dumper) {
|
||||
$dumper = new YamlDumper();
|
||||
}
|
||||
|
||||
if (\defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) {
|
||||
return $dumper->dump($input, $inline, 0, $dumpObjects);
|
||||
}
|
||||
|
||||
return $dumper->dump($input, $inline, 0, false, $dumpObjects);
|
||||
}
|
||||
|
||||
public function dump($value, int $inline = 0, int $dumpObjects = 0): string
|
||||
{
|
||||
if (\is_resource($value)) {
|
||||
return '%Resource%';
|
||||
}
|
||||
|
||||
if (\is_array($value) || \is_object($value)) {
|
||||
return '%'.\gettype($value).'% '.$this->encode($value, $inline, $dumpObjects);
|
||||
}
|
||||
|
||||
return $this->encode($value, $inline, $dumpObjects);
|
||||
}
|
||||
}
|
182
vendor/symfony/twig-bridge/Form/TwigRendererEngine.php
vendored
Normal file
182
vendor/symfony/twig-bridge/Form/TwigRendererEngine.php
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
<?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\Form;
|
||||
|
||||
use Symfony\Component\Form\AbstractRendererEngine;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Twig\Environment;
|
||||
use Twig\Template;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
class TwigRendererEngine extends AbstractRendererEngine
|
||||
{
|
||||
/**
|
||||
* @var Environment
|
||||
*/
|
||||
private $environment;
|
||||
|
||||
/**
|
||||
* @var Template
|
||||
*/
|
||||
private $template;
|
||||
|
||||
public function __construct(array $defaultThemes, Environment $environment)
|
||||
{
|
||||
parent::__construct($defaultThemes);
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function renderBlock(FormView $view, $resource, string $blockName, array $variables = [])
|
||||
{
|
||||
$cacheKey = $view->vars[self::CACHE_KEY_VAR];
|
||||
|
||||
$context = $this->environment->mergeGlobals($variables);
|
||||
|
||||
ob_start();
|
||||
|
||||
// By contract,This method can only be called after getting the resource
|
||||
// (which is passed to the method). Getting a resource for the first time
|
||||
// (with an empty cache) is guaranteed to invoke loadResourcesFromTheme(),
|
||||
// where the property $template is initialized.
|
||||
|
||||
// We do not call renderBlock here to avoid too many nested level calls
|
||||
// (XDebug limits the level to 100 by default)
|
||||
$this->template->displayBlock($blockName, $context, $this->resources[$cacheKey]);
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the cache with the resource for a given block name.
|
||||
*
|
||||
* This implementation eagerly loads all blocks of the themes assigned to the given view
|
||||
* and all of its ancestors views. This is necessary, because Twig receives the
|
||||
* list of blocks later. At that point, all blocks must already be loaded, for the
|
||||
* case that the function "block()" is used in the Twig template.
|
||||
*
|
||||
* @see getResourceForBlock()
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function loadResourceForBlockName(string $cacheKey, FormView $view, string $blockName)
|
||||
{
|
||||
// The caller guarantees that $this->resources[$cacheKey][$block] is
|
||||
// not set, but it doesn't have to check whether $this->resources[$cacheKey]
|
||||
// is set. If $this->resources[$cacheKey] is set, all themes for this
|
||||
// $cacheKey are already loaded (due to the eager population, see doc comment).
|
||||
if (isset($this->resources[$cacheKey])) {
|
||||
// As said in the previous, the caller guarantees that
|
||||
// $this->resources[$cacheKey][$block] is not set. Since the themes are
|
||||
// already loaded, it can only be a non-existing block.
|
||||
$this->resources[$cacheKey][$blockName] = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Recursively try to find the block in the themes assigned to $view,
|
||||
// then of its parent view, then of the parent view of the parent and so on.
|
||||
// When the root view is reached in this recursion, also the default
|
||||
// themes are taken into account.
|
||||
|
||||
// Check each theme whether it contains the searched block
|
||||
if (isset($this->themes[$cacheKey])) {
|
||||
for ($i = \count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) {
|
||||
$this->loadResourcesFromTheme($cacheKey, $this->themes[$cacheKey][$i]);
|
||||
// CONTINUE LOADING (see doc comment)
|
||||
}
|
||||
}
|
||||
|
||||
// Check the default themes once we reach the root view without success
|
||||
if (!$view->parent) {
|
||||
if (!isset($this->useDefaultThemes[$cacheKey]) || $this->useDefaultThemes[$cacheKey]) {
|
||||
for ($i = \count($this->defaultThemes) - 1; $i >= 0; --$i) {
|
||||
$this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]);
|
||||
// CONTINUE LOADING (see doc comment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Proceed with the themes of the parent view
|
||||
if ($view->parent) {
|
||||
$parentCacheKey = $view->parent->vars[self::CACHE_KEY_VAR];
|
||||
|
||||
if (!isset($this->resources[$parentCacheKey])) {
|
||||
$this->loadResourceForBlockName($parentCacheKey, $view->parent, $blockName);
|
||||
}
|
||||
|
||||
// EAGER CACHE POPULATION (see doc comment)
|
||||
foreach ($this->resources[$parentCacheKey] as $nestedBlockName => $resource) {
|
||||
if (!isset($this->resources[$cacheKey][$nestedBlockName])) {
|
||||
$this->resources[$cacheKey][$nestedBlockName] = $resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Even though we loaded the themes, it can happen that none of them
|
||||
// contains the searched block
|
||||
if (!isset($this->resources[$cacheKey][$blockName])) {
|
||||
// Cache that we didn't find anything to speed up further accesses
|
||||
$this->resources[$cacheKey][$blockName] = false;
|
||||
}
|
||||
|
||||
return false !== $this->resources[$cacheKey][$blockName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the resources for all blocks in a theme.
|
||||
*
|
||||
* @param mixed $theme The theme to load the block from. This parameter
|
||||
* is passed by reference, because it might be necessary
|
||||
* to initialize the theme first. Any changes made to
|
||||
* this variable will be kept and be available upon
|
||||
* further calls to this method using the same theme.
|
||||
*/
|
||||
protected function loadResourcesFromTheme(string $cacheKey, &$theme)
|
||||
{
|
||||
if (!$theme instanceof Template) {
|
||||
/* @var Template $theme */
|
||||
$theme = $this->environment->load($theme)->unwrap();
|
||||
}
|
||||
|
||||
if (null === $this->template) {
|
||||
// Store the first Template instance that we find so that
|
||||
// we can call displayBlock() later on. It doesn't matter *which*
|
||||
// template we use for that, since we pass the used blocks manually
|
||||
// anyway.
|
||||
$this->template = $theme;
|
||||
}
|
||||
|
||||
// Use a separate variable for the inheritance traversal, because
|
||||
// theme is a reference and we don't want to change it.
|
||||
$currentTheme = $theme;
|
||||
|
||||
$context = $this->environment->mergeGlobals([]);
|
||||
|
||||
// The do loop takes care of template inheritance.
|
||||
// Add blocks from all templates in the inheritance tree, but avoid
|
||||
// overriding blocks already set.
|
||||
do {
|
||||
foreach ($currentTheme->getBlocks() as $block => $blockData) {
|
||||
if (!isset($this->resources[$cacheKey][$block])) {
|
||||
// The resource given back is the key to the bucket that
|
||||
// contains this block.
|
||||
$this->resources[$cacheKey][$block] = $blockData;
|
||||
}
|
||||
}
|
||||
} while (false !== $currentTheme = $currentTheme->getParent($context));
|
||||
}
|
||||
}
|
19
vendor/symfony/twig-bridge/LICENSE
vendored
Normal file
19
vendor/symfony/twig-bridge/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2004-2022 Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
105
vendor/symfony/twig-bridge/Mime/BodyRenderer.php
vendored
Normal file
105
vendor/symfony/twig-bridge/Mime/BodyRenderer.php
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
<?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\Mime;
|
||||
|
||||
use League\HTMLToMarkdown\HtmlConverter;
|
||||
use Symfony\Component\Mime\BodyRendererInterface;
|
||||
use Symfony\Component\Mime\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Mime\Message;
|
||||
use Twig\Environment;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class BodyRenderer implements BodyRendererInterface
|
||||
{
|
||||
private $twig;
|
||||
private $context;
|
||||
private $converter;
|
||||
|
||||
public function __construct(Environment $twig, array $context = [])
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->context = $context;
|
||||
if (class_exists(HtmlConverter::class)) {
|
||||
$this->converter = new HtmlConverter([
|
||||
'hard_break' => true,
|
||||
'strip_tags' => true,
|
||||
'remove_nodes' => 'head style',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function render(Message $message): void
|
||||
{
|
||||
if (!$message instanceof TemplatedEmail) {
|
||||
return;
|
||||
}
|
||||
|
||||
$messageContext = $message->getContext();
|
||||
|
||||
$previousRenderingKey = $messageContext[__CLASS__] ?? null;
|
||||
unset($messageContext[__CLASS__]);
|
||||
$currentRenderingKey = $this->getFingerPrint($message);
|
||||
if ($previousRenderingKey === $currentRenderingKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($messageContext['email'])) {
|
||||
throw new InvalidArgumentException(sprintf('A "%s" context cannot have an "email" entry as this is a reserved variable.', get_debug_type($message)));
|
||||
}
|
||||
|
||||
$vars = array_merge($this->context, $messageContext, [
|
||||
'email' => new WrappedTemplatedEmail($this->twig, $message),
|
||||
]);
|
||||
|
||||
if ($template = $message->getTextTemplate()) {
|
||||
$message->text($this->twig->render($template, $vars));
|
||||
}
|
||||
|
||||
if ($template = $message->getHtmlTemplate()) {
|
||||
$message->html($this->twig->render($template, $vars));
|
||||
}
|
||||
|
||||
// if text body is empty, compute one from the HTML body
|
||||
if (!$message->getTextBody() && null !== $html = $message->getHtmlBody()) {
|
||||
$message->text($this->convertHtmlToText(\is_resource($html) ? stream_get_contents($html) : $html));
|
||||
}
|
||||
$message->context($message->getContext() + [__CLASS__ => $currentRenderingKey]);
|
||||
}
|
||||
|
||||
private function getFingerPrint(TemplatedEmail $message): string
|
||||
{
|
||||
$messageContext = $message->getContext();
|
||||
unset($messageContext[__CLASS__]);
|
||||
|
||||
$payload = [$messageContext, $message->getTextTemplate(), $message->getHtmlTemplate()];
|
||||
try {
|
||||
$serialized = serialize($payload);
|
||||
} catch (\Exception $e) {
|
||||
// Serialization of 'Closure' is not allowed
|
||||
// Happens when context contain a closure, in that case, we assume that context always change.
|
||||
$serialized = random_bytes(8);
|
||||
}
|
||||
|
||||
return md5($serialized);
|
||||
}
|
||||
|
||||
private function convertHtmlToText(string $html): string
|
||||
{
|
||||
if (null !== $this->converter) {
|
||||
return $this->converter->convert($html);
|
||||
}
|
||||
|
||||
return strip_tags(preg_replace('{<(head|style)\b.*?</\1>}is', '', $html));
|
||||
}
|
||||
}
|
250
vendor/symfony/twig-bridge/Mime/NotificationEmail.php
vendored
Normal file
250
vendor/symfony/twig-bridge/Mime/NotificationEmail.php
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
<?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\Mime;
|
||||
|
||||
use Symfony\Component\ErrorHandler\Exception\FlattenException;
|
||||
use Symfony\Component\Mime\Header\Headers;
|
||||
use Symfony\Component\Mime\Part\AbstractPart;
|
||||
use Twig\Extra\CssInliner\CssInlinerExtension;
|
||||
use Twig\Extra\Inky\InkyExtension;
|
||||
use Twig\Extra\Markdown\MarkdownExtension;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class NotificationEmail extends TemplatedEmail
|
||||
{
|
||||
public const IMPORTANCE_URGENT = 'urgent';
|
||||
public const IMPORTANCE_HIGH = 'high';
|
||||
public const IMPORTANCE_MEDIUM = 'medium';
|
||||
public const IMPORTANCE_LOW = 'low';
|
||||
|
||||
private $theme = 'default';
|
||||
private $context = [
|
||||
'importance' => self::IMPORTANCE_LOW,
|
||||
'content' => '',
|
||||
'exception' => false,
|
||||
'action_text' => null,
|
||||
'action_url' => null,
|
||||
'markdown' => false,
|
||||
'raw' => false,
|
||||
'footer_text' => 'Notification e-mail sent by Symfony',
|
||||
];
|
||||
|
||||
public function __construct(Headers $headers = null, AbstractPart $body = null)
|
||||
{
|
||||
$missingPackages = [];
|
||||
if (!class_exists(CssInlinerExtension::class)) {
|
||||
$missingPackages['twig/cssinliner-extra'] = 'CSS Inliner';
|
||||
}
|
||||
|
||||
if (!class_exists(InkyExtension::class)) {
|
||||
$missingPackages['twig/inky-extra'] = 'Inky';
|
||||
}
|
||||
|
||||
if ($missingPackages) {
|
||||
throw new \LogicException(sprintf('You cannot use "%s" if the "%s" Twig extension%s not available; try running "%s".', static::class, implode('" and "', $missingPackages), \count($missingPackages) > 1 ? 's are' : ' is', 'composer require '.implode(' ', array_keys($missingPackages))));
|
||||
}
|
||||
|
||||
parent::__construct($headers, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a NotificationEmail instance that is appropriate to send to normal (non-admin) users.
|
||||
*/
|
||||
public static function asPublicEmail(Headers $headers = null, AbstractPart $body = null): self
|
||||
{
|
||||
$email = new static($headers, $body);
|
||||
$email->markAsPublic();
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function markAsPublic(): self
|
||||
{
|
||||
$this->context['importance'] = null;
|
||||
$this->context['footer_text'] = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function markdown(string $content)
|
||||
{
|
||||
if (!class_exists(MarkdownExtension::class)) {
|
||||
throw new \LogicException(sprintf('You cannot use "%s" if the Markdown Twig extension is not available; try running "composer require twig/markdown-extra".', __METHOD__));
|
||||
}
|
||||
|
||||
$this->context['markdown'] = true;
|
||||
|
||||
return $this->content($content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function content(string $content, bool $raw = false)
|
||||
{
|
||||
$this->context['content'] = $content;
|
||||
$this->context['raw'] = $raw;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function action(string $text, string $url)
|
||||
{
|
||||
$this->context['action_text'] = $text;
|
||||
$this->context['action_url'] = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function importance(string $importance)
|
||||
{
|
||||
$this->context['importance'] = $importance;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Throwable|FlattenException $exception
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function exception($exception)
|
||||
{
|
||||
if (!$exception instanceof \Throwable && !$exception instanceof FlattenException) {
|
||||
throw new \LogicException(sprintf('"%s" accepts "%s" or "%s" instances.', __METHOD__, \Throwable::class, FlattenException::class));
|
||||
}
|
||||
|
||||
$exceptionAsString = $this->getExceptionAsString($exception);
|
||||
|
||||
$this->context['exception'] = true;
|
||||
$this->attach($exceptionAsString, 'exception.txt', 'text/plain');
|
||||
$this->importance(self::IMPORTANCE_URGENT);
|
||||
|
||||
if (!$this->getSubject()) {
|
||||
$this->subject($exception->getMessage());
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function theme(string $theme)
|
||||
{
|
||||
$this->theme = $theme;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTextTemplate(): ?string
|
||||
{
|
||||
if ($template = parent::getTextTemplate()) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
return '@email/'.$this->theme.'/notification/body.txt.twig';
|
||||
}
|
||||
|
||||
public function getHtmlTemplate(): ?string
|
||||
{
|
||||
if ($template = parent::getHtmlTemplate()) {
|
||||
return $template;
|
||||
}
|
||||
|
||||
return '@email/'.$this->theme.'/notification/body.html.twig';
|
||||
}
|
||||
|
||||
public function getContext(): array
|
||||
{
|
||||
return array_merge($this->context, parent::getContext());
|
||||
}
|
||||
|
||||
public function getPreparedHeaders(): Headers
|
||||
{
|
||||
$headers = parent::getPreparedHeaders();
|
||||
|
||||
$importance = $this->context['importance'] ?? self::IMPORTANCE_LOW;
|
||||
$this->priority($this->determinePriority($importance));
|
||||
if ($this->context['importance']) {
|
||||
$headers->setHeaderBody('Text', 'Subject', sprintf('[%s] %s', strtoupper($importance), $this->getSubject()));
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
private function determinePriority(string $importance): int
|
||||
{
|
||||
switch ($importance) {
|
||||
case self::IMPORTANCE_URGENT:
|
||||
return self::PRIORITY_HIGHEST;
|
||||
case self::IMPORTANCE_HIGH:
|
||||
return self::PRIORITY_HIGH;
|
||||
case self::IMPORTANCE_MEDIUM:
|
||||
return self::PRIORITY_NORMAL;
|
||||
case self::IMPORTANCE_LOW:
|
||||
default:
|
||||
return self::PRIORITY_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
private function getExceptionAsString($exception): string
|
||||
{
|
||||
if (class_exists(FlattenException::class)) {
|
||||
$exception = $exception instanceof FlattenException ? $exception : FlattenException::createFromThrowable($exception);
|
||||
|
||||
return $exception->getAsString();
|
||||
}
|
||||
|
||||
$message = \get_class($exception);
|
||||
if ('' !== $exception->getMessage()) {
|
||||
$message .= ': '.$exception->getMessage();
|
||||
}
|
||||
|
||||
$message .= ' in '.$exception->getFile().':'.$exception->getLine()."\n";
|
||||
$message .= "Stack trace:\n".$exception->getTraceAsString()."\n\n";
|
||||
|
||||
return rtrim($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return [$this->context, parent::__serialize()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
[$this->context, $parentData] = $data;
|
||||
|
||||
parent::__unserialize($parentData);
|
||||
}
|
||||
}
|
87
vendor/symfony/twig-bridge/Mime/TemplatedEmail.php
vendored
Normal file
87
vendor/symfony/twig-bridge/Mime/TemplatedEmail.php
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
<?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\Mime;
|
||||
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TemplatedEmail extends Email
|
||||
{
|
||||
private $htmlTemplate;
|
||||
private $textTemplate;
|
||||
private $context = [];
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function textTemplate(?string $template)
|
||||
{
|
||||
$this->textTemplate = $template;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function htmlTemplate(?string $template)
|
||||
{
|
||||
$this->htmlTemplate = $template;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTextTemplate(): ?string
|
||||
{
|
||||
return $this->textTemplate;
|
||||
}
|
||||
|
||||
public function getHtmlTemplate(): ?string
|
||||
{
|
||||
return $this->htmlTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function context(array $context)
|
||||
{
|
||||
$this->context = $context;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getContext(): array
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
return [$this->htmlTemplate, $this->textTemplate, $this->context, parent::__serialize()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
[$this->htmlTemplate, $this->textTemplate, $this->context, $parentData] = $data;
|
||||
|
||||
parent::__unserialize($parentData);
|
||||
}
|
||||
}
|
194
vendor/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php
vendored
Normal file
194
vendor/symfony/twig-bridge/Mime/WrappedTemplatedEmail.php
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
<?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\Mime;
|
||||
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Twig\Environment;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class WrappedTemplatedEmail
|
||||
{
|
||||
private $twig;
|
||||
private $message;
|
||||
|
||||
public function __construct(Environment $twig, TemplatedEmail $message)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
$this->message = $message;
|
||||
}
|
||||
|
||||
public function toName(): string
|
||||
{
|
||||
return $this->message->getTo()[0]->getName();
|
||||
}
|
||||
|
||||
public function image(string $image, string $contentType = null): string
|
||||
{
|
||||
$file = $this->twig->getLoader()->getSourceContext($image);
|
||||
if ($path = $file->getPath()) {
|
||||
$this->message->embedFromPath($path, $image, $contentType);
|
||||
} else {
|
||||
$this->message->embed($file->getCode(), $image, $contentType);
|
||||
}
|
||||
|
||||
return 'cid:'.$image;
|
||||
}
|
||||
|
||||
public function attach(string $file, string $name = null, string $contentType = null): void
|
||||
{
|
||||
$file = $this->twig->getLoader()->getSourceContext($file);
|
||||
if ($path = $file->getPath()) {
|
||||
$this->message->attachFromPath($path, $name, $contentType);
|
||||
} else {
|
||||
$this->message->attach($file->getCode(), $name, $contentType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setSubject(string $subject): self
|
||||
{
|
||||
$this->message->subject($subject);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubject(): ?string
|
||||
{
|
||||
return $this->message->getSubject();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setReturnPath(string $address): self
|
||||
{
|
||||
$this->message->returnPath($address);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getReturnPath(): string
|
||||
{
|
||||
return $this->message->getReturnPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addFrom(string $address, string $name = ''): self
|
||||
{
|
||||
$this->message->addFrom(new Address($address, $name));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Address[]
|
||||
*/
|
||||
public function getFrom(): array
|
||||
{
|
||||
return $this->message->getFrom();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addReplyTo(string $address): self
|
||||
{
|
||||
$this->message->addReplyTo($address);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Address[]
|
||||
*/
|
||||
public function getReplyTo(): array
|
||||
{
|
||||
return $this->message->getReplyTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addTo(string $address, string $name = ''): self
|
||||
{
|
||||
$this->message->addTo(new Address($address, $name));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Address[]
|
||||
*/
|
||||
public function getTo(): array
|
||||
{
|
||||
return $this->message->getTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addCc(string $address, string $name = ''): self
|
||||
{
|
||||
$this->message->addCc(new Address($address, $name));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Address[]
|
||||
*/
|
||||
public function getCc(): array
|
||||
{
|
||||
return $this->message->getCc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function addBcc(string $address, string $name = ''): self
|
||||
{
|
||||
$this->message->addBcc(new Address($address, $name));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Address[]
|
||||
*/
|
||||
public function getBcc(): array
|
||||
{
|
||||
return $this->message->getBcc();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function setPriority(int $priority): self
|
||||
{
|
||||
$this->message->priority($priority);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPriority(): int
|
||||
{
|
||||
return $this->message->getPriority();
|
||||
}
|
||||
}
|
87
vendor/symfony/twig-bridge/Node/DumpNode.php
vendored
Normal file
87
vendor/symfony/twig-bridge/Node/DumpNode.php
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
<?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\Node;
|
||||
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Node;
|
||||
|
||||
/**
|
||||
* @author Julien Galenski <julien.galenski@gmail.com>
|
||||
*/
|
||||
final class DumpNode extends Node
|
||||
{
|
||||
private $varPrefix;
|
||||
|
||||
public function __construct(string $varPrefix, ?Node $values, int $lineno, string $tag = null)
|
||||
{
|
||||
$nodes = [];
|
||||
if (null !== $values) {
|
||||
$nodes['values'] = $values;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, [], $lineno, $tag);
|
||||
$this->varPrefix = $varPrefix;
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
$compiler
|
||||
->write("if (\$this->env->isDebug()) {\n")
|
||||
->indent();
|
||||
|
||||
if (!$this->hasNode('values')) {
|
||||
// remove embedded templates (macros) from the context
|
||||
$compiler
|
||||
->write(sprintf('$%svars = [];'."\n", $this->varPrefix))
|
||||
->write(sprintf('foreach ($context as $%1$skey => $%1$sval) {'."\n", $this->varPrefix))
|
||||
->indent()
|
||||
->write(sprintf('if (!$%sval instanceof \Twig\Template) {'."\n", $this->varPrefix))
|
||||
->indent()
|
||||
->write(sprintf('$%1$svars[$%1$skey] = $%1$sval;'."\n", $this->varPrefix))
|
||||
->outdent()
|
||||
->write("}\n")
|
||||
->outdent()
|
||||
->write("}\n")
|
||||
->addDebugInfo($this)
|
||||
->write(sprintf('\Symfony\Component\VarDumper\VarDumper::dump($%svars);'."\n", $this->varPrefix));
|
||||
} elseif (($values = $this->getNode('values')) && 1 === $values->count()) {
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write('\Symfony\Component\VarDumper\VarDumper::dump(')
|
||||
->subcompile($values->getNode(0))
|
||||
->raw(");\n");
|
||||
} else {
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write('\Symfony\Component\VarDumper\VarDumper::dump(['."\n")
|
||||
->indent();
|
||||
foreach ($values as $node) {
|
||||
$compiler->write('');
|
||||
if ($node->hasAttribute('name')) {
|
||||
$compiler
|
||||
->string($node->getAttribute('name'))
|
||||
->raw(' => ');
|
||||
}
|
||||
$compiler
|
||||
->subcompile($node)
|
||||
->raw(",\n");
|
||||
}
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("]);\n");
|
||||
}
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("}\n");
|
||||
}
|
||||
}
|
42
vendor/symfony/twig-bridge/Node/FormThemeNode.php
vendored
Normal file
42
vendor/symfony/twig-bridge/Node/FormThemeNode.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?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\Node;
|
||||
|
||||
use Symfony\Component\Form\FormRenderer;
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Node;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class FormThemeNode extends Node
|
||||
{
|
||||
public function __construct(Node $form, Node $resources, int $lineno, string $tag = null, bool $only = false)
|
||||
{
|
||||
parent::__construct(['form' => $form, 'resources' => $resources], ['only' => $only], $lineno, $tag);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write('$this->env->getRuntime(')
|
||||
->string(FormRenderer::class)
|
||||
->raw(')->setTheme(')
|
||||
->subcompile($this->getNode('form'))
|
||||
->raw(', ')
|
||||
->subcompile($this->getNode('resources'))
|
||||
->raw(', ')
|
||||
->raw(false === $this->getAttribute('only') ? 'true' : 'false')
|
||||
->raw(");\n");
|
||||
}
|
||||
}
|
45
vendor/symfony/twig-bridge/Node/RenderBlockNode.php
vendored
Normal file
45
vendor/symfony/twig-bridge/Node/RenderBlockNode.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?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\Node;
|
||||
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Expression\FunctionExpression;
|
||||
|
||||
/**
|
||||
* Compiles a call to {@link \Symfony\Component\Form\FormRendererInterface::renderBlock()}.
|
||||
*
|
||||
* The function name is used as block name. For example, if the function name
|
||||
* is "foo", the block "foo" will be rendered.
|
||||
*
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
final class RenderBlockNode extends FunctionExpression
|
||||
{
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
$compiler->addDebugInfo($this);
|
||||
$arguments = iterator_to_array($this->getNode('arguments'));
|
||||
$compiler->write('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->renderBlock(');
|
||||
|
||||
if (isset($arguments[0])) {
|
||||
$compiler->subcompile($arguments[0]);
|
||||
$compiler->raw(', \''.$this->getAttribute('name').'\'');
|
||||
|
||||
if (isset($arguments[1])) {
|
||||
$compiler->raw(', ');
|
||||
$compiler->subcompile($arguments[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$compiler->raw(')');
|
||||
}
|
||||
}
|
110
vendor/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php
vendored
Normal file
110
vendor/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
<?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\Node;
|
||||
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Expression\ArrayExpression;
|
||||
use Twig\Node\Expression\ConstantExpression;
|
||||
use Twig\Node\Expression\FunctionExpression;
|
||||
|
||||
/**
|
||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||
*/
|
||||
final class SearchAndRenderBlockNode extends FunctionExpression
|
||||
{
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
$compiler->addDebugInfo($this);
|
||||
$compiler->raw('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(');
|
||||
|
||||
preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches);
|
||||
|
||||
$arguments = iterator_to_array($this->getNode('arguments'));
|
||||
$blockNameSuffix = $matches[1];
|
||||
|
||||
if (isset($arguments[0])) {
|
||||
$compiler->subcompile($arguments[0]);
|
||||
$compiler->raw(', \''.$blockNameSuffix.'\'');
|
||||
|
||||
if (isset($arguments[1])) {
|
||||
if ('label' === $blockNameSuffix) {
|
||||
// The "label" function expects the label in the second and
|
||||
// the variables in the third argument
|
||||
$label = $arguments[1];
|
||||
$variables = $arguments[2] ?? null;
|
||||
$lineno = $label->getTemplateLine();
|
||||
|
||||
if ($label instanceof ConstantExpression) {
|
||||
// If the label argument is given as a constant, we can either
|
||||
// strip it away if it is empty, or integrate it into the array
|
||||
// of variables at compile time.
|
||||
$labelIsExpression = false;
|
||||
|
||||
// Only insert the label into the array if it is not empty
|
||||
if (!twig_test_empty($label->getAttribute('value'))) {
|
||||
$originalVariables = $variables;
|
||||
$variables = new ArrayExpression([], $lineno);
|
||||
$labelKey = new ConstantExpression('label', $lineno);
|
||||
|
||||
if (null !== $originalVariables) {
|
||||
foreach ($originalVariables->getKeyValuePairs() as $pair) {
|
||||
// Don't copy the original label attribute over if it exists
|
||||
if ((string) $labelKey !== (string) $pair['key']) {
|
||||
$variables->addElement($pair['value'], $pair['key']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert the label argument into the array
|
||||
$variables->addElement($label, $labelKey);
|
||||
}
|
||||
} else {
|
||||
// The label argument is not a constant, but some kind of
|
||||
// expression. This expression needs to be evaluated at runtime.
|
||||
// Depending on the result (whether it is null or not), the
|
||||
// label in the arguments should take precedence over the label
|
||||
// in the attributes or not.
|
||||
$labelIsExpression = true;
|
||||
}
|
||||
} else {
|
||||
// All other functions than "label" expect the variables
|
||||
// in the second argument
|
||||
$label = null;
|
||||
$variables = $arguments[1];
|
||||
$labelIsExpression = false;
|
||||
}
|
||||
|
||||
if (null !== $variables || $labelIsExpression) {
|
||||
$compiler->raw(', ');
|
||||
|
||||
if (null !== $variables) {
|
||||
$compiler->subcompile($variables);
|
||||
}
|
||||
|
||||
if ($labelIsExpression) {
|
||||
if (null !== $variables) {
|
||||
$compiler->raw(' + ');
|
||||
}
|
||||
|
||||
// Check at runtime whether the label is empty.
|
||||
// If not, add it to the array at runtime.
|
||||
$compiler->raw('(twig_test_empty($_label_ = ');
|
||||
$compiler->subcompile($label);
|
||||
$compiler->raw(') ? [] : ["label" => $_label_])');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$compiler->raw(')');
|
||||
}
|
||||
}
|
48
vendor/symfony/twig-bridge/Node/StopwatchNode.php
vendored
Normal file
48
vendor/symfony/twig-bridge/Node/StopwatchNode.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?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\Node;
|
||||
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Expression\AssignNameExpression;
|
||||
use Twig\Node\Node;
|
||||
|
||||
/**
|
||||
* Represents a stopwatch node.
|
||||
*
|
||||
* @author Wouter J <wouter@wouterj.nl>
|
||||
*/
|
||||
final class StopwatchNode extends Node
|
||||
{
|
||||
public function __construct(Node $name, Node $body, AssignNameExpression $var, int $lineno = 0, string $tag = null)
|
||||
{
|
||||
parent::__construct(['body' => $body, 'name' => $name, 'var' => $var], [], $lineno, $tag);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write('')
|
||||
->subcompile($this->getNode('var'))
|
||||
->raw(' = ')
|
||||
->subcompile($this->getNode('name'))
|
||||
->write(";\n")
|
||||
->write("\$this->env->getExtension('Symfony\Bridge\Twig\Extension\StopwatchExtension')->getStopwatch()->start(")
|
||||
->subcompile($this->getNode('var'))
|
||||
->raw(", 'template');\n")
|
||||
->subcompile($this->getNode('body'))
|
||||
->write("\$this->env->getExtension('Symfony\Bridge\Twig\Extension\StopwatchExtension')->getStopwatch()->stop(")
|
||||
->subcompile($this->getNode('var'))
|
||||
->raw(");\n")
|
||||
;
|
||||
}
|
||||
}
|
32
vendor/symfony/twig-bridge/Node/TransDefaultDomainNode.php
vendored
Normal file
32
vendor/symfony/twig-bridge/Node/TransDefaultDomainNode.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?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\Node;
|
||||
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Expression\AbstractExpression;
|
||||
use Twig\Node\Node;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class TransDefaultDomainNode extends Node
|
||||
{
|
||||
public function __construct(AbstractExpression $expr, int $lineno = 0, string $tag = null)
|
||||
{
|
||||
parent::__construct(['expr' => $expr], [], $lineno, $tag);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
// noop as this node is just a marker for TranslationDefaultDomainNodeVisitor
|
||||
}
|
||||
}
|
130
vendor/symfony/twig-bridge/Node/TransNode.php
vendored
Normal file
130
vendor/symfony/twig-bridge/Node/TransNode.php
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
<?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\Node;
|
||||
|
||||
use Twig\Compiler;
|
||||
use Twig\Node\Expression\AbstractExpression;
|
||||
use Twig\Node\Expression\ArrayExpression;
|
||||
use Twig\Node\Expression\ConstantExpression;
|
||||
use Twig\Node\Expression\NameExpression;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Node\TextNode;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class TransNode extends Node
|
||||
{
|
||||
public function __construct(Node $body, Node $domain = null, AbstractExpression $count = null, AbstractExpression $vars = null, AbstractExpression $locale = null, int $lineno = 0, string $tag = null)
|
||||
{
|
||||
$nodes = ['body' => $body];
|
||||
if (null !== $domain) {
|
||||
$nodes['domain'] = $domain;
|
||||
}
|
||||
if (null !== $count) {
|
||||
$nodes['count'] = $count;
|
||||
}
|
||||
if (null !== $vars) {
|
||||
$nodes['vars'] = $vars;
|
||||
}
|
||||
if (null !== $locale) {
|
||||
$nodes['locale'] = $locale;
|
||||
}
|
||||
|
||||
parent::__construct($nodes, [], $lineno, $tag);
|
||||
}
|
||||
|
||||
public function compile(Compiler $compiler): void
|
||||
{
|
||||
$compiler->addDebugInfo($this);
|
||||
|
||||
$defaults = new ArrayExpression([], -1);
|
||||
if ($this->hasNode('vars') && ($vars = $this->getNode('vars')) instanceof ArrayExpression) {
|
||||
$defaults = $this->getNode('vars');
|
||||
$vars = null;
|
||||
}
|
||||
[$msg, $defaults] = $this->compileString($this->getNode('body'), $defaults, (bool) $vars);
|
||||
|
||||
$compiler
|
||||
->write('echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->trans(')
|
||||
->subcompile($msg)
|
||||
;
|
||||
|
||||
$compiler->raw(', ');
|
||||
|
||||
if (null !== $vars) {
|
||||
$compiler
|
||||
->raw('array_merge(')
|
||||
->subcompile($defaults)
|
||||
->raw(', ')
|
||||
->subcompile($this->getNode('vars'))
|
||||
->raw(')')
|
||||
;
|
||||
} else {
|
||||
$compiler->subcompile($defaults);
|
||||
}
|
||||
|
||||
$compiler->raw(', ');
|
||||
|
||||
if (!$this->hasNode('domain')) {
|
||||
$compiler->repr('messages');
|
||||
} else {
|
||||
$compiler->subcompile($this->getNode('domain'));
|
||||
}
|
||||
|
||||
if ($this->hasNode('locale')) {
|
||||
$compiler
|
||||
->raw(', ')
|
||||
->subcompile($this->getNode('locale'))
|
||||
;
|
||||
} elseif ($this->hasNode('count')) {
|
||||
$compiler->raw(', null');
|
||||
}
|
||||
|
||||
if ($this->hasNode('count')) {
|
||||
$compiler
|
||||
->raw(', ')
|
||||
->subcompile($this->getNode('count'))
|
||||
;
|
||||
}
|
||||
|
||||
$compiler->raw(");\n");
|
||||
}
|
||||
|
||||
private function compileString(Node $body, ArrayExpression $vars, bool $ignoreStrictCheck = false): array
|
||||
{
|
||||
if ($body instanceof ConstantExpression) {
|
||||
$msg = $body->getAttribute('value');
|
||||
} elseif ($body instanceof TextNode) {
|
||||
$msg = $body->getAttribute('data');
|
||||
} else {
|
||||
return [$body, $vars];
|
||||
}
|
||||
|
||||
preg_match_all('/(?<!%)%([^%]+)%/', $msg, $matches);
|
||||
|
||||
foreach ($matches[1] as $var) {
|
||||
$key = new ConstantExpression('%'.$var.'%', $body->getTemplateLine());
|
||||
if (!$vars->hasElement($key)) {
|
||||
if ('count' === $var && $this->hasNode('count')) {
|
||||
$vars->addElement($this->getNode('count'), $key);
|
||||
} else {
|
||||
$varExpr = new NameExpression($var, $body->getTemplateLine());
|
||||
$varExpr->setAttribute('ignore_strict_check', $ignoreStrictCheck);
|
||||
$vars->addElement($varExpr, $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [new ConstantExpression(str_replace('%%', '%', trim($msg)), $body->getTemplateLine()), $vars];
|
||||
}
|
||||
}
|
103
vendor/symfony/twig-bridge/NodeVisitor/Scope.php
vendored
Normal file
103
vendor/symfony/twig-bridge/NodeVisitor/Scope.php
vendored
Normal file
@ -0,0 +1,103 @@
|
||||
<?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\NodeVisitor;
|
||||
|
||||
/**
|
||||
* @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
||||
*/
|
||||
class Scope
|
||||
{
|
||||
private $parent;
|
||||
private $data = [];
|
||||
private $left = false;
|
||||
|
||||
public function __construct(self $parent = null)
|
||||
{
|
||||
$this->parent = $parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new child scope.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function enter()
|
||||
{
|
||||
return new self($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes current scope and returns parent one.
|
||||
*
|
||||
* @return self|null
|
||||
*/
|
||||
public function leave()
|
||||
{
|
||||
$this->left = true;
|
||||
|
||||
return $this->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores data into current scope.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function set(string $key, $value)
|
||||
{
|
||||
if ($this->left) {
|
||||
throw new \LogicException('Left scope is not mutable.');
|
||||
}
|
||||
|
||||
$this->data[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a data is visible from current scope.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function has(string $key)
|
||||
{
|
||||
if (\array_key_exists($key, $this->data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (null === $this->parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->parent->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data visible from current scope.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(string $key, $default = null)
|
||||
{
|
||||
if (\array_key_exists($key, $this->data)) {
|
||||
return $this->data[$key];
|
||||
}
|
||||
|
||||
if (null === $this->parent) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->parent->get($key, $default);
|
||||
}
|
||||
}
|
128
vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php
vendored
Normal file
128
vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
<?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\NodeVisitor;
|
||||
|
||||
use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;
|
||||
use Symfony\Bridge\Twig\Node\TransNode;
|
||||
use Twig\Environment;
|
||||
use Twig\Node\BlockNode;
|
||||
use Twig\Node\Expression\ArrayExpression;
|
||||
use Twig\Node\Expression\AssignNameExpression;
|
||||
use Twig\Node\Expression\ConstantExpression;
|
||||
use Twig\Node\Expression\FilterExpression;
|
||||
use Twig\Node\Expression\NameExpression;
|
||||
use Twig\Node\ModuleNode;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Node\SetNode;
|
||||
use Twig\NodeVisitor\AbstractNodeVisitor;
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor
|
||||
{
|
||||
private $scope;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->scope = new Scope();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doEnterNode(Node $node, Environment $env): Node
|
||||
{
|
||||
if ($node instanceof BlockNode || $node instanceof ModuleNode) {
|
||||
$this->scope = $this->scope->enter();
|
||||
}
|
||||
|
||||
if ($node instanceof TransDefaultDomainNode) {
|
||||
if ($node->getNode('expr') instanceof ConstantExpression) {
|
||||
$this->scope->set('domain', $node->getNode('expr'));
|
||||
|
||||
return $node;
|
||||
} else {
|
||||
$var = $this->getVarName();
|
||||
$name = new AssignNameExpression($var, $node->getTemplateLine());
|
||||
$this->scope->set('domain', new NameExpression($var, $node->getTemplateLine()));
|
||||
|
||||
return new SetNode(false, new Node([$name]), new Node([$node->getNode('expr')]), $node->getTemplateLine());
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->scope->has('domain')) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof FilterExpression && 'trans' === $node->getNode('filter')->getAttribute('value')) {
|
||||
$arguments = $node->getNode('arguments');
|
||||
if ($this->isNamedArguments($arguments)) {
|
||||
if (!$arguments->hasNode('domain') && !$arguments->hasNode(1)) {
|
||||
$arguments->setNode('domain', $this->scope->get('domain'));
|
||||
}
|
||||
} elseif (!$arguments->hasNode(1)) {
|
||||
if (!$arguments->hasNode(0)) {
|
||||
$arguments->setNode(0, new ArrayExpression([], $node->getTemplateLine()));
|
||||
}
|
||||
|
||||
$arguments->setNode(1, $this->scope->get('domain'));
|
||||
}
|
||||
} elseif ($node instanceof TransNode) {
|
||||
if (!$node->hasNode('domain')) {
|
||||
$node->setNode('domain', $this->scope->get('domain'));
|
||||
}
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doLeaveNode(Node $node, Environment $env): ?Node
|
||||
{
|
||||
if ($node instanceof TransDefaultDomainNode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($node instanceof BlockNode || $node instanceof ModuleNode) {
|
||||
$this->scope = $this->scope->leave();
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return -10;
|
||||
}
|
||||
|
||||
private function isNamedArguments(Node $arguments): bool
|
||||
{
|
||||
foreach ($arguments as $name => $node) {
|
||||
if (!\is_int($name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getVarName(): string
|
||||
{
|
||||
return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
|
||||
}
|
||||
}
|
187
vendor/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php
vendored
Normal file
187
vendor/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
<?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\NodeVisitor;
|
||||
|
||||
use Symfony\Bridge\Twig\Node\TransNode;
|
||||
use Twig\Environment;
|
||||
use Twig\Node\Expression\Binary\ConcatBinary;
|
||||
use Twig\Node\Expression\ConstantExpression;
|
||||
use Twig\Node\Expression\FilterExpression;
|
||||
use Twig\Node\Expression\FunctionExpression;
|
||||
use Twig\Node\Node;
|
||||
use Twig\NodeVisitor\AbstractNodeVisitor;
|
||||
|
||||
/**
|
||||
* TranslationNodeVisitor extracts translation messages.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class TranslationNodeVisitor extends AbstractNodeVisitor
|
||||
{
|
||||
public const UNDEFINED_DOMAIN = '_undefined';
|
||||
|
||||
private $enabled = false;
|
||||
private $messages = [];
|
||||
|
||||
public function enable(): void
|
||||
{
|
||||
$this->enabled = true;
|
||||
$this->messages = [];
|
||||
}
|
||||
|
||||
public function disable(): void
|
||||
{
|
||||
$this->enabled = false;
|
||||
$this->messages = [];
|
||||
}
|
||||
|
||||
public function getMessages(): array
|
||||
{
|
||||
return $this->messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doEnterNode(Node $node, Environment $env): Node
|
||||
{
|
||||
if (!$this->enabled) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if (
|
||||
$node instanceof FilterExpression &&
|
||||
'trans' === $node->getNode('filter')->getAttribute('value') &&
|
||||
$node->getNode('node') instanceof ConstantExpression
|
||||
) {
|
||||
// extract constant nodes with a trans filter
|
||||
$this->messages[] = [
|
||||
$node->getNode('node')->getAttribute('value'),
|
||||
$this->getReadDomainFromArguments($node->getNode('arguments'), 1),
|
||||
];
|
||||
} elseif (
|
||||
$node instanceof FunctionExpression &&
|
||||
't' === $node->getAttribute('name')
|
||||
) {
|
||||
$nodeArguments = $node->getNode('arguments');
|
||||
|
||||
if ($nodeArguments->getIterator()->current() instanceof ConstantExpression) {
|
||||
$this->messages[] = [
|
||||
$this->getReadMessageFromArguments($nodeArguments, 0),
|
||||
$this->getReadDomainFromArguments($nodeArguments, 2),
|
||||
];
|
||||
}
|
||||
} elseif ($node instanceof TransNode) {
|
||||
// extract trans nodes
|
||||
$this->messages[] = [
|
||||
$node->getNode('body')->getAttribute('data'),
|
||||
$node->hasNode('domain') ? $this->getReadDomainFromNode($node->getNode('domain')) : null,
|
||||
];
|
||||
} elseif (
|
||||
$node instanceof FilterExpression &&
|
||||
'trans' === $node->getNode('filter')->getAttribute('value') &&
|
||||
$node->getNode('node') instanceof ConcatBinary &&
|
||||
$message = $this->getConcatValueFromNode($node->getNode('node'), null)
|
||||
) {
|
||||
$this->messages[] = [
|
||||
$message,
|
||||
$this->getReadDomainFromArguments($node->getNode('arguments'), 1),
|
||||
];
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doLeaveNode(Node $node, Environment $env): ?Node
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function getReadMessageFromArguments(Node $arguments, int $index): ?string
|
||||
{
|
||||
if ($arguments->hasNode('message')) {
|
||||
$argument = $arguments->getNode('message');
|
||||
} elseif ($arguments->hasNode($index)) {
|
||||
$argument = $arguments->getNode($index);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getReadMessageFromNode($argument);
|
||||
}
|
||||
|
||||
private function getReadMessageFromNode(Node $node): ?string
|
||||
{
|
||||
if ($node instanceof ConstantExpression) {
|
||||
return $node->getAttribute('value');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getReadDomainFromArguments(Node $arguments, int $index): ?string
|
||||
{
|
||||
if ($arguments->hasNode('domain')) {
|
||||
$argument = $arguments->getNode('domain');
|
||||
} elseif ($arguments->hasNode($index)) {
|
||||
$argument = $arguments->getNode($index);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->getReadDomainFromNode($argument);
|
||||
}
|
||||
|
||||
private function getReadDomainFromNode(Node $node): ?string
|
||||
{
|
||||
if ($node instanceof ConstantExpression) {
|
||||
return $node->getAttribute('value');
|
||||
}
|
||||
|
||||
return self::UNDEFINED_DOMAIN;
|
||||
}
|
||||
|
||||
private function getConcatValueFromNode(Node $node, ?string $value): ?string
|
||||
{
|
||||
if ($node instanceof ConcatBinary) {
|
||||
foreach ($node as $nextNode) {
|
||||
if ($nextNode instanceof ConcatBinary) {
|
||||
$nextValue = $this->getConcatValueFromNode($nextNode, $value);
|
||||
if (null === $nextValue) {
|
||||
return null;
|
||||
}
|
||||
$value .= $nextValue;
|
||||
} elseif ($nextNode instanceof ConstantExpression) {
|
||||
$value .= $nextNode->getAttribute('value');
|
||||
} else {
|
||||
// this is a node we cannot process (variable, or translation in translation)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} elseif ($node instanceof ConstantExpression) {
|
||||
$value .= $node->getAttribute('value');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
13
vendor/symfony/twig-bridge/README.md
vendored
Normal file
13
vendor/symfony/twig-bridge/README.md
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
Twig Bridge
|
||||
===========
|
||||
|
||||
The Twig bridge provides integration for [Twig](https://twig.symfony.com/) with
|
||||
various Symfony components.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
|
||||
* [Report issues](https://github.com/symfony/symfony/issues) and
|
||||
[send Pull Requests](https://github.com/symfony/symfony/pulls)
|
||||
in the [main Symfony repository](https://github.com/symfony/symfony)
|
1
vendor/symfony/twig-bridge/Resources/views/Email/default/notification/body.html.twig
vendored
Normal file
1
vendor/symfony/twig-bridge/Resources/views/Email/default/notification/body.html.twig
vendored
Normal file
@ -0,0 +1 @@
|
||||
{% extends "@email/zurb_2/notification/body.html.twig" %}
|
1
vendor/symfony/twig-bridge/Resources/views/Email/default/notification/body.txt.twig
vendored
Normal file
1
vendor/symfony/twig-bridge/Resources/views/Email/default/notification/body.txt.twig
vendored
Normal file
@ -0,0 +1 @@
|
||||
{% extends "@email/zurb_2/notification/body.txt.twig" %}
|
1667
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/main.css
vendored
Normal file
1667
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/main.css
vendored
Normal file
@ -0,0 +1,1667 @@
|
||||
/*
|
||||
* Copyright (c) 2017 ZURB, inc. -- MIT License
|
||||
*
|
||||
* https://raw.githubusercontent.com/foundation/foundation-emails/v2.2.1/dist/foundation-emails.css
|
||||
*/
|
||||
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#outlook a {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 100% !important;
|
||||
min-width: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
margin: 0;
|
||||
Margin: 0;
|
||||
padding: 0;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ExternalClass,
|
||||
.ExternalClass p,
|
||||
.ExternalClass span,
|
||||
.ExternalClass font,
|
||||
.ExternalClass td,
|
||||
.ExternalClass div {
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
#backgroundTable {
|
||||
margin: 0;
|
||||
Margin: 0;
|
||||
padding: 0;
|
||||
width: 100% !important;
|
||||
line-height: 100% !important;
|
||||
}
|
||||
|
||||
img {
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
-ms-interpolation-mode: bicubic;
|
||||
width: auto;
|
||||
max-width: 100%;
|
||||
clear: both;
|
||||
display: block;
|
||||
}
|
||||
|
||||
center {
|
||||
width: 100%;
|
||||
min-width: 580px;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 0 10px;
|
||||
Margin: 0 0 0 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td {
|
||||
word-wrap: break-word;
|
||||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
hyphens: auto;
|
||||
border-collapse: collapse !important;
|
||||
}
|
||||
|
||||
table,
|
||||
tr,
|
||||
td {
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@media only screen {
|
||||
html {
|
||||
min-height: 100%;
|
||||
background: #f3f3f3;
|
||||
}
|
||||
}
|
||||
|
||||
table.body {
|
||||
background: #f3f3f3;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.container {
|
||||
background: #fefefe;
|
||||
width: 580px;
|
||||
margin: 0 auto;
|
||||
Margin: 0 auto;
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
table.row {
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
table.spacer {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.spacer td {
|
||||
mso-line-height-rule: exactly;
|
||||
}
|
||||
|
||||
table.container table.row {
|
||||
display: table;
|
||||
}
|
||||
|
||||
td.columns,
|
||||
td.column,
|
||||
th.columns,
|
||||
th.column {
|
||||
margin: 0 auto;
|
||||
Margin: 0 auto;
|
||||
padding-left: 16px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
td.columns .column,
|
||||
td.columns .columns,
|
||||
td.column .column,
|
||||
td.column .columns,
|
||||
th.columns .column,
|
||||
th.columns .columns,
|
||||
th.column .column,
|
||||
th.column .columns {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
td.columns .column center,
|
||||
td.columns .columns center,
|
||||
td.column .column center,
|
||||
td.column .columns center,
|
||||
th.columns .column center,
|
||||
th.columns .columns center,
|
||||
th.column .column center,
|
||||
th.column .columns center {
|
||||
min-width: none !important;
|
||||
}
|
||||
|
||||
td.columns.last,
|
||||
td.column.last,
|
||||
th.columns.last,
|
||||
th.column.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
td.columns table:not(.button),
|
||||
td.column table:not(.button),
|
||||
th.columns table:not(.button),
|
||||
th.column table:not(.button) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td.large-1,
|
||||
th.large-1 {
|
||||
width: 32.33333px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-1.first,
|
||||
th.large-1.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-1.last,
|
||||
th.large-1.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-1,
|
||||
.collapse>tbody>tr>th.large-1 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 48.33333px;
|
||||
}
|
||||
|
||||
.collapse td.large-1.first,
|
||||
.collapse th.large-1.first,
|
||||
.collapse td.large-1.last,
|
||||
.collapse th.large-1.last {
|
||||
width: 56.33333px;
|
||||
}
|
||||
|
||||
td.large-1 center,
|
||||
th.large-1 center {
|
||||
min-width: 0.33333px;
|
||||
}
|
||||
|
||||
.body .columns td.large-1,
|
||||
.body .column td.large-1,
|
||||
.body .columns th.large-1,
|
||||
.body .column th.large-1 {
|
||||
width: 8.33333%;
|
||||
}
|
||||
|
||||
td.large-2,
|
||||
th.large-2 {
|
||||
width: 80.66667px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-2.first,
|
||||
th.large-2.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-2.last,
|
||||
th.large-2.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-2,
|
||||
.collapse>tbody>tr>th.large-2 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 96.66667px;
|
||||
}
|
||||
|
||||
.collapse td.large-2.first,
|
||||
.collapse th.large-2.first,
|
||||
.collapse td.large-2.last,
|
||||
.collapse th.large-2.last {
|
||||
width: 104.66667px;
|
||||
}
|
||||
|
||||
td.large-2 center,
|
||||
th.large-2 center {
|
||||
min-width: 48.66667px;
|
||||
}
|
||||
|
||||
.body .columns td.large-2,
|
||||
.body .column td.large-2,
|
||||
.body .columns th.large-2,
|
||||
.body .column th.large-2 {
|
||||
width: 16.66667%;
|
||||
}
|
||||
|
||||
td.large-3,
|
||||
th.large-3 {
|
||||
width: 129px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-3.first,
|
||||
th.large-3.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-3.last,
|
||||
th.large-3.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-3,
|
||||
.collapse>tbody>tr>th.large-3 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 145px;
|
||||
}
|
||||
|
||||
.collapse td.large-3.first,
|
||||
.collapse th.large-3.first,
|
||||
.collapse td.large-3.last,
|
||||
.collapse th.large-3.last {
|
||||
width: 153px;
|
||||
}
|
||||
|
||||
td.large-3 center,
|
||||
th.large-3 center {
|
||||
min-width: 97px;
|
||||
}
|
||||
|
||||
.body .columns td.large-3,
|
||||
.body .column td.large-3,
|
||||
.body .columns th.large-3,
|
||||
.body .column th.large-3 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
td.large-4,
|
||||
th.large-4 {
|
||||
width: 177.33333px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-4.first,
|
||||
th.large-4.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-4.last,
|
||||
th.large-4.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-4,
|
||||
.collapse>tbody>tr>th.large-4 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 193.33333px;
|
||||
}
|
||||
|
||||
.collapse td.large-4.first,
|
||||
.collapse th.large-4.first,
|
||||
.collapse td.large-4.last,
|
||||
.collapse th.large-4.last {
|
||||
width: 201.33333px;
|
||||
}
|
||||
|
||||
td.large-4 center,
|
||||
th.large-4 center {
|
||||
min-width: 145.33333px;
|
||||
}
|
||||
|
||||
.body .columns td.large-4,
|
||||
.body .column td.large-4,
|
||||
.body .columns th.large-4,
|
||||
.body .column th.large-4 {
|
||||
width: 33.33333%;
|
||||
}
|
||||
|
||||
td.large-5,
|
||||
th.large-5 {
|
||||
width: 225.66667px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-5.first,
|
||||
th.large-5.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-5.last,
|
||||
th.large-5.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-5,
|
||||
.collapse>tbody>tr>th.large-5 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 241.66667px;
|
||||
}
|
||||
|
||||
.collapse td.large-5.first,
|
||||
.collapse th.large-5.first,
|
||||
.collapse td.large-5.last,
|
||||
.collapse th.large-5.last {
|
||||
width: 249.66667px;
|
||||
}
|
||||
|
||||
td.large-5 center,
|
||||
th.large-5 center {
|
||||
min-width: 193.66667px;
|
||||
}
|
||||
|
||||
.body .columns td.large-5,
|
||||
.body .column td.large-5,
|
||||
.body .columns th.large-5,
|
||||
.body .column th.large-5 {
|
||||
width: 41.66667%;
|
||||
}
|
||||
|
||||
td.large-6,
|
||||
th.large-6 {
|
||||
width: 274px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-6.first,
|
||||
th.large-6.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-6.last,
|
||||
th.large-6.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-6,
|
||||
.collapse>tbody>tr>th.large-6 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 290px;
|
||||
}
|
||||
|
||||
.collapse td.large-6.first,
|
||||
.collapse th.large-6.first,
|
||||
.collapse td.large-6.last,
|
||||
.collapse th.large-6.last {
|
||||
width: 298px;
|
||||
}
|
||||
|
||||
td.large-6 center,
|
||||
th.large-6 center {
|
||||
min-width: 242px;
|
||||
}
|
||||
|
||||
.body .columns td.large-6,
|
||||
.body .column td.large-6,
|
||||
.body .columns th.large-6,
|
||||
.body .column th.large-6 {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
td.large-7,
|
||||
th.large-7 {
|
||||
width: 322.33333px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-7.first,
|
||||
th.large-7.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-7.last,
|
||||
th.large-7.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-7,
|
||||
.collapse>tbody>tr>th.large-7 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 338.33333px;
|
||||
}
|
||||
|
||||
.collapse td.large-7.first,
|
||||
.collapse th.large-7.first,
|
||||
.collapse td.large-7.last,
|
||||
.collapse th.large-7.last {
|
||||
width: 346.33333px;
|
||||
}
|
||||
|
||||
td.large-7 center,
|
||||
th.large-7 center {
|
||||
min-width: 290.33333px;
|
||||
}
|
||||
|
||||
.body .columns td.large-7,
|
||||
.body .column td.large-7,
|
||||
.body .columns th.large-7,
|
||||
.body .column th.large-7 {
|
||||
width: 58.33333%;
|
||||
}
|
||||
|
||||
td.large-8,
|
||||
th.large-8 {
|
||||
width: 370.66667px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-8.first,
|
||||
th.large-8.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-8.last,
|
||||
th.large-8.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-8,
|
||||
.collapse>tbody>tr>th.large-8 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 386.66667px;
|
||||
}
|
||||
|
||||
.collapse td.large-8.first,
|
||||
.collapse th.large-8.first,
|
||||
.collapse td.large-8.last,
|
||||
.collapse th.large-8.last {
|
||||
width: 394.66667px;
|
||||
}
|
||||
|
||||
td.large-8 center,
|
||||
th.large-8 center {
|
||||
min-width: 338.66667px;
|
||||
}
|
||||
|
||||
.body .columns td.large-8,
|
||||
.body .column td.large-8,
|
||||
.body .columns th.large-8,
|
||||
.body .column th.large-8 {
|
||||
width: 66.66667%;
|
||||
}
|
||||
|
||||
td.large-9,
|
||||
th.large-9 {
|
||||
width: 419px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-9.first,
|
||||
th.large-9.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-9.last,
|
||||
th.large-9.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-9,
|
||||
.collapse>tbody>tr>th.large-9 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 435px;
|
||||
}
|
||||
|
||||
.collapse td.large-9.first,
|
||||
.collapse th.large-9.first,
|
||||
.collapse td.large-9.last,
|
||||
.collapse th.large-9.last {
|
||||
width: 443px;
|
||||
}
|
||||
|
||||
td.large-9 center,
|
||||
th.large-9 center {
|
||||
min-width: 387px;
|
||||
}
|
||||
|
||||
.body .columns td.large-9,
|
||||
.body .column td.large-9,
|
||||
.body .columns th.large-9,
|
||||
.body .column th.large-9 {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
td.large-10,
|
||||
th.large-10 {
|
||||
width: 467.33333px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-10.first,
|
||||
th.large-10.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-10.last,
|
||||
th.large-10.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-10,
|
||||
.collapse>tbody>tr>th.large-10 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 483.33333px;
|
||||
}
|
||||
|
||||
.collapse td.large-10.first,
|
||||
.collapse th.large-10.first,
|
||||
.collapse td.large-10.last,
|
||||
.collapse th.large-10.last {
|
||||
width: 491.33333px;
|
||||
}
|
||||
|
||||
td.large-10 center,
|
||||
th.large-10 center {
|
||||
min-width: 435.33333px;
|
||||
}
|
||||
|
||||
.body .columns td.large-10,
|
||||
.body .column td.large-10,
|
||||
.body .columns th.large-10,
|
||||
.body .column th.large-10 {
|
||||
width: 83.33333%;
|
||||
}
|
||||
|
||||
td.large-11,
|
||||
th.large-11 {
|
||||
width: 515.66667px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-11.first,
|
||||
th.large-11.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-11.last,
|
||||
th.large-11.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-11,
|
||||
.collapse>tbody>tr>th.large-11 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 531.66667px;
|
||||
}
|
||||
|
||||
.collapse td.large-11.first,
|
||||
.collapse th.large-11.first,
|
||||
.collapse td.large-11.last,
|
||||
.collapse th.large-11.last {
|
||||
width: 539.66667px;
|
||||
}
|
||||
|
||||
td.large-11 center,
|
||||
th.large-11 center {
|
||||
min-width: 483.66667px;
|
||||
}
|
||||
|
||||
.body .columns td.large-11,
|
||||
.body .column td.large-11,
|
||||
.body .columns th.large-11,
|
||||
.body .column th.large-11 {
|
||||
width: 91.66667%;
|
||||
}
|
||||
|
||||
td.large-12,
|
||||
th.large-12 {
|
||||
width: 564px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
td.large-12.first,
|
||||
th.large-12.first {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
td.large-12.last,
|
||||
th.large-12.last {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
.collapse>tbody>tr>td.large-12,
|
||||
.collapse>tbody>tr>th.large-12 {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
width: 580px;
|
||||
}
|
||||
|
||||
.collapse td.large-12.first,
|
||||
.collapse th.large-12.first,
|
||||
.collapse td.large-12.last,
|
||||
.collapse th.large-12.last {
|
||||
width: 588px;
|
||||
}
|
||||
|
||||
td.large-12 center,
|
||||
th.large-12 center {
|
||||
min-width: 532px;
|
||||
}
|
||||
|
||||
.body .columns td.large-12,
|
||||
.body .column td.large-12,
|
||||
.body .columns th.large-12,
|
||||
.body .column th.large-12 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td.large-offset-1,
|
||||
td.large-offset-1.first,
|
||||
td.large-offset-1.last,
|
||||
th.large-offset-1,
|
||||
th.large-offset-1.first,
|
||||
th.large-offset-1.last {
|
||||
padding-left: 64.33333px;
|
||||
}
|
||||
|
||||
td.large-offset-2,
|
||||
td.large-offset-2.first,
|
||||
td.large-offset-2.last,
|
||||
th.large-offset-2,
|
||||
th.large-offset-2.first,
|
||||
th.large-offset-2.last {
|
||||
padding-left: 112.66667px;
|
||||
}
|
||||
|
||||
td.large-offset-3,
|
||||
td.large-offset-3.first,
|
||||
td.large-offset-3.last,
|
||||
th.large-offset-3,
|
||||
th.large-offset-3.first,
|
||||
th.large-offset-3.last {
|
||||
padding-left: 161px;
|
||||
}
|
||||
|
||||
td.large-offset-4,
|
||||
td.large-offset-4.first,
|
||||
td.large-offset-4.last,
|
||||
th.large-offset-4,
|
||||
th.large-offset-4.first,
|
||||
th.large-offset-4.last {
|
||||
padding-left: 209.33333px;
|
||||
}
|
||||
|
||||
td.large-offset-5,
|
||||
td.large-offset-5.first,
|
||||
td.large-offset-5.last,
|
||||
th.large-offset-5,
|
||||
th.large-offset-5.first,
|
||||
th.large-offset-5.last {
|
||||
padding-left: 257.66667px;
|
||||
}
|
||||
|
||||
td.large-offset-6,
|
||||
td.large-offset-6.first,
|
||||
td.large-offset-6.last,
|
||||
th.large-offset-6,
|
||||
th.large-offset-6.first,
|
||||
th.large-offset-6.last {
|
||||
padding-left: 306px;
|
||||
}
|
||||
|
||||
td.large-offset-7,
|
||||
td.large-offset-7.first,
|
||||
td.large-offset-7.last,
|
||||
th.large-offset-7,
|
||||
th.large-offset-7.first,
|
||||
th.large-offset-7.last {
|
||||
padding-left: 354.33333px;
|
||||
}
|
||||
|
||||
td.large-offset-8,
|
||||
td.large-offset-8.first,
|
||||
td.large-offset-8.last,
|
||||
th.large-offset-8,
|
||||
th.large-offset-8.first,
|
||||
th.large-offset-8.last {
|
||||
padding-left: 402.66667px;
|
||||
}
|
||||
|
||||
td.large-offset-9,
|
||||
td.large-offset-9.first,
|
||||
td.large-offset-9.last,
|
||||
th.large-offset-9,
|
||||
th.large-offset-9.first,
|
||||
th.large-offset-9.last {
|
||||
padding-left: 451px;
|
||||
}
|
||||
|
||||
td.large-offset-10,
|
||||
td.large-offset-10.first,
|
||||
td.large-offset-10.last,
|
||||
th.large-offset-10,
|
||||
th.large-offset-10.first,
|
||||
th.large-offset-10.last {
|
||||
padding-left: 499.33333px;
|
||||
}
|
||||
|
||||
td.large-offset-11,
|
||||
td.large-offset-11.first,
|
||||
td.large-offset-11.last,
|
||||
th.large-offset-11,
|
||||
th.large-offset-11.first,
|
||||
th.large-offset-11.last {
|
||||
padding-left: 547.66667px;
|
||||
}
|
||||
|
||||
td.expander,
|
||||
th.expander {
|
||||
visibility: hidden;
|
||||
width: 0;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
table.container.radius {
|
||||
border-radius: 0;
|
||||
border-collapse: separate;
|
||||
}
|
||||
|
||||
.block-grid {
|
||||
width: 100%;
|
||||
max-width: 580px;
|
||||
}
|
||||
|
||||
.block-grid td {
|
||||
display: inline-block;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.up-2 td {
|
||||
width: 274px !important;
|
||||
}
|
||||
|
||||
.up-3 td {
|
||||
width: 177px !important;
|
||||
}
|
||||
|
||||
.up-4 td {
|
||||
width: 129px !important;
|
||||
}
|
||||
|
||||
.up-5 td {
|
||||
width: 100px !important;
|
||||
}
|
||||
|
||||
.up-6 td {
|
||||
width: 80px !important;
|
||||
}
|
||||
|
||||
.up-7 td {
|
||||
width: 66px !important;
|
||||
}
|
||||
|
||||
.up-8 td {
|
||||
width: 56px !important;
|
||||
}
|
||||
|
||||
table.text-center,
|
||||
th.text-center,
|
||||
td.text-center,
|
||||
h1.text-center,
|
||||
h2.text-center,
|
||||
h3.text-center,
|
||||
h4.text-center,
|
||||
h5.text-center,
|
||||
h6.text-center,
|
||||
p.text-center,
|
||||
span.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table.text-left,
|
||||
th.text-left,
|
||||
td.text-left,
|
||||
h1.text-left,
|
||||
h2.text-left,
|
||||
h3.text-left,
|
||||
h4.text-left,
|
||||
h5.text-left,
|
||||
h6.text-left,
|
||||
p.text-left,
|
||||
span.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table.text-right,
|
||||
th.text-right,
|
||||
td.text-right,
|
||||
h1.text-right,
|
||||
h2.text-right,
|
||||
h3.text-right,
|
||||
h4.text-right,
|
||||
h5.text-right,
|
||||
h6.text-right,
|
||||
p.text-right,
|
||||
span.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
span.text-center {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 596px) {
|
||||
.small-float-center {
|
||||
margin: 0 auto !important;
|
||||
float: none !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
.small-text-center {
|
||||
text-align: center !important;
|
||||
}
|
||||
.small-text-left {
|
||||
text-align: left !important;
|
||||
}
|
||||
.small-text-right {
|
||||
text-align: right !important;
|
||||
}
|
||||
}
|
||||
|
||||
img.float-left {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
img.float-right {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
img.float-center,
|
||||
img.text-center {
|
||||
margin: 0 auto;
|
||||
Margin: 0 auto;
|
||||
float: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
table.float-center,
|
||||
td.float-center,
|
||||
th.float-center {
|
||||
margin: 0 auto;
|
||||
Margin: 0 auto;
|
||||
float: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hide-for-large {
|
||||
display: none !important;
|
||||
mso-hide: all;
|
||||
overflow: hidden;
|
||||
max-height: 0;
|
||||
font-size: 0;
|
||||
width: 0;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 596px) {
|
||||
.hide-for-large {
|
||||
display: block !important;
|
||||
width: auto !important;
|
||||
overflow: visible !important;
|
||||
max-height: none !important;
|
||||
font-size: inherit !important;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
}
|
||||
|
||||
table.body table.container .hide-for-large * {
|
||||
mso-hide: all;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 596px) {
|
||||
table.body table.container .hide-for-large,
|
||||
table.body table.container .row.hide-for-large {
|
||||
display: table !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 596px) {
|
||||
table.body table.container .callout-inner.hide-for-large {
|
||||
display: table-cell !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 596px) {
|
||||
table.body table.container .show-for-large {
|
||||
display: none !important;
|
||||
width: 0;
|
||||
mso-hide: all;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
body,
|
||||
table.body,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6,
|
||||
p,
|
||||
td,
|
||||
th,
|
||||
a {
|
||||
color: #0a0a0a;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
Margin: 0;
|
||||
text-align: left;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
color: inherit;
|
||||
word-wrap: normal;
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-weight: normal;
|
||||
margin-bottom: 10px;
|
||||
Margin-bottom: 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 34px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
body,
|
||||
table.body,
|
||||
p,
|
||||
td,
|
||||
th {
|
||||
font-size: 16px;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 10px;
|
||||
Margin-bottom: 10px;
|
||||
}
|
||||
|
||||
p.lead {
|
||||
font-size: 20px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
p.subheader {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 8px;
|
||||
Margin-top: 4px;
|
||||
Margin-bottom: 8px;
|
||||
font-weight: normal;
|
||||
line-height: 1.4;
|
||||
color: #8a8a8a;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
color: #cacaca;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #2199e8;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #147dc2;
|
||||
}
|
||||
|
||||
a:active {
|
||||
color: #147dc2;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: #2199e8;
|
||||
}
|
||||
|
||||
h1 a,
|
||||
h1 a:visited,
|
||||
h2 a,
|
||||
h2 a:visited,
|
||||
h3 a,
|
||||
h3 a:visited,
|
||||
h4 a,
|
||||
h4 a:visited,
|
||||
h5 a,
|
||||
h5 a:visited,
|
||||
h6 a,
|
||||
h6 a:visited {
|
||||
color: #2199e8;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #f3f3f3;
|
||||
margin: 30px 0;
|
||||
Margin: 30px 0;
|
||||
}
|
||||
|
||||
pre code {
|
||||
color: #cacaca;
|
||||
}
|
||||
|
||||
pre code span.callout {
|
||||
color: #8a8a8a;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre code span.callout-strong {
|
||||
color: #ff6908;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.hr {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.hr th {
|
||||
height: 0;
|
||||
max-width: 580px;
|
||||
border-top: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #0a0a0a;
|
||||
border-left: 0;
|
||||
margin: 20px auto;
|
||||
Margin: 20px auto;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.stat {
|
||||
font-size: 40px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
p+.stat {
|
||||
margin-top: -16px;
|
||||
Margin-top: -16px;
|
||||
}
|
||||
|
||||
span.preheader {
|
||||
display: none !important;
|
||||
visibility: hidden;
|
||||
mso-hide: all !important;
|
||||
font-size: 1px;
|
||||
color: #f3f3f3;
|
||||
line-height: 1px;
|
||||
max-height: 0px;
|
||||
max-width: 0px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
table.button {
|
||||
width: auto;
|
||||
margin: 0 0 16px 0;
|
||||
Margin: 0 0 16px 0;
|
||||
}
|
||||
|
||||
table.button table td {
|
||||
text-align: left;
|
||||
color: #fefefe;
|
||||
background: #2199e8;
|
||||
border: 2px solid #2199e8;
|
||||
}
|
||||
|
||||
table.button table td a {
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #fefefe;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
padding: 8px 16px 8px 16px;
|
||||
border: 0 solid #2199e8;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
table.button.radius table td {
|
||||
border-radius: 3px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
table.button.rounded table td {
|
||||
border-radius: 500px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
table.button:hover table tr td a,
|
||||
table.button:active table tr td a,
|
||||
table.button table tr td a:visited,
|
||||
table.button.tiny:hover table tr td a,
|
||||
table.button.tiny:active table tr td a,
|
||||
table.button.tiny table tr td a:visited,
|
||||
table.button.small:hover table tr td a,
|
||||
table.button.small:active table tr td a,
|
||||
table.button.small table tr td a:visited,
|
||||
table.button.large:hover table tr td a,
|
||||
table.button.large:active table tr td a,
|
||||
table.button.large table tr td a:visited {
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
table.button.tiny table td,
|
||||
table.button.tiny table a {
|
||||
padding: 4px 8px 4px 8px;
|
||||
}
|
||||
|
||||
table.button.tiny table a {
|
||||
font-size: 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
table.button.small table td,
|
||||
table.button.small table a {
|
||||
padding: 5px 10px 5px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
table.button.large table a {
|
||||
padding: 10px 20px 10px 20px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
table.button.expand,
|
||||
table.button.expanded {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
table.button.expand table,
|
||||
table.button.expanded table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.button.expand table a,
|
||||
table.button.expanded table a {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
table.button.expand center,
|
||||
table.button.expanded center {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
table.button:hover table td,
|
||||
table.button:visited table td,
|
||||
table.button:active table td {
|
||||
background: #147dc2;
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
table.button:hover table a,
|
||||
table.button:visited table a,
|
||||
table.button:active table a {
|
||||
border: 0 solid #147dc2;
|
||||
}
|
||||
|
||||
table.button.secondary table td {
|
||||
background: #777777;
|
||||
color: #fefefe;
|
||||
border: 0px solid #777777;
|
||||
}
|
||||
|
||||
table.button.secondary table a {
|
||||
color: #fefefe;
|
||||
border: 0 solid #777777;
|
||||
}
|
||||
|
||||
table.button.secondary:hover table td {
|
||||
background: #919191;
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
table.button.secondary:hover table a {
|
||||
border: 0 solid #919191;
|
||||
}
|
||||
|
||||
table.button.secondary:hover table td a {
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
table.button.secondary:active table td a {
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
table.button.secondary table td a:visited {
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
table.button.success table td {
|
||||
background: #3adb76;
|
||||
border: 0px solid #3adb76;
|
||||
}
|
||||
|
||||
table.button.success table a {
|
||||
border: 0 solid #3adb76;
|
||||
}
|
||||
|
||||
table.button.success:hover table td {
|
||||
background: #23bf5d;
|
||||
}
|
||||
|
||||
table.button.success:hover table a {
|
||||
border: 0 solid #23bf5d;
|
||||
}
|
||||
|
||||
table.button.alert table td {
|
||||
background: #ec5840;
|
||||
border: 0px solid #ec5840;
|
||||
}
|
||||
|
||||
table.button.alert table a {
|
||||
border: 0 solid #ec5840;
|
||||
}
|
||||
|
||||
table.button.alert:hover table td {
|
||||
background: #e23317;
|
||||
}
|
||||
|
||||
table.button.alert:hover table a {
|
||||
border: 0 solid #e23317;
|
||||
}
|
||||
|
||||
table.button.warning table td {
|
||||
background: #ffae00;
|
||||
border: 0px solid #ffae00;
|
||||
}
|
||||
|
||||
table.button.warning table a {
|
||||
border: 0px solid #ffae00;
|
||||
}
|
||||
|
||||
table.button.warning:hover table td {
|
||||
background: #cc8b00;
|
||||
}
|
||||
|
||||
table.button.warning:hover table a {
|
||||
border: 0px solid #cc8b00;
|
||||
}
|
||||
|
||||
table.callout {
|
||||
margin-bottom: 16px;
|
||||
Margin-bottom: 16px;
|
||||
}
|
||||
|
||||
th.callout-inner {
|
||||
width: 100%;
|
||||
border: 1px solid #cbcbcb;
|
||||
padding: 10px;
|
||||
background: #fefefe;
|
||||
}
|
||||
|
||||
th.callout-inner.primary {
|
||||
background: #def0fc;
|
||||
border: 1px solid #444444;
|
||||
color: #0a0a0a;
|
||||
}
|
||||
|
||||
th.callout-inner.secondary {
|
||||
background: #ebebeb;
|
||||
border: 1px solid #444444;
|
||||
color: #0a0a0a;
|
||||
}
|
||||
|
||||
th.callout-inner.success {
|
||||
background: #e1faea;
|
||||
border: 1px solid #1b9448;
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
th.callout-inner.warning {
|
||||
background: #fff3d9;
|
||||
border: 1px solid #996800;
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
th.callout-inner.alert {
|
||||
background: #fce6e2;
|
||||
border: 1px solid #b42912;
|
||||
color: #fefefe;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
border: solid 4px #fefefe;
|
||||
box-shadow: 0 0 0 1px rgba(10, 10, 10, 0.2);
|
||||
display: inline-block;
|
||||
line-height: 0;
|
||||
max-width: 100%;
|
||||
transition: box-shadow 200ms ease-out;
|
||||
border-radius: 3px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.thumbnail:hover,
|
||||
.thumbnail:focus {
|
||||
box-shadow: 0 0 6px 1px rgba(33, 153, 232, 0.5);
|
||||
}
|
||||
|
||||
table.menu {
|
||||
width: 580px;
|
||||
}
|
||||
|
||||
table.menu td.menu-item,
|
||||
table.menu th.menu-item {
|
||||
padding: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
table.menu td.menu-item a,
|
||||
table.menu th.menu-item a {
|
||||
color: #2199e8;
|
||||
}
|
||||
|
||||
table.menu.vertical td.menu-item,
|
||||
table.menu.vertical th.menu-item {
|
||||
padding: 10px;
|
||||
padding-right: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.menu.vertical td.menu-item a,
|
||||
table.menu.vertical th.menu-item a {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.menu.vertical td.menu-item table.menu.vertical td.menu-item,
|
||||
table.menu.vertical td.menu-item table.menu.vertical th.menu-item,
|
||||
table.menu.vertical th.menu-item table.menu.vertical td.menu-item,
|
||||
table.menu.vertical th.menu-item table.menu.vertical th.menu-item {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
table.menu.text-center a {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.menu[align="center"] {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
body.outlook p {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 596px) {
|
||||
table.body img {
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
table.body center {
|
||||
min-width: 0 !important;
|
||||
}
|
||||
table.body .container {
|
||||
width: 95% !important;
|
||||
}
|
||||
table.body .columns,
|
||||
table.body .column {
|
||||
height: auto !important;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
padding-left: 16px !important;
|
||||
padding-right: 16px !important;
|
||||
}
|
||||
table.body .columns .column,
|
||||
table.body .columns .columns,
|
||||
table.body .column .column,
|
||||
table.body .column .columns {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
table.body .collapse .columns,
|
||||
table.body .collapse .column {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
td.small-1,
|
||||
th.small-1 {
|
||||
display: inline-block !important;
|
||||
width: 8.33333% !important;
|
||||
}
|
||||
td.small-2,
|
||||
th.small-2 {
|
||||
display: inline-block !important;
|
||||
width: 16.66667% !important;
|
||||
}
|
||||
td.small-3,
|
||||
th.small-3 {
|
||||
display: inline-block !important;
|
||||
width: 25% !important;
|
||||
}
|
||||
td.small-4,
|
||||
th.small-4 {
|
||||
display: inline-block !important;
|
||||
width: 33.33333% !important;
|
||||
}
|
||||
td.small-5,
|
||||
th.small-5 {
|
||||
display: inline-block !important;
|
||||
width: 41.66667% !important;
|
||||
}
|
||||
td.small-6,
|
||||
th.small-6 {
|
||||
display: inline-block !important;
|
||||
width: 50% !important;
|
||||
}
|
||||
td.small-7,
|
||||
th.small-7 {
|
||||
display: inline-block !important;
|
||||
width: 58.33333% !important;
|
||||
}
|
||||
td.small-8,
|
||||
th.small-8 {
|
||||
display: inline-block !important;
|
||||
width: 66.66667% !important;
|
||||
}
|
||||
td.small-9,
|
||||
th.small-9 {
|
||||
display: inline-block !important;
|
||||
width: 75% !important;
|
||||
}
|
||||
td.small-10,
|
||||
th.small-10 {
|
||||
display: inline-block !important;
|
||||
width: 83.33333% !important;
|
||||
}
|
||||
td.small-11,
|
||||
th.small-11 {
|
||||
display: inline-block !important;
|
||||
width: 91.66667% !important;
|
||||
}
|
||||
td.small-12,
|
||||
th.small-12 {
|
||||
display: inline-block !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.columns td.small-12,
|
||||
.column td.small-12,
|
||||
.columns th.small-12,
|
||||
.column th.small-12 {
|
||||
display: block !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
table.body td.small-offset-1,
|
||||
table.body th.small-offset-1 {
|
||||
margin-left: 8.33333% !important;
|
||||
Margin-left: 8.33333% !important;
|
||||
}
|
||||
table.body td.small-offset-2,
|
||||
table.body th.small-offset-2 {
|
||||
margin-left: 16.66667% !important;
|
||||
Margin-left: 16.66667% !important;
|
||||
}
|
||||
table.body td.small-offset-3,
|
||||
table.body th.small-offset-3 {
|
||||
margin-left: 25% !important;
|
||||
Margin-left: 25% !important;
|
||||
}
|
||||
table.body td.small-offset-4,
|
||||
table.body th.small-offset-4 {
|
||||
margin-left: 33.33333% !important;
|
||||
Margin-left: 33.33333% !important;
|
||||
}
|
||||
table.body td.small-offset-5,
|
||||
table.body th.small-offset-5 {
|
||||
margin-left: 41.66667% !important;
|
||||
Margin-left: 41.66667% !important;
|
||||
}
|
||||
table.body td.small-offset-6,
|
||||
table.body th.small-offset-6 {
|
||||
margin-left: 50% !important;
|
||||
Margin-left: 50% !important;
|
||||
}
|
||||
table.body td.small-offset-7,
|
||||
table.body th.small-offset-7 {
|
||||
margin-left: 58.33333% !important;
|
||||
Margin-left: 58.33333% !important;
|
||||
}
|
||||
table.body td.small-offset-8,
|
||||
table.body th.small-offset-8 {
|
||||
margin-left: 66.66667% !important;
|
||||
Margin-left: 66.66667% !important;
|
||||
}
|
||||
table.body td.small-offset-9,
|
||||
table.body th.small-offset-9 {
|
||||
margin-left: 75% !important;
|
||||
Margin-left: 75% !important;
|
||||
}
|
||||
table.body td.small-offset-10,
|
||||
table.body th.small-offset-10 {
|
||||
margin-left: 83.33333% !important;
|
||||
Margin-left: 83.33333% !important;
|
||||
}
|
||||
table.body td.small-offset-11,
|
||||
table.body th.small-offset-11 {
|
||||
margin-left: 91.66667% !important;
|
||||
Margin-left: 91.66667% !important;
|
||||
}
|
||||
table.body table.columns td.expander,
|
||||
table.body table.columns th.expander {
|
||||
display: none !important;
|
||||
}
|
||||
table.body .right-text-pad,
|
||||
table.body .text-pad-right {
|
||||
padding-left: 10px !important;
|
||||
}
|
||||
table.body .left-text-pad,
|
||||
table.body .text-pad-left {
|
||||
padding-right: 10px !important;
|
||||
}
|
||||
table.menu {
|
||||
width: 100% !important;
|
||||
}
|
||||
table.menu td,
|
||||
table.menu th {
|
||||
width: auto !important;
|
||||
display: inline-block !important;
|
||||
}
|
||||
table.menu.vertical td,
|
||||
table.menu.vertical th,
|
||||
table.menu.small-vertical td,
|
||||
table.menu.small-vertical th {
|
||||
display: block !important;
|
||||
}
|
||||
table.menu[align="center"] {
|
||||
width: auto !important;
|
||||
}
|
||||
table.button.small-expand,
|
||||
table.button.small-expanded {
|
||||
width: 100% !important;
|
||||
}
|
||||
table.button.small-expand table,
|
||||
table.button.small-expanded table {
|
||||
width: 100%;
|
||||
}
|
||||
table.button.small-expand table a,
|
||||
table.button.small-expanded table a {
|
||||
text-align: center !important;
|
||||
width: 100% !important;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
table.button.small-expand center,
|
||||
table.button.small-expanded center {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
67
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.html.twig
vendored
Normal file
67
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.html.twig
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
{% apply inky_to_html|inline_css %}
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
{% block style %}
|
||||
{{ source("@email/zurb_2/main.css") }}
|
||||
{{ source("@email/zurb_2/notification/local.css") }}
|
||||
{% endblock %}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<spacer size="32"></spacer>
|
||||
<wrapper class="body">
|
||||
<container class="body_{{ ("urgent" == importance ? "alert" : ("high" == importance ? "warning" : "default")) }}">
|
||||
<spacer size="16"></spacer>
|
||||
<row>
|
||||
<columns large="12" small="12">
|
||||
{% block lead %}
|
||||
{% if importance is not null %}<small><strong>{{ importance|upper }}</strong></small>{% endif %}
|
||||
<p class="lead">
|
||||
{{ email.subject }}
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% if markdown %}
|
||||
{{ include('@email/zurb_2/notification/content_markdown.html.twig') }}
|
||||
{% else %}
|
||||
{{ (raw ? content|raw : content)|nl2br }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block action %}
|
||||
{% if action_url %}
|
||||
<spacer size="16"></spacer>
|
||||
<button href="{{ action_url }}">{{ action_text }}</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block exception %}
|
||||
{% if exception %}
|
||||
<spacer size="16"></spacer>
|
||||
<p><em>Exception stack trace attached.</em></p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</columns>
|
||||
</row>
|
||||
|
||||
<wrapper class="secondary">
|
||||
<spacer size="16"></spacer>
|
||||
{% block footer %}
|
||||
{% if footer_text is defined and footer_text is not null %}
|
||||
<row>
|
||||
<columns small="12" large="6">
|
||||
{% block footer_content %}
|
||||
<p><small>{{ footer_text }}</small></p>
|
||||
{% endblock %}
|
||||
</columns>
|
||||
</row>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</wrapper>
|
||||
</container>
|
||||
</wrapper>
|
||||
</body>
|
||||
</html>
|
||||
{% endapply %}
|
20
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.txt.twig
vendored
Normal file
20
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/body.txt.twig
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
{% block lead %}
|
||||
{{ email.subject }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{{ content }}
|
||||
{% endblock %}
|
||||
|
||||
{% block action %}
|
||||
{% if action_url %}
|
||||
{{ action_text }}: {{ action_url }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block exception %}
|
||||
{% if exception %}
|
||||
Exception stack trace attached.
|
||||
{{ exception }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
@ -0,0 +1 @@
|
||||
{{ content|markdown_to_html }}
|
19
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/local.css
vendored
Normal file
19
vendor/symfony/twig-bridge/Resources/views/Email/zurb_2/notification/local.css
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
body {
|
||||
background: #f3f3f3;
|
||||
}
|
||||
|
||||
.wrapper.secondary {
|
||||
background: #f3f3f3;
|
||||
}
|
||||
|
||||
.container.body_alert {
|
||||
border-top: 8px solid #ec5840;
|
||||
}
|
||||
|
||||
.container.body_warning {
|
||||
border-top: 8px solid #ffae00;
|
||||
}
|
||||
|
||||
.container.body_default {
|
||||
border-top: 8px solid #aaaaaa;
|
||||
}
|
71
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig
vendored
Normal file
71
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
{% use "bootstrap_3_layout.html.twig" %}
|
||||
|
||||
{% block form_start -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-horizontal')|trim}) %}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_start %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
{%- if label is same as(false) -%}
|
||||
<div class="{{ block('form_label_class') }}"></div>
|
||||
{%- else -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endif -%}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{% block form_label_class -%}
|
||||
col-sm-2
|
||||
{%- endblock form_label_class %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ ((not compound or force_error|default(false)) and not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_label(form) -}}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{##}</div>
|
||||
{%- endblock form_row %}
|
||||
|
||||
{% block submit_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock submit_row %}
|
||||
|
||||
{% block reset_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock reset_row %}
|
||||
|
||||
{% block form_group_class -%}
|
||||
col-sm-10
|
||||
{%- endblock form_group_class %}
|
||||
|
||||
{% block checkbox_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock checkbox_row %}
|
216
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig
vendored
Normal file
216
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
{% use "bootstrap_base_layout.html.twig" %}
|
||||
|
||||
{# Widgets #}
|
||||
|
||||
{% block form_widget_simple -%}
|
||||
{% if type is not defined or type not in ['file', 'hidden'] %}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
|
||||
{% endif %}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_widget_simple %}
|
||||
|
||||
{% block button_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('btn-default') ~ ' btn')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock button_widget %}
|
||||
|
||||
{% block money_widget -%}
|
||||
{% set prepend = not (money_pattern starts with '{{') %}
|
||||
{% set append = not (money_pattern ends with '}}') %}
|
||||
{% if prepend or append %}
|
||||
<div class="input-group">
|
||||
{% if prepend %}
|
||||
<span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span>
|
||||
{% endif %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% if append %}
|
||||
<span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% endif %}
|
||||
{%- endblock money_widget %}
|
||||
|
||||
{% block checkbox_widget -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{% if 'checkbox-inline' in parent_label_class %}
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
{% else -%}
|
||||
<div class="checkbox">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock checkbox_widget %}
|
||||
|
||||
{% block radio_widget -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- if 'radio-inline' in parent_label_class -%}
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
{%- else -%}
|
||||
<div class="radio">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock radio_widget %}
|
||||
|
||||
{% block choice_widget_collapsed -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock choice_widget_collapsed %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' control-label')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{% block choice_label -%}
|
||||
{# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #}
|
||||
{%- set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) -%}
|
||||
{{- block('form_label') -}}
|
||||
{% endblock %}
|
||||
|
||||
{% block checkbox_label -%}
|
||||
{%- set label_attr = label_attr|merge({'for': id}) -%}
|
||||
|
||||
{{- block('checkbox_radio_label') -}}
|
||||
{%- endblock checkbox_label %}
|
||||
|
||||
{% block radio_label -%}
|
||||
{%- set label_attr = label_attr|merge({'for': id}) -%}
|
||||
|
||||
{{- block('checkbox_radio_label') -}}
|
||||
{%- endblock radio_label %}
|
||||
|
||||
{% block checkbox_radio_label -%}
|
||||
{# Do not display the label if widget is not defined in order to prevent double label rendering #}
|
||||
{%- if widget is defined -%}
|
||||
{%- if required -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- if label is not same as(false) and label is empty -%}
|
||||
{%- if label_format is not empty -%}
|
||||
{%- set label = label_format|replace({
|
||||
'%name%': name,
|
||||
'%id%': id,
|
||||
}) -%}
|
||||
{%- else -%}
|
||||
{% set label = name|humanize %}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{#- if statement must be kept on the same line, to force the space between widget and label -#}
|
||||
{{- widget|raw }} {% if label is not same as(false) -%}
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{ label -}}
|
||||
{%- else -%}
|
||||
{{ label|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{ label|trans(label_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{ label|trans(label_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</label>
|
||||
{%- endif -%}
|
||||
{%- endblock checkbox_radio_label %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ ((not compound or force_error|default(false)) and not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_label(form) }} {# -#}
|
||||
{{ form_widget(form, widget_attr) }} {# -#}
|
||||
{{- form_help(form) -}}
|
||||
{{ form_errors(form) }} {# -#}
|
||||
</div> {# -#}
|
||||
{%- endblock form_row %}
|
||||
|
||||
{% block button_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_widget(form) -}}
|
||||
</div>
|
||||
{%- endblock button_row %}
|
||||
|
||||
{% block choice_row -%}
|
||||
{% set force_error = true %}
|
||||
{{- block('form_row') }}
|
||||
{%- endblock choice_row %}
|
||||
|
||||
{% block date_row -%}
|
||||
{% set force_error = true %}
|
||||
{{- block('form_row') }}
|
||||
{%- endblock date_row %}
|
||||
|
||||
{% block time_row -%}
|
||||
{% set force_error = true %}
|
||||
{{- block('form_row') }}
|
||||
{%- endblock time_row %}
|
||||
|
||||
{% block datetime_row -%}
|
||||
{% set force_error = true %}
|
||||
{{- block('form_row') }}
|
||||
{%- endblock datetime_row %}
|
||||
|
||||
{% block checkbox_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_widget(form) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{%- endblock checkbox_row %}
|
||||
|
||||
{% block radio_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_widget(form) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{%- endblock radio_row %}
|
||||
|
||||
{# Errors #}
|
||||
|
||||
{% block form_errors -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% if form is not rootform %}<span class="help-block">{% else %}<div class="alert alert-danger">{% endif %}
|
||||
<ul class="list-unstyled">
|
||||
{%- for error in errors -%}
|
||||
<li><span class="glyphicon glyphicon-exclamation-sign"></span> {{ error.message }}</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{% if form is not rootform %}</span>{% else %}</div>{% endif %}
|
||||
{%- endif %}
|
||||
{%- endblock form_errors %}
|
||||
|
||||
{# Help #}
|
||||
|
||||
{% block form_help -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-block')|trim}) -%}
|
||||
<span id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if help_html is same as(false) -%}
|
||||
{{- help -}}
|
||||
{%- else -%}
|
||||
{{- help|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if help_html is same as(false) -%}
|
||||
{{- help|trans(help_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- help|trans(help_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</span>
|
||||
{%- endif -%}
|
||||
{%- endblock form_help %}
|
87
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig
vendored
Normal file
87
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
{% use "bootstrap_4_layout.html.twig" %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
{%- if label is same as(false) -%}
|
||||
<div class="{{ block('form_label_class') }}"></div>
|
||||
{%- else -%}
|
||||
{%- if expanded is not defined or not expanded -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endif -%}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{% block form_label_class -%}
|
||||
col-sm-2
|
||||
{%- endblock form_label_class %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block form_row -%}
|
||||
{%- if expanded is defined and expanded -%}
|
||||
{{ block('fieldset_form_row') }}
|
||||
{%- else -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row' ~ ((not compound or force_error|default(false)) and not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_label(form) -}}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
</div>
|
||||
{##}</div>
|
||||
{%- endif -%}
|
||||
{%- endblock form_row %}
|
||||
|
||||
{% block fieldset_form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<fieldset{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<div class="row{% if (not compound or force_error|default(false)) and not valid %} is-invalid{% endif %}">
|
||||
{{- form_label(form) -}}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
</div>
|
||||
</div>
|
||||
{##}</fieldset>
|
||||
{%- endblock fieldset_form_row %}
|
||||
|
||||
{% block submit_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock submit_row %}
|
||||
|
||||
{% block reset_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock reset_row %}
|
||||
|
||||
{% block form_group_class -%}
|
||||
col-sm-10
|
||||
{%- endblock form_group_class %}
|
||||
|
||||
{% block checkbox_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
{{- form_help(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock checkbox_row %}
|
371
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig
vendored
Normal file
371
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig
vendored
Normal file
@ -0,0 +1,371 @@
|
||||
{% use "bootstrap_base_layout.html.twig" %}
|
||||
|
||||
{# Widgets #}
|
||||
|
||||
{% block money_widget -%}
|
||||
{%- set prepend = not (money_pattern starts with '{{') -%}
|
||||
{%- set append = not (money_pattern ends with '}}') -%}
|
||||
{%- if prepend or append -%}
|
||||
<div class="input-group{{ group_class|default('') }}">
|
||||
{%- if prepend -%}
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text">{{ money_pattern|form_encode_currency }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- if append -%}
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">{{ money_pattern|form_encode_currency }}</span>
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock money_widget %}
|
||||
|
||||
{% block datetime_widget -%}
|
||||
{%- if widget != 'single_text' and not valid -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock datetime_widget %}
|
||||
|
||||
{% block date_widget -%}
|
||||
{%- if widget != 'single_text' and not valid -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock date_widget %}
|
||||
|
||||
{% block time_widget -%}
|
||||
{%- if widget != 'single_text' and not valid -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock time_widget %}
|
||||
|
||||
{% block dateinterval_widget -%}
|
||||
{%- if widget != 'single_text' and not valid -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{%- endif -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- if with_years -%}
|
||||
<div class="col-auto">
|
||||
{{ form_label(form.years) }}
|
||||
{{ form_widget(form.years) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_months -%}
|
||||
<div class="col-auto">
|
||||
{{ form_label(form.months) }}
|
||||
{{ form_widget(form.months) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_weeks -%}
|
||||
<div class="col-auto">
|
||||
{{ form_label(form.weeks) }}
|
||||
{{ form_widget(form.weeks) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_days -%}
|
||||
<div class="col-auto">
|
||||
{{ form_label(form.days) }}
|
||||
{{ form_widget(form.days) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_hours -%}
|
||||
<div class="col-auto">
|
||||
{{ form_label(form.hours) }}
|
||||
{{ form_widget(form.hours) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_minutes -%}
|
||||
<div class="col-auto">
|
||||
{{ form_label(form.minutes) }}
|
||||
{{ form_widget(form.minutes) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_seconds -%}
|
||||
<div class="col-auto">
|
||||
{{ form_label(form.seconds) }}
|
||||
{{ form_widget(form.seconds) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock dateinterval_widget %}
|
||||
|
||||
{% block percent_widget -%}
|
||||
{%- if symbol -%}
|
||||
<div class="input-group">
|
||||
{{- block('form_widget_simple') -}}
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">{{ symbol|default('%') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock percent_widget %}
|
||||
|
||||
{% block file_widget -%}
|
||||
<{{ element|default('div') }} class="custom-file">
|
||||
{%- set type = type|default('file') -%}
|
||||
{%- set input_lang = 'en' -%}
|
||||
{% if app is defined and app.request is defined %}{%- set input_lang = app.request.locale -%}{%- endif -%}
|
||||
{%- set attr = {lang: input_lang} | merge(attr) -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- set label_attr = label_attr|merge({ class: (label_attr.class|default('') ~ ' custom-file-label')|trim })|filter((value, key) => key != 'id') -%}
|
||||
<label for="{{ form.vars.id }}" {% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if attr.placeholder is defined and attr.placeholder is not none -%}
|
||||
{{- translation_domain is same as(false) ? attr.placeholder : attr.placeholder|trans({}, translation_domain) -}}
|
||||
{%- endif -%}
|
||||
</label>
|
||||
</{{ element|default('div') }}>
|
||||
{% endblock %}
|
||||
|
||||
{% block form_widget_simple -%}
|
||||
{%- if type is not defined or type != 'hidden' -%}
|
||||
{%- set className = ' form-control' -%}
|
||||
{%- if type|default('') == 'file' -%}
|
||||
{%- set className = ' custom-file-input' -%}
|
||||
{%- elseif type|default('') == 'range' -%}
|
||||
{%- set className = ' form-control-range' -%}
|
||||
{%- endif -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ className)|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- if type is defined and (type == 'range' or type == 'color') %}
|
||||
{# Attribute "required" is not supported #}
|
||||
{%- set required = false -%}
|
||||
{% endif %}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_widget_simple %}
|
||||
|
||||
{% block widget_attributes -%}
|
||||
{%- if not valid -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) %}
|
||||
{%- endif -%}
|
||||
{{ parent() }}
|
||||
{%- endblock widget_attributes %}
|
||||
|
||||
{% block button_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('btn-secondary') ~ ' btn')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock button_widget %}
|
||||
|
||||
{% block submit_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('btn-primary'))|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock submit_widget %}
|
||||
|
||||
{% block checkbox_widget -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- if 'checkbox-custom' in parent_label_class -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%}
|
||||
<div class="custom-control custom-checkbox{{ 'checkbox-inline' in parent_label_class ? ' custom-control-inline' }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- elseif 'switch-custom' in parent_label_class -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%}
|
||||
<div class="custom-control custom-switch{{ 'switch-inline' in parent_label_class ? ' custom-control-inline' }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%}
|
||||
<div class="form-check{{ 'checkbox-inline' in parent_label_class ? ' form-check-inline' }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock checkbox_widget %}
|
||||
|
||||
{% block radio_widget -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- if 'radio-custom' in parent_label_class -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%}
|
||||
<div class="custom-control custom-radio{{ 'radio-inline' in parent_label_class ? ' custom-control-inline' }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%}
|
||||
<div class="form-check{{ 'radio-inline' in parent_label_class ? ' form-check-inline' }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock radio_widget %}
|
||||
|
||||
{% block choice_widget_collapsed -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock choice_widget_collapsed %}
|
||||
|
||||
{% block choice_widget_expanded -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- for child in form %}
|
||||
{{- form_widget(child, {
|
||||
parent_label_class: label_attr.class|default(''),
|
||||
translation_domain: choice_translation_domain,
|
||||
valid: valid,
|
||||
}) -}}
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{%- endblock choice_widget_expanded %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
{% if label is not same as(false) -%}
|
||||
{%- if compound is defined and compound -%}
|
||||
{%- set element = 'legend' -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%}
|
||||
{%- else -%}
|
||||
{%- set label_attr = label_attr|merge({for: id}) -%}
|
||||
{%- endif -%}
|
||||
{% if required -%}
|
||||
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %}
|
||||
{%- endif -%}
|
||||
{% if label is empty -%}
|
||||
{%- if label_format is not empty -%}
|
||||
{% set label = label_format|replace({
|
||||
'%name%': name,
|
||||
'%id%': id,
|
||||
}) %}
|
||||
{%- else -%}
|
||||
{% set label = name|humanize %}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
<{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label -}}
|
||||
{%- else -%}
|
||||
{{- label|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{% block form_label_errors %}{{- form_errors(form) -}}{% endblock form_label_errors %}</{{ element|default('label') }}>
|
||||
{%- else -%}
|
||||
{%- if errors|length > 0 -%}
|
||||
<div id="{{ id }}_errors" class="mb-2">
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{% block checkbox_radio_label -%}
|
||||
{#- Do not display the label if widget is not defined in order to prevent double label rendering -#}
|
||||
{%- if widget is defined -%}
|
||||
{% set is_parent_custom = parent_label_class is defined and ('checkbox-custom' in parent_label_class or 'radio-custom' in parent_label_class or 'switch-custom' in parent_label_class) %}
|
||||
{% set is_custom = label_attr.class is defined and ('checkbox-custom' in label_attr.class or 'radio-custom' in label_attr.class or 'switch-custom' in label_attr.class) %}
|
||||
{%- if is_parent_custom or is_custom -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' custom-control-label')|trim}) -%}
|
||||
{%- else %}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%}
|
||||
{%- endif %}
|
||||
{%- if not compound -%}
|
||||
{% set label_attr = label_attr|merge({'for': id}) %}
|
||||
{%- endif -%}
|
||||
{%- if required -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- if label is not same as(false) and label is empty -%}
|
||||
{%- if label_format is not empty -%}
|
||||
{%- set label = label_format|replace({
|
||||
'%name%': name,
|
||||
'%id%': id,
|
||||
}) -%}
|
||||
{%- else -%}
|
||||
{%- set label = name|humanize -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{{ widget|raw }}
|
||||
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if label is not same as(false) -%}
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label -}}
|
||||
{%- else -%}
|
||||
{{- label|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{{- form_errors(form) -}}
|
||||
</label>
|
||||
{%- endif -%}
|
||||
{%- endblock checkbox_radio_label %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block form_row -%}
|
||||
{%- if compound is defined and compound -%}
|
||||
{%- set element = 'fieldset' -%}
|
||||
{%- endif -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<{{ element|default('div') }}{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_label(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
</{{ element|default('div') }}>
|
||||
{%- endblock form_row %}
|
||||
|
||||
{# Errors #}
|
||||
|
||||
{% block form_errors -%}
|
||||
{%- if errors|length > 0 -%}
|
||||
<span class="{% if form is not rootform %}invalid-feedback{% else %}alert alert-danger{% endif %} d-block">
|
||||
{%- for error in errors -%}
|
||||
<span class="d-block">
|
||||
<span class="form-error-icon badge badge-danger text-uppercase">{{ 'Error'|trans({}, 'validators') }}</span> <span class="form-error-message">{{ error.message }}</span>
|
||||
</span>
|
||||
{%- endfor -%}
|
||||
</span>
|
||||
{%- endif %}
|
||||
{%- endblock form_errors %}
|
||||
|
||||
{# Help #}
|
||||
|
||||
{% block form_help -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' form-text text-muted')|trim}) -%}
|
||||
<small id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if help_html is same as(false) -%}
|
||||
{{- help -}}
|
||||
{%- else -%}
|
||||
{{- help|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if help_html is same as(false) -%}
|
||||
{{- help|trans(help_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- help|trans(help_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</small>
|
||||
{%- endif -%}
|
||||
{%- endblock form_help %}
|
130
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig
vendored
Normal file
130
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_5_horizontal_layout.html.twig
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
{% use "bootstrap_5_layout.html.twig" %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
{%- if label is same as(false) -%}
|
||||
<div class="{{ block('form_label_class') }}"></div>
|
||||
{%- else -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('')) -%}
|
||||
{%- if 'form-floating' not in row_class and 'input-group' not in row_class -%}
|
||||
{%- if expanded is not defined or not expanded -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endif -%}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{% block form_label_class -%}
|
||||
col-sm-2
|
||||
{%- endblock form_label_class %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block form_row -%}
|
||||
{%- if expanded is defined and expanded -%}
|
||||
{{ block('fieldset_form_row') }}
|
||||
{%- else -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('mb-3')) -%}
|
||||
{%- set is_form_floating = is_form_floating|default('form-floating' in row_class) -%}
|
||||
{%- set is_input_group = is_input_group|default('input-group' in row_class) -%}
|
||||
{#- Remove behavior class from the main container -#}
|
||||
{%- set row_class = row_class|replace({'form-floating': '', 'input-group': ''}) -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_class ~ ' row' ~ ((not compound or force_error|default(false)) and not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if is_form_floating or is_input_group -%}
|
||||
<div class="{{ block('form_label_class') }}"></div>
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{%- if is_form_floating -%}
|
||||
<div class="form-floating">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_label(form) -}}
|
||||
</div>
|
||||
{%- elseif is_input_group -%}
|
||||
<div class="input-group">
|
||||
{{- form_label(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{#- Hack to properly display help with input group -#}
|
||||
{{- form_help(form) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if not is_input_group -%}
|
||||
{{- form_help(form) -}}
|
||||
{%- endif -%}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- form_label(form) -}}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{##}</div>
|
||||
{%- endif -%}
|
||||
{%- endblock form_row %}
|
||||
|
||||
{% block fieldset_form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<fieldset{% with {attr: row_attr|merge({class: row_attr.class|default('mb-3')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<div class="row{% if (not compound or force_error|default(false)) and not valid %} is-invalid{% endif %}">
|
||||
{{- form_label(form) -}}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
{%- endblock fieldset_form_row %}
|
||||
|
||||
{% block submit_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock submit_row %}
|
||||
|
||||
{% block reset_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock reset_row %}
|
||||
|
||||
{% block button_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock button_row %}
|
||||
|
||||
{% block checkbox_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('mb-3') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>{#--#}
|
||||
<div class="{{ block('form_label_class') }}"></div>{#--#}
|
||||
<div class="{{ block('form_group_class') }}">
|
||||
{{- form_widget(form) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>{#--#}
|
||||
</div>
|
||||
{%- endblock checkbox_row %}
|
||||
|
||||
{% block form_group_class -%}
|
||||
col-sm-10
|
||||
{%- endblock form_group_class %}
|
374
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_5_layout.html.twig
vendored
Normal file
374
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_5_layout.html.twig
vendored
Normal file
@ -0,0 +1,374 @@
|
||||
{% use "bootstrap_base_layout.html.twig" %}
|
||||
|
||||
{# Widgets #}
|
||||
|
||||
{% block money_widget -%}
|
||||
{%- set prepend = not (money_pattern starts with '{{') -%}
|
||||
{%- set append = not (money_pattern ends with '}}') -%}
|
||||
{%- if prepend or append -%}
|
||||
<div class="input-group{{ group_class|default('') }}">
|
||||
{%- if prepend -%}
|
||||
<span class="input-group-text">{{ money_pattern|form_encode_currency }}</span>
|
||||
{%- endif -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- if append -%}
|
||||
<span class="input-group-text">{{ money_pattern|form_encode_currency }}</span>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock money_widget %}
|
||||
|
||||
{% block date_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
{%- if datetime is not defined or not datetime -%}
|
||||
<div {{ block('widget_container_attributes') -}}>
|
||||
{%- endif %}
|
||||
{%- if label is not same as(false) -%}
|
||||
<div class="visually-hidden">
|
||||
{{- form_label(form.year) -}}
|
||||
{{- form_label(form.month) -}}
|
||||
{{- form_label(form.day) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
<div class="input-group">
|
||||
{{- date_pattern|replace({
|
||||
'{{ year }}': form_widget(form.year),
|
||||
'{{ month }}': form_widget(form.month),
|
||||
'{{ day }}': form_widget(form.day),
|
||||
})|raw -}}
|
||||
</div>
|
||||
{%- if datetime is not defined or not datetime -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endblock date_widget %}
|
||||
|
||||
{% block time_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
{%- if datetime is not defined or false == datetime -%}
|
||||
<div {{ block('widget_container_attributes') -}}>
|
||||
{%- endif -%}
|
||||
{%- if label is not same as(false) -%}
|
||||
<div class="visually-hidden">
|
||||
{{- form_label(form.hour) -}}
|
||||
{%- if with_minutes -%}{{ form_label(form.minute) }}{%- endif -%}
|
||||
{%- if with_seconds -%}{{ form_label(form.second) }}{%- endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{% if with_minutes or with_seconds %}
|
||||
<div class="input-group">
|
||||
{% endif %}
|
||||
{{- form_widget(form.hour) -}}
|
||||
{%- if with_minutes -%}
|
||||
<span class="input-group-text">:</span>
|
||||
{{- form_widget(form.minute) -}}
|
||||
{%- endif -%}
|
||||
{%- if with_seconds -%}
|
||||
<span class="input-group-text">:</span>
|
||||
{{- form_widget(form.second) -}}
|
||||
{%- endif -%}
|
||||
{% if with_minutes or with_seconds %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- if datetime is not defined or false == datetime -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endblock time_widget %}
|
||||
|
||||
{% block datetime_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{- form_widget(form.date, { datetime: true } ) -}}
|
||||
{{- form_errors(form.date) -}}
|
||||
{{- form_widget(form.time, { datetime: true } ) -}}
|
||||
{{- form_errors(form.time) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock datetime_widget %}
|
||||
|
||||
{% block dateinterval_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) -%}
|
||||
{% set valid = true %}
|
||||
{% endif %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- if with_years -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.years) }}
|
||||
{{ form_widget(form.years) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_months -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.months) }}
|
||||
{{ form_widget(form.months) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_weeks -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.weeks) }}
|
||||
{{ form_widget(form.weeks) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_days -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.days) }}
|
||||
{{ form_widget(form.days) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_hours -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.hours) }}
|
||||
{{ form_widget(form.hours) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_minutes -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.minutes) }}
|
||||
{{ form_widget(form.minutes) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_seconds -%}
|
||||
<div class="col-auto mb-3">
|
||||
{{ form_label(form.seconds) }}
|
||||
{{ form_widget(form.seconds) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock dateinterval_widget %}
|
||||
|
||||
{% block percent_widget -%}
|
||||
{%- if symbol -%}
|
||||
<div class="input-group">
|
||||
{{- block('form_widget_simple') -}}
|
||||
<span class="input-group-text">{{ symbol|default('%') }}</span>
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock percent_widget %}
|
||||
|
||||
{% block form_widget_simple -%}
|
||||
{%- if type is not defined or type != 'hidden' %}
|
||||
{%- set widget_class = ' form-control' %}
|
||||
{%- if type|default('') == 'color' -%}
|
||||
{%- set widget_class = widget_class ~ ' form-control-color' -%}
|
||||
{%- elseif type|default('') == 'range' -%}
|
||||
{%- set widget_class = ' form-range' -%}
|
||||
{%- endif -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ widget_class)|trim}) -%}
|
||||
{% endif -%}
|
||||
{%- if type is defined and type in ['range', 'color'] %}
|
||||
{# Attribute "required" is not supported #}
|
||||
{% set required = false %}
|
||||
{% endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_widget_simple %}
|
||||
|
||||
{%- block widget_attributes -%}
|
||||
{%- if not valid %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) %}
|
||||
{% endif -%}
|
||||
{{ parent() }}
|
||||
{%- endblock widget_attributes -%}
|
||||
|
||||
{%- block button_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('btn-secondary') ~ ' btn')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock button_widget %}
|
||||
|
||||
{%- block submit_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('btn-primary'))|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock submit_widget %}
|
||||
|
||||
{%- block checkbox_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- set row_class = 'form-check' -%}
|
||||
{%- if 'checkbox-inline' in parent_label_class %}
|
||||
{% set row_class = row_class ~ ' form-check-inline' %}
|
||||
{% endif -%}
|
||||
{%- if 'checkbox-switch' in parent_label_class %}
|
||||
{% set row_class = row_class ~ ' form-switch' %}
|
||||
{% endif -%}
|
||||
<div class="{{ row_class }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endblock checkbox_widget %}
|
||||
|
||||
{%- block radio_widget -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- set row_class = 'form-check' -%}
|
||||
{%- if 'radio-inline' in parent_label_class -%}
|
||||
{%- set row_class = row_class ~ ' form-check-inline' -%}
|
||||
{%- endif -%}
|
||||
<div class="{{ row_class }}">
|
||||
{{- form_label(form, null, { widget: parent() }) -}}
|
||||
</div>
|
||||
{%- endblock radio_widget %}
|
||||
|
||||
{%- block choice_widget_collapsed -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-select')|trim}) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock choice_widget_collapsed -%}
|
||||
|
||||
{%- block choice_widget_expanded -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- for child in form %}
|
||||
{{- form_widget(child, {
|
||||
parent_label_class: label_attr.class|default(''),
|
||||
translation_domain: choice_translation_domain,
|
||||
valid: valid,
|
||||
}) -}}
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{%- endblock choice_widget_expanded %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{%- block form_label -%}
|
||||
{% if label is not same as(false) -%}
|
||||
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||
{%- if compound is defined and compound -%}
|
||||
{%- set element = 'legend' -%}
|
||||
{%- if 'col-form-label' not in parent_label_class -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label' )|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('')) -%}
|
||||
{%- set label_attr = label_attr|merge({for: id}) -%}
|
||||
{%- if 'col-form-label' not in parent_label_class -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ('input-group' in row_class ? ' input-group-text' : ' form-label') )|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{%- block checkbox_radio_label -%}
|
||||
{#- Do not display the label if widget is not defined in order to prevent double label rendering -#}
|
||||
{%- if widget is defined -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%}
|
||||
{%- if not compound -%}
|
||||
{% set label_attr = label_attr|merge({'for': id}) %}
|
||||
{%- endif -%}
|
||||
{%- if required -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- if parent_label_class is defined -%}
|
||||
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) -%}
|
||||
{%- endif -%}
|
||||
{%- if label is not same as(false) and label is empty -%}
|
||||
{%- if label_format is not empty -%}
|
||||
{%- set label = label_format|replace({
|
||||
'%name%': name,
|
||||
'%id%': id,
|
||||
}) -%}
|
||||
{%- else -%}
|
||||
{%- set label = name|humanize -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{{ widget|raw }}
|
||||
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if label is not same as(false) -%}
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label -}}
|
||||
{%- else -%}
|
||||
{{- label|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</label>
|
||||
{%- endif -%}
|
||||
{%- endblock checkbox_radio_label %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{%- block form_row -%}
|
||||
{%- if compound is defined and compound -%}
|
||||
{%- set element = 'fieldset' -%}
|
||||
{%- endif -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
{%- set row_class = row_class|default(row_attr.class|default('mb-3')|trim) -%}
|
||||
<{{ element|default('div') }}{% with {attr: row_attr|merge({class: row_class})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if 'form-floating' in row_class -%}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_label(form) -}}
|
||||
{%- else -%}
|
||||
{{- form_label(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{%- endif -%}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</{{ element|default('div') }}>
|
||||
{%- endblock form_row %}
|
||||
|
||||
{%- block button_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: row_attr.class|default('mb-3')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_widget(form) -}}
|
||||
</div>
|
||||
{%- endblock button_row %}
|
||||
|
||||
{# Errors #}
|
||||
|
||||
{%- block form_errors -%}
|
||||
{%- if errors|length > 0 -%}
|
||||
{%- for error in errors -%}
|
||||
<div class="invalid-feedback d-block">{{ error.message }}</div>
|
||||
{%- endfor -%}
|
||||
{%- endif %}
|
||||
{%- endblock form_errors %}
|
||||
|
||||
{# Help #}
|
||||
|
||||
{%- block form_help -%}
|
||||
{% set row_class = row_attr.class|default('') %}
|
||||
{% set help_class = ' form-text' %}
|
||||
{% if 'input-group' in row_class %}
|
||||
{#- Hack to properly display help with input group -#}
|
||||
{% set help_class = ' input-group-text' %}
|
||||
{% endif %}
|
||||
{%- if help is not empty -%}
|
||||
{%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ help_class ~ ' mb-0')|trim}) -%}
|
||||
{%- endif -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_help %}
|
208
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig
vendored
Normal file
208
vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
{% use "form_div_layout.html.twig" %}
|
||||
|
||||
{# Widgets #}
|
||||
|
||||
{% block textarea_widget -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) %}
|
||||
{{- parent() -}}
|
||||
{%- endblock textarea_widget %}
|
||||
|
||||
{% block money_widget -%}
|
||||
{% set prepend = not (money_pattern starts with '{{') %}
|
||||
{% set append = not (money_pattern ends with '}}') %}
|
||||
{% if prepend or append %}
|
||||
<div class="input-group{{ group_class|default('') }}">
|
||||
{% if prepend %}
|
||||
<span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span>
|
||||
{% endif %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% if append %}
|
||||
<span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% endif %}
|
||||
{%- endblock money_widget %}
|
||||
|
||||
{% block percent_widget -%}
|
||||
{%- if symbol -%}
|
||||
<div class="input-group">
|
||||
{{- block('form_widget_simple') -}}
|
||||
<span class="input-group-addon">{{ symbol|default('%') }}</span>
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock percent_widget %}
|
||||
|
||||
{% block datetime_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{- form_errors(form.date) -}}
|
||||
{{- form_errors(form.time) -}}
|
||||
|
||||
<div class="sr-only">
|
||||
{%- if form.date.year is defined %}{{ form_label(form.date.year) }}{% endif -%}
|
||||
{%- if form.date.month is defined %}{{ form_label(form.date.month) }}{% endif -%}
|
||||
{%- if form.date.day is defined %}{{ form_label(form.date.day) }}{% endif -%}
|
||||
{%- if form.time.hour is defined %}{{ form_label(form.time.hour) }}{% endif -%}
|
||||
{%- if form.time.minute is defined %}{{ form_label(form.time.minute) }}{% endif -%}
|
||||
{%- if form.time.second is defined %}{{ form_label(form.time.second) }}{% endif -%}
|
||||
</div>
|
||||
|
||||
{{- form_widget(form.date, { datetime: true } ) -}}
|
||||
{{- form_widget(form.time, { datetime: true } ) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock datetime_widget %}
|
||||
|
||||
{% block date_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%}
|
||||
{%- if datetime is not defined or not datetime -%}
|
||||
<div {{ block('widget_container_attributes') -}}>
|
||||
{%- endif %}
|
||||
{%- if label is not same as(false) -%}
|
||||
<div class="sr-only">
|
||||
{{ form_label(form.year) }}
|
||||
{{ form_label(form.month) }}
|
||||
{{ form_label(form.day) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
|
||||
{{- date_pattern|replace({
|
||||
'{{ year }}': form_widget(form.year),
|
||||
'{{ month }}': form_widget(form.month),
|
||||
'{{ day }}': form_widget(form.day),
|
||||
})|raw -}}
|
||||
{%- if datetime is not defined or not datetime -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endblock date_widget %}
|
||||
|
||||
{% block time_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%}
|
||||
{%- if datetime is not defined or false == datetime -%}
|
||||
<div {{ block('widget_container_attributes') -}}>
|
||||
{%- endif -%}
|
||||
{%- if label is not same as(false) -%}<div class="sr-only">{{ form_label(form.hour) }}</div>{%- endif -%}
|
||||
{{- form_widget(form.hour) -}}
|
||||
{%- if with_minutes -%}:{%- if label is not same as(false) -%}<div class="sr-only">{{ form_label(form.minute) }}</div>{%- endif -%}{{ form_widget(form.minute) }}{%- endif -%}
|
||||
{%- if with_seconds -%}:{%- if label is not same as(false) -%}<div class="sr-only">{{ form_label(form.second) }}</div>{%- endif -%}{{ form_widget(form.second) }}{%- endif -%}
|
||||
{%- if datetime is not defined or false == datetime -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endblock time_widget %}
|
||||
|
||||
{%- block dateinterval_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{- form_errors(form) -}}
|
||||
<div class="table-responsive">
|
||||
<table class="table {{ table_class|default('table-bordered table-condensed table-striped') }}" role="presentation">
|
||||
<thead>
|
||||
<tr>
|
||||
{%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%}
|
||||
{%- if with_months %}<th>{{ form_label(form.months) }}</th>{% endif -%}
|
||||
{%- if with_weeks %}<th>{{ form_label(form.weeks) }}</th>{% endif -%}
|
||||
{%- if with_days %}<th>{{ form_label(form.days) }}</th>{% endif -%}
|
||||
{%- if with_hours %}<th>{{ form_label(form.hours) }}</th>{% endif -%}
|
||||
{%- if with_minutes %}<th>{{ form_label(form.minutes) }}</th>{% endif -%}
|
||||
{%- if with_seconds %}<th>{{ form_label(form.seconds) }}</th>{% endif -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
{%- if with_years %}<td>{{ form_widget(form.years) }}</td>{% endif -%}
|
||||
{%- if with_months %}<td>{{ form_widget(form.months) }}</td>{% endif -%}
|
||||
{%- if with_weeks %}<td>{{ form_widget(form.weeks) }}</td>{% endif -%}
|
||||
{%- if with_days %}<td>{{ form_widget(form.days) }}</td>{% endif -%}
|
||||
{%- if with_hours %}<td>{{ form_widget(form.hours) }}</td>{% endif -%}
|
||||
{%- if with_minutes %}<td>{{ form_widget(form.minutes) }}</td>{% endif -%}
|
||||
{%- if with_seconds %}<td>{{ form_widget(form.seconds) }}</td>{% endif -%}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock dateinterval_widget -%}
|
||||
|
||||
{% block choice_widget_expanded -%}
|
||||
{%- if '-inline' in label_attr.class|default('') -%}
|
||||
{%- for child in form %}
|
||||
{{- form_widget(child, {
|
||||
parent_label_class: label_attr.class|default(''),
|
||||
translation_domain: choice_translation_domain,
|
||||
}) -}}
|
||||
{% endfor -%}
|
||||
{%- else -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- for child in form %}
|
||||
{{- form_widget(child, {
|
||||
parent_label_class: label_attr.class|default(''),
|
||||
translation_domain: choice_translation_domain,
|
||||
}) -}}
|
||||
{%- endfor -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock choice_widget_expanded %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block choice_label -%}
|
||||
{# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #}
|
||||
{%- set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': '', 'checkbox-custom': '', 'radio-custom': '', 'switch-custom': ''})|trim}) -%}
|
||||
{{- block('form_label') -}}
|
||||
{% endblock choice_label %}
|
||||
|
||||
{% block checkbox_label -%}
|
||||
{{- block('checkbox_radio_label') -}}
|
||||
{%- endblock checkbox_label %}
|
||||
|
||||
{% block radio_label -%}
|
||||
{{- block('checkbox_radio_label') -}}
|
||||
{%- endblock radio_label %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block button_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_widget(form) -}}
|
||||
</div>
|
||||
{%- endblock button_row %}
|
||||
|
||||
{% block choice_row -%}
|
||||
{%- set force_error = true -%}
|
||||
{{- block('form_row') -}}
|
||||
{%- endblock choice_row %}
|
||||
|
||||
{% block date_row -%}
|
||||
{%- set force_error = true -%}
|
||||
{{- block('form_row') -}}
|
||||
{%- endblock date_row %}
|
||||
|
||||
{% block time_row -%}
|
||||
{%- set force_error = true -%}
|
||||
{{- block('form_row') -}}
|
||||
{%- endblock time_row %}
|
||||
|
||||
{% block datetime_row -%}
|
||||
{%- set force_error = true -%}
|
||||
{{- block('form_row') -}}
|
||||
{%- endblock datetime_row %}
|
476
vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig
vendored
Normal file
476
vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig
vendored
Normal file
@ -0,0 +1,476 @@
|
||||
{# Widgets #}
|
||||
|
||||
{%- block form_widget -%}
|
||||
{% if compound %}
|
||||
{{- block('form_widget_compound') -}}
|
||||
{% else %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% endif %}
|
||||
{%- endblock form_widget -%}
|
||||
|
||||
{%- block form_widget_simple -%}
|
||||
{%- set type = type|default('text') -%}
|
||||
{%- if type == 'range' or type == 'color' -%}
|
||||
{# Attribute "required" is not supported #}
|
||||
{%- set required = false -%}
|
||||
{%- endif -%}
|
||||
<input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
|
||||
{%- endblock form_widget_simple -%}
|
||||
|
||||
{%- block form_widget_compound -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- if form is rootform -%}
|
||||
{{ form_errors(form) }}
|
||||
{%- endif -%}
|
||||
{{- block('form_rows') -}}
|
||||
{{- form_rest(form) -}}
|
||||
</div>
|
||||
{%- endblock form_widget_compound -%}
|
||||
|
||||
{%- block collection_widget -%}
|
||||
{% if prototype is defined and not prototype.rendered %}
|
||||
{%- set attr = attr|merge({'data-prototype': form_row(prototype) }) -%}
|
||||
{% endif %}
|
||||
{{- block('form_widget') -}}
|
||||
{%- endblock collection_widget -%}
|
||||
|
||||
{%- block textarea_widget -%}
|
||||
<textarea {{ block('widget_attributes') }}>{{ value }}</textarea>
|
||||
{%- endblock textarea_widget -%}
|
||||
|
||||
{%- block choice_widget -%}
|
||||
{% if expanded %}
|
||||
{{- block('choice_widget_expanded') -}}
|
||||
{% else %}
|
||||
{{- block('choice_widget_collapsed') -}}
|
||||
{% endif %}
|
||||
{%- endblock choice_widget -%}
|
||||
|
||||
{%- block choice_widget_expanded -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- for child in form %}
|
||||
{{- form_widget(child) -}}
|
||||
{{- form_label(child, null, {translation_domain: choice_translation_domain}) -}}
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{%- endblock choice_widget_expanded -%}
|
||||
|
||||
{%- block choice_widget_collapsed -%}
|
||||
{%- if required and placeholder is none and not placeholder_in_choices and not multiple and (attr.size is not defined or attr.size <= 1) -%}
|
||||
{% set required = false %}
|
||||
{%- endif -%}
|
||||
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
|
||||
{%- if placeholder is not none -%}
|
||||
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder != '' ? (translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain)) }}</option>
|
||||
{%- endif -%}
|
||||
{%- if preferred_choices|length > 0 -%}
|
||||
{% set options = preferred_choices %}
|
||||
{% set render_preferred_choices = true %}
|
||||
{{- block('choice_widget_options') -}}
|
||||
{%- if choices|length > 0 and separator is not none -%}
|
||||
<option disabled="disabled">{{ separator }}</option>
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- set options = choices -%}
|
||||
{%- set render_preferred_choices = false -%}
|
||||
{{- block('choice_widget_options') -}}
|
||||
</select>
|
||||
{%- endblock choice_widget_collapsed -%}
|
||||
|
||||
{%- block choice_widget_options -%}
|
||||
{% for group_label, choice in options %}
|
||||
{%- if choice is iterable -%}
|
||||
<optgroup label="{{ choice_translation_domain is same as(false) ? group_label : group_label|trans({}, choice_translation_domain) }}">
|
||||
{% set options = choice %}
|
||||
{{- block('choice_widget_options') -}}
|
||||
</optgroup>
|
||||
{%- else -%}
|
||||
<option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if not render_preferred_choices|default(false) and choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans(choice.labelTranslationParameters, choice_translation_domain) }}</option>
|
||||
{%- endif -%}
|
||||
{% endfor %}
|
||||
{%- endblock choice_widget_options -%}
|
||||
|
||||
{%- block checkbox_widget -%}
|
||||
<input type="checkbox" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
|
||||
{%- endblock checkbox_widget -%}
|
||||
|
||||
{%- block radio_widget -%}
|
||||
<input type="radio" {{ block('widget_attributes') }}{% if value is defined %} value="{{ value }}"{% endif %}{% if checked %} checked="checked"{% endif %} />
|
||||
{%- endblock radio_widget -%}
|
||||
|
||||
{%- block datetime_widget -%}
|
||||
{% if widget == 'single_text' %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{- form_errors(form.date) -}}
|
||||
{{- form_errors(form.time) -}}
|
||||
{{- form_widget(form.date) -}}
|
||||
{{- form_widget(form.time) -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock datetime_widget -%}
|
||||
|
||||
{%- block date_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- else -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{- date_pattern|replace({
|
||||
'{{ year }}': form_widget(form.year),
|
||||
'{{ month }}': form_widget(form.month),
|
||||
'{{ day }}': form_widget(form.day),
|
||||
})|raw -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock date_widget -%}
|
||||
|
||||
{%- block time_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- else -%}
|
||||
{%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{ form_widget(form.hour, vars) }}{% if with_minutes %}:{{ form_widget(form.minute, vars) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second, vars) }}{% endif %}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock time_widget -%}
|
||||
|
||||
{%- block dateinterval_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- else -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{- form_errors(form) -}}
|
||||
<table class="{{ table_class|default('') }}" role="presentation">
|
||||
<thead>
|
||||
<tr>
|
||||
{%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%}
|
||||
{%- if with_months %}<th>{{ form_label(form.months) }}</th>{% endif -%}
|
||||
{%- if with_weeks %}<th>{{ form_label(form.weeks) }}</th>{% endif -%}
|
||||
{%- if with_days %}<th>{{ form_label(form.days) }}</th>{% endif -%}
|
||||
{%- if with_hours %}<th>{{ form_label(form.hours) }}</th>{% endif -%}
|
||||
{%- if with_minutes %}<th>{{ form_label(form.minutes) }}</th>{% endif -%}
|
||||
{%- if with_seconds %}<th>{{ form_label(form.seconds) }}</th>{% endif -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
{%- if with_years %}<td>{{ form_widget(form.years) }}</td>{% endif -%}
|
||||
{%- if with_months %}<td>{{ form_widget(form.months) }}</td>{% endif -%}
|
||||
{%- if with_weeks %}<td>{{ form_widget(form.weeks) }}</td>{% endif -%}
|
||||
{%- if with_days %}<td>{{ form_widget(form.days) }}</td>{% endif -%}
|
||||
{%- if with_hours %}<td>{{ form_widget(form.hours) }}</td>{% endif -%}
|
||||
{%- if with_minutes %}<td>{{ form_widget(form.minutes) }}</td>{% endif -%}
|
||||
{%- if with_seconds %}<td>{{ form_widget(form.seconds) }}</td>{% endif -%}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock dateinterval_widget -%}
|
||||
|
||||
{%- block number_widget -%}
|
||||
{# type="number" doesn't work with floats in localized formats #}
|
||||
{%- set type = type|default('text') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock number_widget -%}
|
||||
|
||||
{%- block integer_widget -%}
|
||||
{%- set type = type|default('number') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock integer_widget -%}
|
||||
|
||||
{%- block money_widget -%}
|
||||
{{ money_pattern|form_encode_currency(block('form_widget_simple')) }}
|
||||
{%- endblock money_widget -%}
|
||||
|
||||
{%- block url_widget -%}
|
||||
{%- set type = type|default('url') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock url_widget -%}
|
||||
|
||||
{%- block search_widget -%}
|
||||
{%- set type = type|default('search') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock search_widget -%}
|
||||
|
||||
{%- block percent_widget -%}
|
||||
{%- set type = type|default('text') -%}
|
||||
{{ block('form_widget_simple') }}{% if symbol %} {{ symbol|default('%') }}{% endif %}
|
||||
{%- endblock percent_widget -%}
|
||||
|
||||
{%- block password_widget -%}
|
||||
{%- set type = type|default('password') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock password_widget -%}
|
||||
|
||||
{%- block hidden_widget -%}
|
||||
{%- set type = type|default('hidden') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock hidden_widget -%}
|
||||
|
||||
{%- block email_widget -%}
|
||||
{%- set type = type|default('email') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock email_widget -%}
|
||||
|
||||
{%- block range_widget -%}
|
||||
{% set type = type|default('range') %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endblock range_widget %}
|
||||
|
||||
{%- block button_widget -%}
|
||||
{%- if label is empty -%}
|
||||
{%- if label_format is not empty -%}
|
||||
{% set label = label_format|replace({
|
||||
'%name%': name,
|
||||
'%id%': id,
|
||||
}) %}
|
||||
{%- elseif label is not same as(false) -%}
|
||||
{% set label = name|humanize %}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label -}}
|
||||
{%- else -%}
|
||||
{{- label|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</button>
|
||||
{%- endblock button_widget -%}
|
||||
|
||||
{%- block submit_widget -%}
|
||||
{%- set type = type|default('submit') -%}
|
||||
{{ block('button_widget') }}
|
||||
{%- endblock submit_widget -%}
|
||||
|
||||
{%- block reset_widget -%}
|
||||
{%- set type = type|default('reset') -%}
|
||||
{{ block('button_widget') }}
|
||||
{%- endblock reset_widget -%}
|
||||
|
||||
{%- block tel_widget -%}
|
||||
{%- set type = type|default('tel') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock tel_widget -%}
|
||||
|
||||
{%- block color_widget -%}
|
||||
{%- set type = type|default('color') -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- endblock color_widget -%}
|
||||
|
||||
{%- block week_widget -%}
|
||||
{%- if widget == 'single_text' -%}
|
||||
{{ block('form_widget_simple') }}
|
||||
{%- else -%}
|
||||
{%- set vars = widget == 'text' ? { 'attr': { 'size': 1 }} : {} -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{{ form_widget(form.year, vars) }}-{{ form_widget(form.week, vars) }}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
{%- endblock week_widget -%}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{%- block form_label -%}
|
||||
{% if label is not same as(false) -%}
|
||||
{% if not compound -%}
|
||||
{% set label_attr = label_attr|merge({'for': id}) %}
|
||||
{%- endif -%}
|
||||
{% if required -%}
|
||||
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
|
||||
{%- endif -%}
|
||||
{% if label is empty -%}
|
||||
{%- if label_format is not empty -%}
|
||||
{% set label = label_format|replace({
|
||||
'%name%': name,
|
||||
'%id%': id,
|
||||
}) %}
|
||||
{%- else -%}
|
||||
{% set label = name|humanize %}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
<{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label -}}
|
||||
{%- else -%}
|
||||
{{- label|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if label_html is same as(false) -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- label|trans(label_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</{{ element|default('label') }}>
|
||||
{%- endif -%}
|
||||
{%- endblock form_label -%}
|
||||
|
||||
{%- block button_label -%}{%- endblock -%}
|
||||
|
||||
{# Help #}
|
||||
|
||||
{% block form_help -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set help_attr = help_attr|merge({class: (help_attr.class|default('') ~ ' help-text')|trim}) -%}
|
||||
<p id="{{ id }}_help"{% with { attr: help_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{%- if translation_domain is same as(false) -%}
|
||||
{%- if help_html is same as(false) -%}
|
||||
{{- help -}}
|
||||
{%- else -%}
|
||||
{{- help|raw -}}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- if help_html is same as(false) -%}
|
||||
{{- help|trans(help_translation_parameters, translation_domain) -}}
|
||||
{%- else -%}
|
||||
{{- help|trans(help_translation_parameters, translation_domain)|raw -}}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
</p>
|
||||
{%- endif -%}
|
||||
{%- endblock form_help %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{%- block repeated_row -%}
|
||||
{#
|
||||
No need to render the errors here, as all errors are mapped
|
||||
to the first child (see RepeatedTypeValidatorExtension).
|
||||
#}
|
||||
{{- block('form_rows') -}}
|
||||
{%- endblock repeated_row -%}
|
||||
|
||||
{%- block form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_label(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
</div>
|
||||
{%- endblock form_row -%}
|
||||
|
||||
{%- block button_row -%}
|
||||
<div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_widget(form) -}}
|
||||
</div>
|
||||
{%- endblock button_row -%}
|
||||
|
||||
{%- block hidden_row -%}
|
||||
{{ form_widget(form) }}
|
||||
{%- endblock hidden_row -%}
|
||||
|
||||
{# Misc #}
|
||||
|
||||
{%- block form -%}
|
||||
{{ form_start(form) }}
|
||||
{{- form_widget(form) -}}
|
||||
{{ form_end(form) }}
|
||||
{%- endblock form -%}
|
||||
|
||||
{%- block form_start -%}
|
||||
{%- do form.setMethodRendered() -%}
|
||||
{% set method = method|upper %}
|
||||
{%- if method in ["GET", "POST"] -%}
|
||||
{% set form_method = method %}
|
||||
{%- else -%}
|
||||
{% set form_method = "POST" %}
|
||||
{%- endif -%}
|
||||
<form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{{ block('attributes') }}{% if multipart %} enctype="multipart/form-data"{% endif %}>
|
||||
{%- if form_method != method -%}
|
||||
<input type="hidden" name="_method" value="{{ method }}" />
|
||||
{%- endif -%}
|
||||
{%- endblock form_start -%}
|
||||
|
||||
{%- block form_end -%}
|
||||
{%- if not render_rest is defined or render_rest -%}
|
||||
{{ form_rest(form) }}
|
||||
{%- endif -%}
|
||||
</form>
|
||||
{%- endblock form_end -%}
|
||||
|
||||
{%- block form_errors -%}
|
||||
{%- if errors|length > 0 -%}
|
||||
<ul>
|
||||
{%- for error in errors -%}
|
||||
<li>{{ error.message }}</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
{%- endblock form_errors -%}
|
||||
|
||||
{%- block form_rest -%}
|
||||
{% for child in form -%}
|
||||
{% if not child.rendered %}
|
||||
{{- form_row(child) -}}
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
|
||||
{% if not form.methodRendered and form is rootform %}
|
||||
{%- do form.setMethodRendered() -%}
|
||||
{% set method = method|upper %}
|
||||
{%- if method in ["GET", "POST"] -%}
|
||||
{% set form_method = method %}
|
||||
{%- else -%}
|
||||
{% set form_method = "POST" %}
|
||||
{%- endif -%}
|
||||
|
||||
{%- if form_method != method -%}
|
||||
<input type="hidden" name="_method" value="{{ method }}" />
|
||||
{%- endif -%}
|
||||
{% endif -%}
|
||||
{% endblock form_rest %}
|
||||
|
||||
{# Support #}
|
||||
|
||||
{%- block form_rows -%}
|
||||
{% for child in form|filter(child => not child.rendered) %}
|
||||
{{- form_row(child) -}}
|
||||
{% endfor %}
|
||||
{%- endblock form_rows -%}
|
||||
|
||||
{%- block widget_attributes -%}
|
||||
id="{{ id }}" name="{{ full_name }}"
|
||||
{%- if disabled %} disabled="disabled"{% endif -%}
|
||||
{%- if required %} required="required"{% endif -%}
|
||||
{{ block('attributes') }}
|
||||
{%- endblock widget_attributes -%}
|
||||
|
||||
{%- block widget_container_attributes -%}
|
||||
{%- if id is not empty %}id="{{ id }}"{% endif -%}
|
||||
{{ block('attributes') }}
|
||||
{%- endblock widget_container_attributes -%}
|
||||
|
||||
{%- block button_attributes -%}
|
||||
id="{{ id }}" name="{{ full_name }}"{% if disabled %} disabled="disabled"{% endif -%}
|
||||
{{ block('attributes') }}
|
||||
{%- endblock button_attributes -%}
|
||||
|
||||
{% block attributes -%}
|
||||
{%- for attrname, attrvalue in attr -%}
|
||||
{{- " " -}}
|
||||
{%- if attrname in ['placeholder', 'title'] -%}
|
||||
{{- attrname }}="{{ translation_domain is same as(false) or attrvalue is null ? attrvalue : attrvalue|trans(attr_translation_parameters, translation_domain) }}"
|
||||
{%- elseif attrvalue is same as(true) -%}
|
||||
{{- attrname }}="{{ attrname }}"
|
||||
{%- elseif attrvalue is not same as(false) -%}
|
||||
{{- attrname }}="{{ attrvalue }}"
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endblock attributes -%}
|
50
vendor/symfony/twig-bridge/Resources/views/Form/form_table_layout.html.twig
vendored
Normal file
50
vendor/symfony/twig-bridge/Resources/views/Form/form_table_layout.html.twig
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
{% use "form_div_layout.html.twig" %}
|
||||
|
||||
{%- block form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<tr{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
|
||||
<td>
|
||||
{{- form_label(form) -}}
|
||||
</td>
|
||||
<td>
|
||||
{{- form_errors(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endblock form_row -%}
|
||||
|
||||
{%- block button_row -%}
|
||||
<tr{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
|
||||
<td></td>
|
||||
<td>
|
||||
{{- form_widget(form) -}}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endblock button_row -%}
|
||||
|
||||
{%- block hidden_row -%}
|
||||
{%- set style = row_attr.style is defined ? (row_attr.style ~ (row_attr.style|trim|last != ';' ? '; ')) -%}
|
||||
<tr{% with {attr: row_attr|merge({style: (style ~ ' display: none')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<td colspan="2">
|
||||
{{- form_widget(form) -}}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endblock hidden_row -%}
|
||||
|
||||
{%- block form_widget_compound -%}
|
||||
<table {{ block('widget_container_attributes') }}>
|
||||
{%- if form is rootform and errors|length > 0 -%}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{{- form_errors(form) -}}
|
||||
</td>
|
||||
</tr>
|
||||
{%- endif -%}
|
||||
{{- block('form_rows') -}}
|
||||
{{- form_rest(form) -}}
|
||||
</table>
|
||||
{%- endblock form_widget_compound -%}
|
340
vendor/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig
vendored
Normal file
340
vendor/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig
vendored
Normal file
@ -0,0 +1,340 @@
|
||||
{% extends "form_div_layout.html.twig" %}
|
||||
|
||||
{# Based on Foundation 5 Doc #}
|
||||
{# Widgets #}
|
||||
|
||||
{% block form_widget_simple -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_widget_simple %}
|
||||
|
||||
{% block textarea_widget -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
{{- parent() -}}
|
||||
{%- endblock textarea_widget %}
|
||||
|
||||
{% block button_widget -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' button')|trim}) %}
|
||||
{{- parent() -}}
|
||||
{%- endblock button_widget %}
|
||||
|
||||
{% block money_widget -%}
|
||||
<div class="row collapse">
|
||||
{% set prepend = '{{' == money_pattern[0:2] %}
|
||||
{% if not prepend %}
|
||||
<div class="small-3 large-2 columns">
|
||||
<span class="prefix">{{ money_pattern|form_encode_currency }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="small-9 large-10 columns">
|
||||
{{- block('form_widget_simple') -}}
|
||||
</div>
|
||||
{% if prepend %}
|
||||
<div class="small-3 large-2 columns">
|
||||
<span class="postfix">{{ money_pattern|form_encode_currency }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{%- endblock money_widget %}
|
||||
|
||||
{% block percent_widget -%}
|
||||
<div class="row collapse">
|
||||
{%- if symbol -%}
|
||||
<div class="small-9 large-10 columns">
|
||||
{{- block('form_widget_simple') -}}
|
||||
</div>
|
||||
<div class="small-3 large-2 columns">
|
||||
<span class="postfix">{{ symbol|default('%') }}</span>
|
||||
</div>
|
||||
{%- else -%}
|
||||
<div class="small-12 large-12 columns">
|
||||
{{- block('form_widget_simple') -}}
|
||||
</div>
|
||||
{%- endif -%}
|
||||
</div>
|
||||
{%- endblock percent_widget %}
|
||||
|
||||
{% block datetime_widget -%}
|
||||
{% if widget == 'single_text' %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% else %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %}
|
||||
<div class="row">
|
||||
<div class="large-7 columns">{{ form_errors(form.date) }}</div>
|
||||
<div class="large-5 columns">{{ form_errors(form.time) }}</div>
|
||||
</div>
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
<div class="large-7 columns">{{ form_widget(form.date, { datetime: true } ) }}</div>
|
||||
<div class="large-5 columns">{{ form_widget(form.time, { datetime: true } ) }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endblock datetime_widget %}
|
||||
|
||||
{% block date_widget -%}
|
||||
{% if widget == 'single_text' %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% else %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %}
|
||||
{% if datetime is not defined or not datetime %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{% endif %}
|
||||
{{- date_pattern|replace({
|
||||
'{{ year }}': '<div class="large-4 columns">' ~ form_widget(form.year) ~ '</div>',
|
||||
'{{ month }}': '<div class="large-4 columns">' ~ form_widget(form.month) ~ '</div>',
|
||||
'{{ day }}': '<div class="large-4 columns">' ~ form_widget(form.day) ~ '</div>',
|
||||
})|raw -}}
|
||||
{% if datetime is not defined or not datetime %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{%- endblock date_widget %}
|
||||
|
||||
{% block time_widget -%}
|
||||
{% if widget == 'single_text' %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% else %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %}
|
||||
{% if datetime is not defined or false == datetime %}
|
||||
<div {{ block('widget_container_attributes') -}}>
|
||||
{% endif %}
|
||||
{% if with_seconds %}
|
||||
<div class="large-4 columns">{{ form_widget(form.hour) }}</div>
|
||||
<div class="large-4 columns">
|
||||
<div class="row collapse">
|
||||
<div class="small-3 large-2 columns">
|
||||
<span class="prefix">:</span>
|
||||
</div>
|
||||
<div class="small-9 large-10 columns">
|
||||
{{ form_widget(form.minute) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="large-4 columns">
|
||||
<div class="row collapse">
|
||||
<div class="small-3 large-2 columns">
|
||||
<span class="prefix">:</span>
|
||||
</div>
|
||||
<div class="small-9 large-10 columns">
|
||||
{{ form_widget(form.second) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="large-6 columns">{{ form_widget(form.hour) }}</div>
|
||||
<div class="large-6 columns">
|
||||
<div class="row collapse">
|
||||
<div class="small-3 large-2 columns">
|
||||
<span class="prefix">:</span>
|
||||
</div>
|
||||
<div class="small-9 large-10 columns">
|
||||
{{ form_widget(form.minute) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if datetime is not defined or false == datetime %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{%- endblock time_widget %}
|
||||
|
||||
{% block choice_widget_collapsed -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
|
||||
{% if multiple -%}
|
||||
{% set attr = attr|merge({style: (attr.style|default('') ~ ' height: auto; background-image: none;')|trim}) %}
|
||||
{% endif %}
|
||||
|
||||
{% if required and placeholder is none and not placeholder_in_choices and not multiple -%}
|
||||
{% set required = false %}
|
||||
{%- endif -%}
|
||||
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple" data-customforms="disabled"{% endif %}>
|
||||
{% if placeholder is not none -%}
|
||||
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ translation_domain is same as(false) ? placeholder : placeholder|trans({}, translation_domain) }}</option>
|
||||
{%- endif %}
|
||||
{%- if preferred_choices|length > 0 -%}
|
||||
{% set options = preferred_choices %}
|
||||
{% set render_preferred_choices = true %}
|
||||
{{- block('choice_widget_options') -}}
|
||||
{% if choices|length > 0 and separator is not none -%}
|
||||
<option disabled="disabled">{{ separator }}</option>
|
||||
{%- endif %}
|
||||
{%- endif -%}
|
||||
{% set options = choices -%}
|
||||
{%- set render_preferred_choices = false -%}
|
||||
{{- block('choice_widget_options') -}}
|
||||
</select>
|
||||
{%- endblock choice_widget_collapsed %}
|
||||
|
||||
{% block choice_widget_expanded -%}
|
||||
{% if '-inline' in label_attr.class|default('') %}
|
||||
<ul class="inline-list">
|
||||
{% for child in form %}
|
||||
<li>{{ form_widget(child, {
|
||||
parent_label_class: label_attr.class|default(''),
|
||||
}) }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{% for child in form %}
|
||||
{{ form_widget(child, {
|
||||
parent_label_class: label_attr.class|default(''),
|
||||
}) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endblock choice_widget_expanded %}
|
||||
|
||||
{% block checkbox_widget -%}
|
||||
{% set parent_label_class = parent_label_class|default('') %}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
{% if 'checkbox-inline' in parent_label_class %}
|
||||
{{ form_label(form, null, { widget: parent() }) }}
|
||||
{% else %}
|
||||
<div class="checkbox">
|
||||
{{ form_label(form, null, { widget: parent() }) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endblock checkbox_widget %}
|
||||
|
||||
{% block radio_widget -%}
|
||||
{% set parent_label_class = parent_label_class|default('') %}
|
||||
{% if 'radio-inline' in parent_label_class %}
|
||||
{{ form_label(form, null, { widget: parent() }) }}
|
||||
{% else %}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
<div class="radio">
|
||||
{{ form_label(form, null, { widget: parent() }) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{%- endblock radio_widget %}
|
||||
|
||||
{# Labels #}
|
||||
|
||||
{% block form_label -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_label %}
|
||||
|
||||
{% block choice_label -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
{# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #}
|
||||
{% set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) %}
|
||||
{{- block('form_label') -}}
|
||||
{%- endblock choice_label %}
|
||||
|
||||
{% block checkbox_label -%}
|
||||
{{- block('checkbox_radio_label') -}}
|
||||
{%- endblock checkbox_label %}
|
||||
|
||||
{% block radio_label -%}
|
||||
{{- block('checkbox_radio_label') -}}
|
||||
{%- endblock radio_label %}
|
||||
|
||||
{% block checkbox_radio_label -%}
|
||||
{% if required %}
|
||||
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %}
|
||||
{% endif %}
|
||||
{% if errors|length > 0 -%}
|
||||
{% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %}
|
||||
{% endif %}
|
||||
{% if label is empty %}
|
||||
{%- if label_format is not empty -%}
|
||||
{% set label = label_format|replace({
|
||||
'%name%': name,
|
||||
'%id%': id,
|
||||
}) %}
|
||||
{%- else -%}
|
||||
{% set label = name|humanize %}
|
||||
{%- endif -%}
|
||||
{% endif %}
|
||||
<label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}>
|
||||
{{ widget|raw }}
|
||||
{{ translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain) }}
|
||||
</label>
|
||||
{%- endblock checkbox_radio_label %}
|
||||
|
||||
{# Rows #}
|
||||
|
||||
{% block form_row -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<div class="large-12 columns{% if (not compound or force_error|default(false)) and not valid %} error{% endif %}">
|
||||
{{- form_label(form) -}}
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_help(form) -}}
|
||||
{{- form_errors(form) -}}
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock form_row %}
|
||||
|
||||
{% block choice_row -%}
|
||||
{% set force_error = true %}
|
||||
{{ block('form_row') }}
|
||||
{%- endblock choice_row %}
|
||||
|
||||
{% block date_row -%}
|
||||
{% set force_error = true %}
|
||||
{{ block('form_row') }}
|
||||
{%- endblock date_row %}
|
||||
|
||||
{% block time_row -%}
|
||||
{% set force_error = true %}
|
||||
{{ block('form_row') }}
|
||||
{%- endblock time_row %}
|
||||
|
||||
{% block datetime_row -%}
|
||||
{% set force_error = true %}
|
||||
{{ block('form_row') }}
|
||||
{%- endblock datetime_row %}
|
||||
|
||||
{% block checkbox_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<div class="large-12 columns{% if not valid %} error{% endif %}">
|
||||
{{ form_widget(form) }}
|
||||
{{- form_help(form) -}}
|
||||
{{ form_errors(form) }}
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock checkbox_row %}
|
||||
|
||||
{% block radio_row -%}
|
||||
<div{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' row')|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<div class="large-12 columns{% if not valid %} error{% endif %}">
|
||||
{{ form_widget(form) }}
|
||||
{{- form_help(form) -}}
|
||||
{{ form_errors(form) }}
|
||||
</div>
|
||||
</div>
|
||||
{%- endblock radio_row %}
|
||||
|
||||
{# Errors #}
|
||||
|
||||
{% block form_errors -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% if form is not rootform %}<small class="error">{% else %}<div data-alert class="alert-box alert">{% endif %}
|
||||
{%- for error in errors -%}
|
||||
{{ error.message }}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{%- endfor -%}
|
||||
{% if form is not rootform %}</small>{% else %}</div>{% endif %}
|
||||
{%- endif %}
|
||||
{%- endblock form_errors %}
|
50
vendor/symfony/twig-bridge/Resources/views/Form/foundation_6_layout.html.twig
vendored
Normal file
50
vendor/symfony/twig-bridge/Resources/views/Form/foundation_6_layout.html.twig
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
{% extends "form_div_layout.html.twig" %}
|
||||
|
||||
{%- block checkbox_row -%}
|
||||
{%- set parent_class = parent_class|default(attr.class|default('')) -%}
|
||||
{%- if 'switch-input' in parent_class -%}
|
||||
{{- form_label(form) -}}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' switch-input')|trim}) -%}
|
||||
{{- form_widget(form) -}}
|
||||
<label class="switch-paddle" for="{{ form.vars.id }}"></label>
|
||||
{{- form_errors(form) -}}
|
||||
{%- else -%}
|
||||
{{- block('form_row') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock checkbox_row -%}
|
||||
|
||||
{% block money_widget -%}
|
||||
{% set prepend = not (money_pattern starts with '{{') %}
|
||||
{% set append = not (money_pattern ends with '}}') %}
|
||||
{% if prepend or append %}
|
||||
<div class="input-group">
|
||||
{% if prepend %}
|
||||
<span class="input-group-label">{{ money_pattern|form_encode_currency }}</span>
|
||||
{% endif %}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' input-group-field')|trim}) %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% if append %}
|
||||
<span class="input-group-label">{{ money_pattern|form_encode_currency }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{% endif %}
|
||||
{%- endblock money_widget %}
|
||||
|
||||
{% block percent_widget -%}
|
||||
{%- if symbol -%}
|
||||
<div class="input-group">
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' input-group-field')|trim}) %}
|
||||
{{- block('form_widget_simple') -}}
|
||||
<span class="input-group-label">{{ symbol|default('%') }}</span>
|
||||
</div>
|
||||
{%- else -%}
|
||||
{{- block('form_widget_simple') -}}
|
||||
{%- endif -%}
|
||||
{%- endblock percent_widget %}
|
||||
|
||||
{% block button_widget -%}
|
||||
{% set attr = attr|merge({class: (attr.class|default('') ~ ' button')|trim}) %}
|
||||
{{- parent() -}}
|
||||
{%- endblock button_widget %}
|
69
vendor/symfony/twig-bridge/Resources/views/Form/tailwind_2_layout.html.twig
vendored
Normal file
69
vendor/symfony/twig-bridge/Resources/views/Form/tailwind_2_layout.html.twig
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
{% use 'form_div_layout.html.twig' %}
|
||||
|
||||
{%- block form_row -%}
|
||||
{%- set row_attr = row_attr|merge({ class: row_attr.class|default(row_class|default('mb-6')) }) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_row -%}
|
||||
|
||||
{%- block widget_attributes -%}
|
||||
{%- set attr = attr|merge({ class: attr.class|default(widget_class|default('mt-1 w-full')) ~ (disabled ? ' ' ~ widget_disabled_class|default('border-gray-300 text-gray-500')) ~ (errors|length ? ' ' ~ widget_errors_class|default('border-red-700')) }) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock widget_attributes -%}
|
||||
|
||||
{%- block form_label -%}
|
||||
{%- set label_attr = label_attr|merge({ class: label_attr.class|default(label_class|default('block text-gray-800')) }) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_label -%}
|
||||
|
||||
{%- block form_help -%}
|
||||
{%- set help_attr = help_attr|merge({ class: help_attr.class|default(help_class|default('mt-1 text-gray-600')) }) -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock form_help -%}
|
||||
|
||||
{%- block form_errors -%}
|
||||
{%- if errors|length > 0 -%}
|
||||
<ul>
|
||||
{%- for error in errors -%}
|
||||
<li class="{{ error_item_class|default('text-red-700') }}">{{ error.message }}</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
{%- endblock form_errors -%}
|
||||
|
||||
{%- block choice_widget_expanded -%}
|
||||
{%- set attr = attr|merge({ class: attr.class|default('mt-2') }) -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- for child in form %}
|
||||
<div class="flex items-center">
|
||||
{{- form_widget(child) -}}
|
||||
{{- form_label(child, null, { translation_domain: choice_translation_domain }) -}}
|
||||
</div>
|
||||
{% endfor -%}
|
||||
</div>
|
||||
{%- endblock choice_widget_expanded -%}
|
||||
|
||||
{%- block checkbox_row -%}
|
||||
{%- set row_attr = row_attr|merge({ class: row_attr.class|default(row_class|default('mb-6')) }) -%}
|
||||
{%- set widget_attr = {} -%}
|
||||
{%- if help is not empty -%}
|
||||
{%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%}
|
||||
{%- endif -%}
|
||||
<div{% with {attr: row_attr} %}{{ block('attributes') }}{% endwith %}>
|
||||
{{- form_errors(form) -}}
|
||||
<div class="inline-flex items-center">
|
||||
{{- form_widget(form, widget_attr) -}}
|
||||
{{- form_label(form) -}}
|
||||
</div>
|
||||
{{- form_help(form) -}}
|
||||
</div>
|
||||
{%- endblock checkbox_row -%}
|
||||
|
||||
{%- block checkbox_widget -%}
|
||||
{%- set widget_class = widget_class|default('mr-2') -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock checkbox_widget -%}
|
||||
|
||||
{%- block radio_widget -%}
|
||||
{%- set widget_class = widget_class|default('mr-2') -%}
|
||||
{{- parent() -}}
|
||||
{%- endblock radio_widget -%}
|
53
vendor/symfony/twig-bridge/TokenParser/DumpTokenParser.php
vendored
Normal file
53
vendor/symfony/twig-bridge/TokenParser/DumpTokenParser.php
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
<?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\TokenParser;
|
||||
|
||||
use Symfony\Bridge\Twig\Node\DumpNode;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Token;
|
||||
use Twig\TokenParser\AbstractTokenParser;
|
||||
|
||||
/**
|
||||
* Token Parser for the 'dump' tag.
|
||||
*
|
||||
* Dump variables with:
|
||||
*
|
||||
* {% dump %}
|
||||
* {% dump foo %}
|
||||
* {% dump foo, bar %}
|
||||
*
|
||||
* @author Julien Galenski <julien.galenski@gmail.com>
|
||||
*/
|
||||
final class DumpTokenParser extends AbstractTokenParser
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse(Token $token): Node
|
||||
{
|
||||
$values = null;
|
||||
if (!$this->parser->getStream()->test(Token::BLOCK_END_TYPE)) {
|
||||
$values = $this->parser->getExpressionParser()->parseMultitargetExpression();
|
||||
}
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new DumpNode($this->parser->getVarName(), $values, $token->getLine(), $this->getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTag(): string
|
||||
{
|
||||
return 'dump';
|
||||
}
|
||||
}
|
64
vendor/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php
vendored
Normal file
64
vendor/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?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\TokenParser;
|
||||
|
||||
use Symfony\Bridge\Twig\Node\FormThemeNode;
|
||||
use Twig\Node\Expression\ArrayExpression;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Token;
|
||||
use Twig\TokenParser\AbstractTokenParser;
|
||||
|
||||
/**
|
||||
* Token Parser for the 'form_theme' tag.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class FormThemeTokenParser extends AbstractTokenParser
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse(Token $token): Node
|
||||
{
|
||||
$lineno = $token->getLine();
|
||||
$stream = $this->parser->getStream();
|
||||
|
||||
$form = $this->parser->getExpressionParser()->parseExpression();
|
||||
$only = false;
|
||||
|
||||
if ($this->parser->getStream()->test(Token::NAME_TYPE, 'with')) {
|
||||
$this->parser->getStream()->next();
|
||||
$resources = $this->parser->getExpressionParser()->parseExpression();
|
||||
|
||||
if ($this->parser->getStream()->nextIf(Token::NAME_TYPE, 'only')) {
|
||||
$only = true;
|
||||
}
|
||||
} else {
|
||||
$resources = new ArrayExpression([], $stream->getCurrent()->getLine());
|
||||
do {
|
||||
$resources->addElement($this->parser->getExpressionParser()->parseExpression());
|
||||
} while (!$stream->test(Token::BLOCK_END_TYPE));
|
||||
}
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new FormThemeNode($form, $resources, $lineno, $this->getTag(), $only);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTag(): string
|
||||
{
|
||||
return 'form_theme';
|
||||
}
|
||||
}
|
64
vendor/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php
vendored
Normal file
64
vendor/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
<?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\TokenParser;
|
||||
|
||||
use Symfony\Bridge\Twig\Node\StopwatchNode;
|
||||
use Twig\Node\Expression\AssignNameExpression;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Token;
|
||||
use Twig\TokenParser\AbstractTokenParser;
|
||||
|
||||
/**
|
||||
* Token Parser for the stopwatch tag.
|
||||
*
|
||||
* @author Wouter J <wouter@wouterj.nl>
|
||||
*/
|
||||
final class StopwatchTokenParser extends AbstractTokenParser
|
||||
{
|
||||
protected $stopwatchIsAvailable;
|
||||
|
||||
public function __construct(bool $stopwatchIsAvailable)
|
||||
{
|
||||
$this->stopwatchIsAvailable = $stopwatchIsAvailable;
|
||||
}
|
||||
|
||||
public function parse(Token $token): Node
|
||||
{
|
||||
$lineno = $token->getLine();
|
||||
$stream = $this->parser->getStream();
|
||||
|
||||
// {% stopwatch 'bar' %}
|
||||
$name = $this->parser->getExpressionParser()->parseExpression();
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
// {% endstopwatch %}
|
||||
$body = $this->parser->subparse([$this, 'decideStopwatchEnd'], true);
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
if ($this->stopwatchIsAvailable) {
|
||||
return new StopwatchNode($name, $body, new AssignNameExpression($this->parser->getVarName(), $token->getLine()), $lineno, $this->getTag());
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
public function decideStopwatchEnd(Token $token): bool
|
||||
{
|
||||
return $token->test('endstopwatch');
|
||||
}
|
||||
|
||||
public function getTag(): string
|
||||
{
|
||||
return 'stopwatch';
|
||||
}
|
||||
}
|
45
vendor/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php
vendored
Normal file
45
vendor/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
<?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\TokenParser;
|
||||
|
||||
use Symfony\Bridge\Twig\Node\TransDefaultDomainNode;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Token;
|
||||
use Twig\TokenParser\AbstractTokenParser;
|
||||
|
||||
/**
|
||||
* Token Parser for the 'trans_default_domain' tag.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class TransDefaultDomainTokenParser extends AbstractTokenParser
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse(Token $token): Node
|
||||
{
|
||||
$expr = $this->parser->getExpressionParser()->parseExpression();
|
||||
|
||||
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new TransDefaultDomainNode($expr, $token->getLine(), $this->getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTag(): string
|
||||
{
|
||||
return 'trans_default_domain';
|
||||
}
|
||||
}
|
95
vendor/symfony/twig-bridge/TokenParser/TransTokenParser.php
vendored
Normal file
95
vendor/symfony/twig-bridge/TokenParser/TransTokenParser.php
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
<?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\TokenParser;
|
||||
|
||||
use Symfony\Bridge\Twig\Node\TransNode;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\Node\Expression\AbstractExpression;
|
||||
use Twig\Node\Expression\ArrayExpression;
|
||||
use Twig\Node\Node;
|
||||
use Twig\Node\TextNode;
|
||||
use Twig\Token;
|
||||
use Twig\TokenParser\AbstractTokenParser;
|
||||
|
||||
/**
|
||||
* Token Parser for the 'trans' tag.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
final class TransTokenParser extends AbstractTokenParser
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse(Token $token): Node
|
||||
{
|
||||
$lineno = $token->getLine();
|
||||
$stream = $this->parser->getStream();
|
||||
|
||||
$count = null;
|
||||
$vars = new ArrayExpression([], $lineno);
|
||||
$domain = null;
|
||||
$locale = null;
|
||||
if (!$stream->test(Token::BLOCK_END_TYPE)) {
|
||||
if ($stream->test('count')) {
|
||||
// {% trans count 5 %}
|
||||
$stream->next();
|
||||
$count = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
if ($stream->test('with')) {
|
||||
// {% trans with vars %}
|
||||
$stream->next();
|
||||
$vars = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
if ($stream->test('from')) {
|
||||
// {% trans from "messages" %}
|
||||
$stream->next();
|
||||
$domain = $this->parser->getExpressionParser()->parseExpression();
|
||||
}
|
||||
|
||||
if ($stream->test('into')) {
|
||||
// {% trans into "fr" %}
|
||||
$stream->next();
|
||||
$locale = $this->parser->getExpressionParser()->parseExpression();
|
||||
} elseif (!$stream->test(Token::BLOCK_END_TYPE)) {
|
||||
throw new SyntaxError('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getSourceContext());
|
||||
}
|
||||
}
|
||||
|
||||
// {% trans %}message{% endtrans %}
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
$body = $this->parser->subparse([$this, 'decideTransFork'], true);
|
||||
|
||||
if (!$body instanceof TextNode && !$body instanceof AbstractExpression) {
|
||||
throw new SyntaxError('A message inside a trans tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext());
|
||||
}
|
||||
|
||||
$stream->expect(Token::BLOCK_END_TYPE);
|
||||
|
||||
return new TransNode($body, $domain, $count, $vars, $locale, $lineno, $this->getTag());
|
||||
}
|
||||
|
||||
public function decideTransFork(Token $token): bool
|
||||
{
|
||||
return $token->test(['endtrans']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTag(): string
|
||||
{
|
||||
return 'trans';
|
||||
}
|
||||
}
|
104
vendor/symfony/twig-bridge/Translation/TwigExtractor.php
vendored
Normal file
104
vendor/symfony/twig-bridge/Translation/TwigExtractor.php
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
<?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\Translation;
|
||||
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Translation\Extractor\AbstractFileExtractor;
|
||||
use Symfony\Component\Translation\Extractor\ExtractorInterface;
|
||||
use Symfony\Component\Translation\MessageCatalogue;
|
||||
use Twig\Environment;
|
||||
use Twig\Error\Error;
|
||||
use Twig\Source;
|
||||
|
||||
/**
|
||||
* TwigExtractor extracts translation messages from a twig template.
|
||||
*
|
||||
* @author Michel Salib <michelsalib@hotmail.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class TwigExtractor extends AbstractFileExtractor implements ExtractorInterface
|
||||
{
|
||||
/**
|
||||
* Default domain for found messages.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $defaultDomain = 'messages';
|
||||
|
||||
/**
|
||||
* Prefix for found message.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $prefix = '';
|
||||
|
||||
private $twig;
|
||||
|
||||
public function __construct(Environment $twig)
|
||||
{
|
||||
$this->twig = $twig;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function extract($resource, MessageCatalogue $catalogue)
|
||||
{
|
||||
foreach ($this->extractFiles($resource) as $file) {
|
||||
try {
|
||||
$this->extractTemplate(file_get_contents($file->getPathname()), $catalogue);
|
||||
} catch (Error $e) {
|
||||
// ignore errors, these should be fixed by using the linter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setPrefix(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
protected function extractTemplate(string $template, MessageCatalogue $catalogue)
|
||||
{
|
||||
$visitor = $this->twig->getExtension('Symfony\Bridge\Twig\Extension\TranslationExtension')->getTranslationNodeVisitor();
|
||||
$visitor->enable();
|
||||
|
||||
$this->twig->parse($this->twig->tokenize(new Source($template, '')));
|
||||
|
||||
foreach ($visitor->getMessages() as $message) {
|
||||
$catalogue->set(trim($message[0]), $this->prefix.trim($message[0]), $message[1] ?: $this->defaultDomain);
|
||||
}
|
||||
|
||||
$visitor->disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function canBeExtracted(string $file)
|
||||
{
|
||||
return $this->isFile($file) && 'twig' === pathinfo($file, \PATHINFO_EXTENSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function extractFromDirectory($directory)
|
||||
{
|
||||
$finder = new Finder();
|
||||
|
||||
return $finder->files()->name('*.twig')->in($directory);
|
||||
}
|
||||
}
|
107
vendor/symfony/twig-bridge/UndefinedCallableHandler.php
vendored
Normal file
107
vendor/symfony/twig-bridge/UndefinedCallableHandler.php
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
<?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;
|
||||
|
||||
use Symfony\Bundle\FullStack;
|
||||
use Twig\Error\SyntaxError;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
class UndefinedCallableHandler
|
||||
{
|
||||
private const FILTER_COMPONENTS = [
|
||||
'humanize' => 'form',
|
||||
'trans' => 'translation',
|
||||
'yaml_encode' => 'yaml',
|
||||
'yaml_dump' => 'yaml',
|
||||
];
|
||||
|
||||
private const FUNCTION_COMPONENTS = [
|
||||
'asset' => 'asset',
|
||||
'asset_version' => 'asset',
|
||||
'dump' => 'debug-bundle',
|
||||
'encore_entry_link_tags' => 'webpack-encore-bundle',
|
||||
'encore_entry_script_tags' => 'webpack-encore-bundle',
|
||||
'expression' => 'expression-language',
|
||||
'form_widget' => 'form',
|
||||
'form_errors' => 'form',
|
||||
'form_label' => 'form',
|
||||
'form_help' => 'form',
|
||||
'form_row' => 'form',
|
||||
'form_rest' => 'form',
|
||||
'form' => 'form',
|
||||
'form_start' => 'form',
|
||||
'form_end' => 'form',
|
||||
'csrf_token' => 'form',
|
||||
'logout_url' => 'security-http',
|
||||
'logout_path' => 'security-http',
|
||||
'is_granted' => 'security-core',
|
||||
'link' => 'web-link',
|
||||
'preload' => 'web-link',
|
||||
'dns_prefetch' => 'web-link',
|
||||
'preconnect' => 'web-link',
|
||||
'prefetch' => 'web-link',
|
||||
'prerender' => 'web-link',
|
||||
'workflow_can' => 'workflow',
|
||||
'workflow_transitions' => 'workflow',
|
||||
'workflow_has_marked_place' => 'workflow',
|
||||
'workflow_marked_places' => 'workflow',
|
||||
];
|
||||
|
||||
private const FULL_STACK_ENABLE = [
|
||||
'form' => 'enable "framework.form"',
|
||||
'security-core' => 'add the "SecurityBundle"',
|
||||
'security-http' => 'add the "SecurityBundle"',
|
||||
'web-link' => 'enable "framework.web_link"',
|
||||
'workflow' => 'enable "framework.workflows"',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return TwigFilter|false
|
||||
*/
|
||||
public static function onUndefinedFilter(string $name)
|
||||
{
|
||||
if (!isset(self::FILTER_COMPONENTS[$name])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new SyntaxError(self::onUndefined($name, 'filter', self::FILTER_COMPONENTS[$name]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TwigFunction|false
|
||||
*/
|
||||
public static function onUndefinedFunction(string $name)
|
||||
{
|
||||
if (!isset(self::FUNCTION_COMPONENTS[$name])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ('webpack-encore-bundle' === self::FUNCTION_COMPONENTS[$name]) {
|
||||
return new TwigFunction($name, static function () { return ''; });
|
||||
}
|
||||
|
||||
throw new SyntaxError(self::onUndefined($name, 'function', self::FUNCTION_COMPONENTS[$name]));
|
||||
}
|
||||
|
||||
private static function onUndefined(string $name, string $type, string $component): string
|
||||
{
|
||||
if (class_exists(FullStack::class) && isset(self::FULL_STACK_ENABLE[$component])) {
|
||||
return sprintf('Did you forget to %s? Unknown %s "%s".', self::FULL_STACK_ENABLE[$component], $type, $name);
|
||||
}
|
||||
|
||||
return sprintf('Did you forget to run "composer require symfony/%s"? Unknown %s "%s".', $component, $type, $name);
|
||||
}
|
||||
}
|
88
vendor/symfony/twig-bridge/composer.json
vendored
Normal file
88
vendor/symfony/twig-bridge/composer.json
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "symfony/twig-bridge",
|
||||
"type": "symfony-bridge",
|
||||
"description": "Provides integration for Twig with various Symfony components",
|
||||
"keywords": [],
|
||||
"homepage": "https://symfony.com",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/polyfill-php80": "^1.16",
|
||||
"symfony/translation-contracts": "^1.1|^2|^3",
|
||||
"twig/twig": "^2.13|^3.0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.12",
|
||||
"egulias/email-validator": "^2.1.10|^3",
|
||||
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
|
||||
"symfony/asset": "^4.4|^5.0|^6.0",
|
||||
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
|
||||
"symfony/finder": "^4.4|^5.0|^6.0",
|
||||
"symfony/form": "^5.3|^6.0",
|
||||
"symfony/http-foundation": "^5.3|^6.0",
|
||||
"symfony/http-kernel": "^4.4|^5.0|^6.0",
|
||||
"symfony/intl": "^4.4|^5.0|^6.0",
|
||||
"symfony/mime": "^5.2|^6.0",
|
||||
"symfony/polyfill-intl-icu": "~1.0",
|
||||
"symfony/property-info": "^4.4|^5.1|^6.0",
|
||||
"symfony/routing": "^4.4|^5.0|^6.0",
|
||||
"symfony/translation": "^5.2|^6.0",
|
||||
"symfony/yaml": "^4.4|^5.0|^6.0",
|
||||
"symfony/security-acl": "^2.8|^3.0",
|
||||
"symfony/security-core": "^4.4|^5.0|^6.0",
|
||||
"symfony/security-csrf": "^4.4|^5.0|^6.0",
|
||||
"symfony/security-http": "^4.4|^5.0|^6.0",
|
||||
"symfony/serializer": "^5.2|^6.0",
|
||||
"symfony/stopwatch": "^4.4|^5.0|^6.0",
|
||||
"symfony/console": "^5.3|^6.0",
|
||||
"symfony/expression-language": "^4.4|^5.0|^6.0",
|
||||
"symfony/web-link": "^4.4|^5.0|^6.0",
|
||||
"symfony/workflow": "^5.2|^6.0",
|
||||
"twig/cssinliner-extra": "^2.12|^3",
|
||||
"twig/inky-extra": "^2.12|^3",
|
||||
"twig/markdown-extra": "^2.12|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"phpdocumentor/reflection-docblock": "<3.2.2",
|
||||
"phpdocumentor/type-resolver": "<1.4.0",
|
||||
"symfony/console": "<5.3",
|
||||
"symfony/form": "<5.3",
|
||||
"symfony/http-foundation": "<5.3",
|
||||
"symfony/http-kernel": "<4.4",
|
||||
"symfony/translation": "<5.2",
|
||||
"symfony/workflow": "<5.2"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/finder": "",
|
||||
"symfony/asset": "For using the AssetExtension",
|
||||
"symfony/form": "For using the FormExtension",
|
||||
"symfony/http-kernel": "For using the HttpKernelExtension",
|
||||
"symfony/routing": "For using the RoutingExtension",
|
||||
"symfony/translation": "For using the TranslationExtension",
|
||||
"symfony/yaml": "For using the YamlExtension",
|
||||
"symfony/security-core": "For using the SecurityExtension",
|
||||
"symfony/security-csrf": "For using the CsrfExtension",
|
||||
"symfony/security-http": "For using the LogoutUrlExtension",
|
||||
"symfony/stopwatch": "For using the StopwatchExtension",
|
||||
"symfony/var-dumper": "For using the DumpExtension",
|
||||
"symfony/expression-language": "For using the ExpressionExtension",
|
||||
"symfony/web-link": "For using the WebLinkExtension"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Bridge\\Twig\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev"
|
||||
}
|
Reference in New Issue
Block a user