Merge branch '4.2'
* 4.2: [Phpunit] fixed support for PHP 5.3 Response prepare method update [Workflow] Added missing license header Fix case when multiple loaders are providing paths for the same namespace Check if Client exists when test.client does not exist, to provide clearer exception message throw TypeErrors to prepare for type hints in 5.0 [Form] Preventing validation of children if parent with Valid constraint has no validation groups [Form] Added ResetInterface to CachingFactoryDecorator Remove deprecated usage [Tests] fixed compatbility of assertEquals(): void Fixed usage of TranslatorInterface in form extension (fixes #30591) [Intl][4.2] Fix test [Intl] Fix test [Validator] Add the missing translations for the Arabic (ar) locale [Intl] Add compile binary Fix DebugCommand when chain loader is involved [Form] Fixed some phpdocs
This commit is contained in:
commit
522594a69d
|
@ -42,7 +42,7 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE
|
||||||
@trigger_error(sprintf('Injecting an instance of "%s" in "%s" is deprecated since Symfony 4.2, inject an instance of "%s" instead.', ClassMetadataFactory::class, __CLASS__, EntityManagerInterface::class), E_USER_DEPRECATED);
|
@trigger_error(sprintf('Injecting an instance of "%s" in "%s" is deprecated since Symfony 4.2, inject an instance of "%s" instead.', ClassMetadataFactory::class, __CLASS__, EntityManagerInterface::class), E_USER_DEPRECATED);
|
||||||
$this->classMetadataFactory = $entityManager;
|
$this->classMetadataFactory = $entityManager;
|
||||||
} else {
|
} else {
|
||||||
throw new \InvalidArgumentException(sprintf('$entityManager must be an instance of "%s", "%s" given.', EntityManagerInterface::class, \is_object($entityManager) ? \get_class($entityManager) : \gettype($entityManager)));
|
throw new \TypeError(sprintf('$entityManager must be an instance of "%s", "%s" given.', EntityManagerInterface::class, \is_object($entityManager) ? \get_class($entityManager) : \gettype($entityManager)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,11 +76,11 @@ if ('phpdbg' === PHP_SAPI) {
|
||||||
$PHP .= ' -qrr';
|
$PHP .= ' -qrr';
|
||||||
}
|
}
|
||||||
|
|
||||||
$defaultEnvs = [
|
$defaultEnvs = array(
|
||||||
'COMPOSER' => 'composer.json',
|
'COMPOSER' => 'composer.json',
|
||||||
'COMPOSER_VENDOR_DIR' => 'vendor',
|
'COMPOSER_VENDOR_DIR' => 'vendor',
|
||||||
'COMPOSER_BIN_DIR' => 'bin',
|
'COMPOSER_BIN_DIR' => 'bin',
|
||||||
];
|
);
|
||||||
|
|
||||||
foreach ($defaultEnvs as $envName => $envValue) {
|
foreach ($defaultEnvs as $envName => $envValue) {
|
||||||
if ($envValue !== getenv($envName)) {
|
if ($envValue !== getenv($envName)) {
|
||||||
|
|
|
@ -20,6 +20,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
use Twig\Environment;
|
use Twig\Environment;
|
||||||
|
use Twig\Loader\ChainLoader;
|
||||||
use Twig\Loader\FilesystemLoader;
|
use Twig\Loader\FilesystemLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,6 +37,7 @@ class DebugCommand extends Command
|
||||||
private $bundlesMetadata;
|
private $bundlesMetadata;
|
||||||
private $twigDefaultPath;
|
private $twigDefaultPath;
|
||||||
private $rootDir;
|
private $rootDir;
|
||||||
|
private $filesystemLoaders;
|
||||||
|
|
||||||
public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = [], string $twigDefaultPath = null, string $rootDir = null)
|
public function __construct(Environment $twig, string $projectDir = null, array $bundlesMetadata = [], string $twigDefaultPath = null, string $rootDir = null)
|
||||||
{
|
{
|
||||||
|
@ -87,7 +89,7 @@ EOF
|
||||||
$name = $input->getArgument('name');
|
$name = $input->getArgument('name');
|
||||||
$filter = $input->getOption('filter');
|
$filter = $input->getOption('filter');
|
||||||
|
|
||||||
if (null !== $name && !$this->twig->getLoader() instanceof FilesystemLoader) {
|
if (null !== $name && [] === $this->getFilesystemLoaders()) {
|
||||||
throw new InvalidArgumentException(sprintf('Argument "name" not supported, it requires the Twig loader "%s"', FilesystemLoader::class));
|
throw new InvalidArgumentException(sprintf('Argument "name" not supported, it requires the Twig loader "%s"', FilesystemLoader::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,9 +152,11 @@ EOF
|
||||||
$message = 'No template paths configured for your application';
|
$message = 'No template paths configured for your application';
|
||||||
} else {
|
} else {
|
||||||
$message = sprintf('No template paths configured for "@%s" namespace', $namespace);
|
$message = sprintf('No template paths configured for "@%s" namespace', $namespace);
|
||||||
$namespaces = $this->twig->getLoader()->getNamespaces();
|
foreach ($this->getFilesystemLoaders() as $loader) {
|
||||||
foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) {
|
$namespaces = $loader->getNamespaces();
|
||||||
$alternatives[] = '@'.$namespace;
|
foreach ($this->findAlternatives($namespace, $namespaces) as $namespace) {
|
||||||
|
$alternatives[] = '@'.$namespace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,25 +247,25 @@ EOF
|
||||||
|
|
||||||
private function getLoaderPaths(string $name = null): array
|
private function getLoaderPaths(string $name = null): array
|
||||||
{
|
{
|
||||||
/** @var FilesystemLoader $loader */
|
|
||||||
$loader = $this->twig->getLoader();
|
|
||||||
$loaderPaths = [];
|
$loaderPaths = [];
|
||||||
$namespaces = $loader->getNamespaces();
|
foreach ($this->getFilesystemLoaders() as $loader) {
|
||||||
if (null !== $name) {
|
$namespaces = $loader->getNamespaces();
|
||||||
$namespace = $this->parseTemplateName($name)[0];
|
if (null !== $name) {
|
||||||
$namespaces = array_intersect([$namespace], $namespaces);
|
$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] = $paths;
|
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;
|
return $loaderPaths;
|
||||||
|
@ -437,22 +441,22 @@ EOF
|
||||||
|
|
||||||
private function findTemplateFiles(string $name): array
|
private function findTemplateFiles(string $name): array
|
||||||
{
|
{
|
||||||
/** @var FilesystemLoader $loader */
|
|
||||||
$loader = $this->twig->getLoader();
|
|
||||||
$files = [];
|
|
||||||
list($namespace, $shortname) = $this->parseTemplateName($name);
|
list($namespace, $shortname) = $this->parseTemplateName($name);
|
||||||
|
|
||||||
foreach ($loader->getPaths($namespace) as $path) {
|
$files = [];
|
||||||
if (!$this->isAbsolutePath($path)) {
|
foreach ($this->getFilesystemLoaders() as $loader) {
|
||||||
$path = $this->projectDir.'/'.$path;
|
foreach ($loader->getPaths($namespace) as $path) {
|
||||||
}
|
if (!$this->isAbsolutePath($path)) {
|
||||||
$filename = $path.'/'.$shortname;
|
$path = $this->projectDir.'/'.$path;
|
||||||
|
}
|
||||||
|
$filename = $path.'/'.$shortname;
|
||||||
|
|
||||||
if (is_file($filename)) {
|
if (is_file($filename)) {
|
||||||
if (false !== $realpath = realpath($filename)) {
|
if (false !== $realpath = realpath($filename)) {
|
||||||
$files[] = $this->getRelativePath($realpath);
|
$files[] = $this->getRelativePath($realpath);
|
||||||
} else {
|
} else {
|
||||||
$files[] = $this->getRelativePath($filename);
|
$files[] = $this->getRelativePath($filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -535,4 +539,28 @@ EOF
|
||||||
{
|
{
|
||||||
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 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ use Symfony\Bridge\Twig\Command\DebugCommand;
|
||||||
use Symfony\Component\Console\Application;
|
use Symfony\Component\Console\Application;
|
||||||
use Symfony\Component\Console\Tester\CommandTester;
|
use Symfony\Component\Console\Tester\CommandTester;
|
||||||
use Twig\Environment;
|
use Twig\Environment;
|
||||||
|
use Twig\Loader\ChainLoader;
|
||||||
use Twig\Loader\FilesystemLoader;
|
use Twig\Loader\FilesystemLoader;
|
||||||
|
|
||||||
class DebugCommandTest extends TestCase
|
class DebugCommandTest extends TestCase
|
||||||
|
@ -279,7 +280,16 @@ TXT
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createCommandTester(array $paths = [], array $bundleMetadata = [], string $defaultPath = null, string $rootDir = null): CommandTester
|
public function testDebugTemplateNameWithChainLoader()
|
||||||
|
{
|
||||||
|
$tester = $this->createCommandTester(['templates/' => null], [], null, null, true);
|
||||||
|
$ret = $tester->execute(['name' => 'base.html.twig'], ['decorated' => false]);
|
||||||
|
|
||||||
|
$this->assertEquals(0, $ret, 'Returns 0 in case of success');
|
||||||
|
$this->assertContains('[OK]', $tester->getDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createCommandTester(array $paths = [], array $bundleMetadata = [], string $defaultPath = null, string $rootDir = null, bool $useChainLoader = false): CommandTester
|
||||||
{
|
{
|
||||||
$projectDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures';
|
$projectDir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures';
|
||||||
$loader = new FilesystemLoader([], $projectDir);
|
$loader = new FilesystemLoader([], $projectDir);
|
||||||
|
@ -291,6 +301,10 @@ TXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($useChainLoader) {
|
||||||
|
$loader = new ChainLoader([$loader]);
|
||||||
|
}
|
||||||
|
|
||||||
$application = new Application();
|
$application = new Application();
|
||||||
$application->add(new DebugCommand(new Environment($loader), $projectDir, $bundleMetadata, $defaultPath, $rootDir));
|
$application->add(new DebugCommand(new Environment($loader), $projectDir, $bundleMetadata, $defaultPath, $rootDir));
|
||||||
$command = $application->find('debug:twig');
|
$command = $application->find('debug:twig');
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^7.1.3",
|
"php": "^7.1.3",
|
||||||
"symfony/contracts": "^1.0.2",
|
"symfony/contracts": "^1.0.2",
|
||||||
"twig/twig": "^1.37.1|^2.6.2"
|
"twig/twig": "^1.38.1|^2.7.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"egulias/email-validator": "^2.0",
|
"egulias/email-validator": "^2.0",
|
||||||
|
|
|
@ -55,6 +55,7 @@ use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
use Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator;
|
||||||
use Symfony\Component\Form\FormTypeExtensionInterface;
|
use Symfony\Component\Form\FormTypeExtensionInterface;
|
||||||
use Symfony\Component\Form\FormTypeGuesserInterface;
|
use Symfony\Component\Form\FormTypeGuesserInterface;
|
||||||
use Symfony\Component\Form\FormTypeInterface;
|
use Symfony\Component\Form\FormTypeInterface;
|
||||||
|
@ -440,6 +441,11 @@ class FrameworkExtension extends Extension
|
||||||
if (!class_exists(Translator::class)) {
|
if (!class_exists(Translator::class)) {
|
||||||
$container->removeDefinition('form.type_extension.upload.validator');
|
$container->removeDefinition('form.type_extension.upload.validator');
|
||||||
}
|
}
|
||||||
|
if (!method_exists(CachingFactoryDecorator::class, 'reset')) {
|
||||||
|
$container->getDefinition('form.choice_list_factory.cached')
|
||||||
|
->clearTag('kernel.reset')
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function registerEsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
private function registerEsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
|
|
||||||
<service id="form.choice_list_factory.cached" class="Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator">
|
<service id="form.choice_list_factory.cached" class="Symfony\Component\Form\ChoiceList\Factory\CachingFactoryDecorator">
|
||||||
<argument type="service" id="form.choice_list_factory.property_access"/>
|
<argument type="service" id="form.choice_list_factory.property_access"/>
|
||||||
|
<tag name="kernel.reset" method="reset" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="form.choice_list_factory" alias="form.choice_list_factory.cached" />
|
<service id="form.choice_list_factory" alias="form.choice_list_factory.cached" />
|
||||||
|
|
|
@ -36,7 +36,10 @@ abstract class WebTestCase extends KernelTestCase
|
||||||
try {
|
try {
|
||||||
$client = $kernel->getContainer()->get('test.client');
|
$client = $kernel->getContainer()->get('test.client');
|
||||||
} catch (ServiceNotFoundException $e) {
|
} catch (ServiceNotFoundException $e) {
|
||||||
throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit".');
|
if (class_exists(Client::class)) {
|
||||||
|
throw new \LogicException('You cannot create the client used in functional tests if the "framework.test" config is not set to true.');
|
||||||
|
}
|
||||||
|
throw new \LogicException('You cannot create the client used in functional tests if the BrowserKit component is not available. Try running "composer require symfony/browser-kit"');
|
||||||
}
|
}
|
||||||
|
|
||||||
$client->setServerParameters($server);
|
$client->setServerParameters($server);
|
||||||
|
|
|
@ -41,7 +41,7 @@ class FirewallContext
|
||||||
$this->logoutListener = $logoutListener;
|
$this->logoutListener = $logoutListener;
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
} else {
|
} else {
|
||||||
throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be instance of %s or null, %s given.', __METHOD__, LogoutListener::class, \is_object($logoutListener) ? \get_class($logoutListener) : \gettype($logoutListener)));
|
throw new \TypeError(sprintf('Argument 3 passed to %s() must be instance of %s or null, %s given.', __METHOD__, LogoutListener::class, \is_object($logoutListener) ? \get_class($logoutListener) : \gettype($logoutListener)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,10 @@ namespace Symfony\Component\Form\ChoiceList;
|
||||||
* A list of choices with arbitrary data types.
|
* A list of choices with arbitrary data types.
|
||||||
*
|
*
|
||||||
* The user of this class is responsible for assigning string values to the
|
* The user of this class is responsible for assigning string values to the
|
||||||
* choices. Both the choices and their values are passed to the constructor.
|
* choices annd for their uniqueness.
|
||||||
* Each choice must have a corresponding value (with the same array key) in
|
* Both the choices and their values are passed to the constructor.
|
||||||
* the value array.
|
* Each choice must have a corresponding value (with the same key) in
|
||||||
|
* the values array.
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
@ -43,12 +44,6 @@ class ArrayChoiceList implements ChoiceListInterface
|
||||||
* @var int[]|string[]
|
* @var int[]|string[]
|
||||||
*/
|
*/
|
||||||
protected $originalKeys;
|
protected $originalKeys;
|
||||||
|
|
||||||
/**
|
|
||||||
* The callback for creating the value for a choice.
|
|
||||||
*
|
|
||||||
* @var callable
|
|
||||||
*/
|
|
||||||
protected $valueCallback;
|
protected $valueCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,6 +207,8 @@ class ArrayChoiceList implements ChoiceListInterface
|
||||||
/**
|
/**
|
||||||
* Checks whether the given choices can be cast to strings without
|
* Checks whether the given choices can be cast to strings without
|
||||||
* generating duplicates.
|
* generating duplicates.
|
||||||
|
* This method is responsible for preventing conflict between scalar values
|
||||||
|
* and the empty value.
|
||||||
*
|
*
|
||||||
* @param array $choices The choices
|
* @param array $choices The choices
|
||||||
* @param array|null $cache The cache for previously checked entries. Internal
|
* @param array|null $cache The cache for previously checked entries. Internal
|
||||||
|
@ -232,6 +229,7 @@ class ArrayChoiceList implements ChoiceListInterface
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prevent having false casted to the empty string by isset()
|
||||||
$choice = false === $choice ? '0' : (string) $choice;
|
$choice = false === $choice ? '0' : (string) $choice;
|
||||||
|
|
||||||
if (isset($cache[$choice])) {
|
if (isset($cache[$choice])) {
|
||||||
|
|
|
@ -35,7 +35,25 @@ interface ChoiceListInterface
|
||||||
/**
|
/**
|
||||||
* Returns the values for the choices.
|
* Returns the values for the choices.
|
||||||
*
|
*
|
||||||
* The values are strings that do not contain duplicates.
|
* The values are strings that do not contain duplicates:
|
||||||
|
*
|
||||||
|
* $form->add('field', 'choice', [
|
||||||
|
* 'choices' => [
|
||||||
|
* 'Decided' => ['Yes' => true, 'No' => false],
|
||||||
|
* 'Undecided' => ['Maybe' => null],
|
||||||
|
* ],
|
||||||
|
* ]);
|
||||||
|
*
|
||||||
|
* In this example, the result of this method is:
|
||||||
|
*
|
||||||
|
* [
|
||||||
|
* 'Yes' => '0',
|
||||||
|
* 'No' => '1',
|
||||||
|
* 'Maybe' => '2',
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* Null and false MUST NOT conflict when being casted to string.
|
||||||
|
* For this some default incremented values SHOULD be computed.
|
||||||
*
|
*
|
||||||
* @return string[] The choice values
|
* @return string[] The choice values
|
||||||
*/
|
*/
|
||||||
|
@ -62,6 +80,12 @@ interface ChoiceListInterface
|
||||||
* 'Undecided' => ['Maybe' => '2'],
|
* 'Undecided' => ['Maybe' => '2'],
|
||||||
* ]
|
* ]
|
||||||
*
|
*
|
||||||
|
* Nested arrays do not make sense in a view format unless
|
||||||
|
* they are used as a convenient way of grouping.
|
||||||
|
* If the implementation does not intend to support grouped choices,
|
||||||
|
* this method SHOULD be equivalent to {@link getValues()}.
|
||||||
|
* The $groupBy callback parameter SHOULD be used instead.
|
||||||
|
*
|
||||||
* @return string[] The choice values
|
* @return string[] The choice values
|
||||||
*/
|
*/
|
||||||
public function getStructuredValues();
|
public function getStructuredValues();
|
||||||
|
|
|
@ -14,13 +14,14 @@ namespace Symfony\Component\Form\ChoiceList\Factory;
|
||||||
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
use Symfony\Component\Form\ChoiceList\ChoiceListInterface;
|
||||||
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface;
|
||||||
use Symfony\Component\Form\ChoiceList\View\ChoiceListView;
|
use Symfony\Component\Form\ChoiceList\View\ChoiceListView;
|
||||||
|
use Symfony\Contracts\Service\ResetInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caches the choice lists created by the decorated factory.
|
* Caches the choice lists created by the decorated factory.
|
||||||
*
|
*
|
||||||
* @author Bernhard Schussek <bschussek@gmail.com>
|
* @author Bernhard Schussek <bschussek@gmail.com>
|
||||||
*/
|
*/
|
||||||
class CachingFactoryDecorator implements ChoiceListFactoryInterface
|
class CachingFactoryDecorator implements ChoiceListFactoryInterface, ResetInterface
|
||||||
{
|
{
|
||||||
private $decoratedFactory;
|
private $decoratedFactory;
|
||||||
|
|
||||||
|
@ -134,4 +135,10 @@ class CachingFactoryDecorator implements ChoiceListFactoryInterface
|
||||||
|
|
||||||
return $this->views[$hash];
|
return $this->views[$hash];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function reset()
|
||||||
|
{
|
||||||
|
$this->lists = [];
|
||||||
|
$this->views = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ interface ChoiceListFactoryInterface
|
||||||
* The choices should be passed in the values of the choices array.
|
* The choices should be passed in the values of the choices array.
|
||||||
*
|
*
|
||||||
* Optionally, a callable can be passed for generating the choice values.
|
* Optionally, a callable can be passed for generating the choice values.
|
||||||
* The callable receives the choice as first and the array key as the second
|
* The callable receives the choice as only argument.
|
||||||
* argument.
|
* Null may be passed when the choice list contains the empty value.
|
||||||
*
|
*
|
||||||
* @param iterable $choices The choices
|
* @param iterable $choices The choices
|
||||||
* @param callable|null $value The callable generating the choice
|
* @param callable|null $value The callable generating the choice
|
||||||
|
@ -43,8 +43,8 @@ interface ChoiceListFactoryInterface
|
||||||
* Creates a choice list that is loaded with the given loader.
|
* Creates a choice list that is loaded with the given loader.
|
||||||
*
|
*
|
||||||
* Optionally, a callable can be passed for generating the choice values.
|
* Optionally, a callable can be passed for generating the choice values.
|
||||||
* The callable receives the choice as first and the array key as the second
|
* The callable receives the choice as only argument.
|
||||||
* argument.
|
* Null may be passed when the choice list contains the empty value.
|
||||||
*
|
*
|
||||||
* @param ChoiceLoaderInterface $loader The choice loader
|
* @param ChoiceLoaderInterface $loader The choice loader
|
||||||
* @param callable|null $value The callable generating the choice
|
* @param callable|null $value The callable generating the choice
|
||||||
|
|
|
@ -28,8 +28,8 @@ interface ChoiceLoaderInterface
|
||||||
* Loads a list of choices.
|
* Loads a list of choices.
|
||||||
*
|
*
|
||||||
* Optionally, a callable can be passed for generating the choice values.
|
* Optionally, a callable can be passed for generating the choice values.
|
||||||
* The callable receives the choice as first and the array key as the second
|
* The callable receives the choice as only argument.
|
||||||
* argument.
|
* Null may be passed when the choice list contains the empty value.
|
||||||
*
|
*
|
||||||
* @param callable|null $value The callable which generates the values
|
* @param callable|null $value The callable which generates the values
|
||||||
* from choices
|
* from choices
|
||||||
|
@ -45,8 +45,8 @@ interface ChoiceLoaderInterface
|
||||||
* corresponding values in the given array.
|
* corresponding values in the given array.
|
||||||
*
|
*
|
||||||
* Optionally, a callable can be passed for generating the choice values.
|
* Optionally, a callable can be passed for generating the choice values.
|
||||||
* The callable receives the choice as first and the array key as the second
|
* The callable receives the choice as only argument.
|
||||||
* argument.
|
* Null may be passed when the choice list contains the empty value.
|
||||||
*
|
*
|
||||||
* @param string[] $values An array of choice values. Non-existing
|
* @param string[] $values An array of choice values. Non-existing
|
||||||
* values in this array are ignored
|
* values in this array are ignored
|
||||||
|
@ -63,8 +63,8 @@ interface ChoiceLoaderInterface
|
||||||
* corresponding choices in the given array.
|
* corresponding choices in the given array.
|
||||||
*
|
*
|
||||||
* Optionally, a callable can be passed for generating the choice values.
|
* Optionally, a callable can be passed for generating the choice values.
|
||||||
* The callable receives the choice as first and the array key as the second
|
* The callable receives the choice as only argument.
|
||||||
* argument.
|
* Null may be passed when the choice list contains the empty value.
|
||||||
*
|
*
|
||||||
* @param array $choices An array of choices. Non-existing choices in
|
* @param array $choices An array of choices. Non-existing choices in
|
||||||
* this array are ignored
|
* this array are ignored
|
||||||
|
|
|
@ -19,7 +19,8 @@ use Symfony\Component\Form\ChoiceList\Factory\PropertyAccessDecorator;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension;
|
use Symfony\Component\Form\Extension\Core\Type\TransformationFailureExtension;
|
||||||
use Symfony\Component\PropertyAccess\PropertyAccess;
|
use Symfony\Component\PropertyAccess\PropertyAccess;
|
||||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the main form extension, which loads the core functionality.
|
* Represents the main form extension, which loads the core functionality.
|
||||||
|
@ -32,8 +33,14 @@ class CoreExtension extends AbstractExtension
|
||||||
private $choiceListFactory;
|
private $choiceListFactory;
|
||||||
private $translator;
|
private $translator;
|
||||||
|
|
||||||
public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null, TranslatorInterface $translator = null)
|
/**
|
||||||
|
* @param TranslatorInterface|null $translator
|
||||||
|
*/
|
||||||
|
public function __construct(PropertyAccessorInterface $propertyAccessor = null, ChoiceListFactoryInterface $choiceListFactory = null, $translator = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 3 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();
|
||||||
$this->choiceListFactory = $choiceListFactory ?: new CachingFactoryDecorator(new PropertyAccessDecorator(new DefaultChoiceListFactory(), $this->propertyAccessor));
|
$this->choiceListFactory = $choiceListFactory ?: new CachingFactoryDecorator(new PropertyAccessDecorator(new DefaultChoiceListFactory(), $this->propertyAccessor));
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
|
|
|
@ -15,7 +15,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Symfony\Component\Form\FormError;
|
use Symfony\Component\Form\FormError;
|
||||||
use Symfony\Component\Form\FormEvent;
|
use Symfony\Component\Form\FormEvent;
|
||||||
use Symfony\Component\Form\FormEvents;
|
use Symfony\Component\Form\FormEvents;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||||
|
@ -24,8 +25,14 @@ class TransformationFailureListener implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
private $translator;
|
private $translator;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator = null)
|
/**
|
||||||
|
* @param TranslatorInterface|null $translator
|
||||||
|
*/
|
||||||
|
public function __construct($translator = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@ namespace Symfony\Component\Form\Extension\Core\Type;
|
||||||
use Symfony\Component\Form\AbstractTypeExtension;
|
use Symfony\Component\Form\AbstractTypeExtension;
|
||||||
use Symfony\Component\Form\Extension\Core\EventListener\TransformationFailureListener;
|
use Symfony\Component\Form\Extension\Core\EventListener\TransformationFailureListener;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Translation\TranslatorInterface;
|
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
* @author Christian Flothmann <christian.flothmann@sensiolabs.de>
|
||||||
|
@ -23,8 +24,14 @@ class TransformationFailureExtension extends AbstractTypeExtension
|
||||||
{
|
{
|
||||||
private $translator;
|
private $translator;
|
||||||
|
|
||||||
public function __construct(TranslatorInterface $translator = null)
|
/**
|
||||||
|
* @param TranslatorInterface|null $translator
|
||||||
|
*/
|
||||||
|
public function __construct($translator = null)
|
||||||
{
|
{
|
||||||
|
if (null !== $translator && !$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) {
|
||||||
|
throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, TranslatorInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator)));
|
||||||
|
}
|
||||||
$this->translator = $translator;
|
$this->translator = $translator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,11 @@ class FormValidator extends ConstraintValidator
|
||||||
if ($form->isSubmitted() && $form->isSynchronized()) {
|
if ($form->isSubmitted() && $form->isSynchronized()) {
|
||||||
// Validate the form data only if transformation succeeded
|
// Validate the form data only if transformation succeeded
|
||||||
$groups = self::getValidationGroups($form);
|
$groups = self::getValidationGroups($form);
|
||||||
|
|
||||||
|
if (!$groups) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$data = $form->getData();
|
$data = $form->getData();
|
||||||
|
|
||||||
// Validate the data against its own constraints
|
// Validate the data against its own constraints
|
||||||
|
|
|
@ -13,18 +13,11 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToHtml5LocalDateTimeTransformer;
|
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToHtml5LocalDateTimeTransformer;
|
||||||
|
use Symfony\Component\Form\Tests\Extension\Core\DataTransformer\Traits\DateTimeEqualsTrait;
|
||||||
|
|
||||||
class DateTimeToHtml5LocalDateTimeTransformerTest extends TestCase
|
class DateTimeToHtml5LocalDateTimeTransformerTest extends TestCase
|
||||||
{
|
{
|
||||||
public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
|
use DateTimeEqualsTrait;
|
||||||
{
|
|
||||||
if ($expected instanceof \DateTime && $actual instanceof \DateTime) {
|
|
||||||
$expected = $expected->format('c');
|
|
||||||
$actual = $actual->format('c');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function transformProvider()
|
public function transformProvider()
|
||||||
{
|
{
|
||||||
|
@ -95,7 +88,7 @@ class DateTimeToHtml5LocalDateTimeTransformerTest extends TestCase
|
||||||
$transformer = new DateTimeToHtml5LocalDateTimeTransformer($toTz, $fromTz);
|
$transformer = new DateTimeToHtml5LocalDateTimeTransformer($toTz, $fromTz);
|
||||||
|
|
||||||
if (null !== $to) {
|
if (null !== $to) {
|
||||||
$this->assertEquals(new \DateTime($to), $transformer->reverseTransform($from));
|
$this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from));
|
||||||
} else {
|
} else {
|
||||||
$this->assertNull($transformer->reverseTransform($from));
|
$this->assertNull($transformer->reverseTransform($from));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,13 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
|
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer;
|
||||||
|
use Symfony\Component\Form\Tests\Extension\Core\DataTransformer\Traits\DateTimeEqualsTrait;
|
||||||
use Symfony\Component\Intl\Util\IntlTestHelper;
|
use Symfony\Component\Intl\Util\IntlTestHelper;
|
||||||
|
|
||||||
class DateTimeToLocalizedStringTransformerTest extends TestCase
|
class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
{
|
{
|
||||||
|
use DateTimeEqualsTrait;
|
||||||
|
|
||||||
protected $dateTime;
|
protected $dateTime;
|
||||||
protected $dateTimeWithoutSeconds;
|
protected $dateTimeWithoutSeconds;
|
||||||
|
|
||||||
|
@ -39,16 +42,6 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
$this->dateTimeWithoutSeconds = null;
|
$this->dateTimeWithoutSeconds = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
|
|
||||||
{
|
|
||||||
if ($expected instanceof \DateTime && $actual instanceof \DateTime) {
|
|
||||||
$expected = $expected->format('c');
|
|
||||||
$actual = $actual->format('c');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dataProvider()
|
public function dataProvider()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
@ -152,7 +145,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
|
|
||||||
$dateTime = new \DateTime('2010-02-03 04:05');
|
$dateTime = new \DateTime('2010-02-03 04:05');
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertDateTimeEquals(
|
||||||
$dateTime->format('c'),
|
$dateTime->format('c'),
|
||||||
$transformer->reverseTransform('03.02.2010, 04:05')->format('c')
|
$transformer->reverseTransform('03.02.2010, 04:05')->format('c')
|
||||||
);
|
);
|
||||||
|
@ -217,14 +210,14 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
|
|
||||||
$output = new \DateTime($output);
|
$output = new \DateTime($output);
|
||||||
|
|
||||||
$this->assertEquals($output, $transformer->reverseTransform($input));
|
$this->assertDateTimeEquals($output, $transformer->reverseTransform($input));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReverseTransformFullTime()
|
public function testReverseTransformFullTime()
|
||||||
{
|
{
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL);
|
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL);
|
||||||
|
|
||||||
$this->assertEquals($this->dateTime, $transformer->reverseTransform('03.02.2010, 04:05:06 GMT+00:00'));
|
$this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010, 04:05:06 GMT+00:00'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReverseTransformFromDifferentLocale()
|
public function testReverseTransformFromDifferentLocale()
|
||||||
|
@ -233,7 +226,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
|
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC');
|
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC');
|
||||||
|
|
||||||
$this->assertEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM'));
|
$this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReverseTransformWithDifferentTimezones()
|
public function testReverseTransformWithDifferentTimezones()
|
||||||
|
@ -243,7 +236,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
$dateTime = new \DateTime('2010-02-03 04:05:00 Asia/Hong_Kong');
|
$dateTime = new \DateTime('2010-02-03 04:05:00 Asia/Hong_Kong');
|
||||||
$dateTime->setTimezone(new \DateTimeZone('America/New_York'));
|
$dateTime->setTimezone(new \DateTimeZone('America/New_York'));
|
||||||
|
|
||||||
$this->assertEquals($dateTime, $transformer->reverseTransform('03.02.2010, 04:05'));
|
$this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('03.02.2010, 04:05'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReverseTransformOnlyDateWithDifferentTimezones()
|
public function testReverseTransformOnlyDateWithDifferentTimezones()
|
||||||
|
@ -252,21 +245,21 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
|
|
||||||
$dateTime = new \DateTime('2017-01-10 11:00', new \DateTimeZone('Europe/Berlin'));
|
$dateTime = new \DateTime('2017-01-10 11:00', new \DateTimeZone('Europe/Berlin'));
|
||||||
|
|
||||||
$this->assertEquals($dateTime, $transformer->reverseTransform('2017-01-10'));
|
$this->assertDateTimeEquals($dateTime, $transformer->reverseTransform('2017-01-10'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReverseTransformWithDifferentPatterns()
|
public function testReverseTransformWithDifferentPatterns()
|
||||||
{
|
{
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss');
|
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'MM*yyyy*dd HH|mm|ss');
|
||||||
|
|
||||||
$this->assertEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06'));
|
$this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('02*2010*03 04|05|06'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testReverseTransformDateOnlyWithDstIssue()
|
public function testReverseTransformDateOnlyWithDstIssue()
|
||||||
{
|
{
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'dd/MM/yyyy');
|
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, 'dd/MM/yyyy');
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertDateTimeEquals(
|
||||||
new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')),
|
new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')),
|
||||||
$transformer->reverseTransform('28/05/1978')
|
$transformer->reverseTransform('28/05/1978')
|
||||||
);
|
);
|
||||||
|
@ -276,7 +269,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
{
|
{
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, "'day': dd 'month': MM 'year': yyyy");
|
$transformer = new DateTimeToLocalizedStringTransformer('Europe/Rome', 'Europe/Rome', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, \IntlDateFormatter::GREGORIAN, "'day': dd 'month': MM 'year': yyyy");
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertDateTimeEquals(
|
||||||
new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')),
|
new \DateTime('1978-05-28', new \DateTimeZone('Europe/Rome')),
|
||||||
$transformer->reverseTransform('day: 28 month: 05 year: 1978')
|
$transformer->reverseTransform('day: 28 month: 05 year: 1978')
|
||||||
);
|
);
|
||||||
|
@ -314,7 +307,7 @@ class DateTimeToLocalizedStringTransformerTest extends TestCase
|
||||||
{
|
{
|
||||||
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT);
|
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT);
|
||||||
|
|
||||||
$this->assertEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05'));
|
$this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,9 +13,12 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer;
|
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToRfc3339Transformer;
|
||||||
|
use Symfony\Component\Form\Tests\Extension\Core\DataTransformer\Traits\DateTimeEqualsTrait;
|
||||||
|
|
||||||
class DateTimeToRfc3339TransformerTest extends TestCase
|
class DateTimeToRfc3339TransformerTest extends TestCase
|
||||||
{
|
{
|
||||||
|
use DateTimeEqualsTrait;
|
||||||
|
|
||||||
protected $dateTime;
|
protected $dateTime;
|
||||||
protected $dateTimeWithoutSeconds;
|
protected $dateTimeWithoutSeconds;
|
||||||
|
|
||||||
|
@ -33,16 +36,6 @@ class DateTimeToRfc3339TransformerTest extends TestCase
|
||||||
$this->dateTimeWithoutSeconds = null;
|
$this->dateTimeWithoutSeconds = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
|
|
||||||
{
|
|
||||||
if ($expected instanceof \DateTime && $actual instanceof \DateTime) {
|
|
||||||
$expected = $expected->format('c');
|
|
||||||
$actual = $actual->format('c');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function allProvider()
|
public function allProvider()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
@ -108,7 +101,7 @@ class DateTimeToRfc3339TransformerTest extends TestCase
|
||||||
$transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz);
|
$transformer = new DateTimeToRfc3339Transformer($toTz, $fromTz);
|
||||||
|
|
||||||
if (null !== $to) {
|
if (null !== $to) {
|
||||||
$this->assertEquals(new \DateTime($to), $transformer->reverseTransform($from));
|
$this->assertDateTimeEquals(new \DateTime($to), $transformer->reverseTransform($from));
|
||||||
} else {
|
} else {
|
||||||
$this->assertNull($transformer->reverseTransform($from));
|
$this->assertNull($transformer->reverseTransform($from));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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\Component\Form\Tests\Extension\Core\DataTransformer\Traits;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
trait DateTimeEqualsTrait
|
||||||
|
{
|
||||||
|
public static function assertDateTimeEquals($expected, $actual)
|
||||||
|
{
|
||||||
|
if ($expected instanceof \DateTime && $actual instanceof \DateTime) {
|
||||||
|
$expected = $expected->format('c');
|
||||||
|
$actual = $actual->format('c');
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::assertEquals($expected, $actual);
|
||||||
|
}
|
||||||
|
}
|
|
@ -220,6 +220,28 @@ class FormValidatorTest extends ConstraintValidatorTestCase
|
||||||
$this->assertNoViolation();
|
$this->assertNoViolation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDontValidateChildConstraintsIfCallableNoValidationGroups()
|
||||||
|
{
|
||||||
|
$formOptions = [
|
||||||
|
'constraints' => [new Valid()],
|
||||||
|
'validation_groups' => [],
|
||||||
|
];
|
||||||
|
$form = $this->getBuilder('name', null, $formOptions)
|
||||||
|
->setCompound(true)
|
||||||
|
->setDataMapper(new PropertyPathMapper())
|
||||||
|
->getForm();
|
||||||
|
$childOptions = ['constraints' => [new NotBlank()]];
|
||||||
|
$child = $this->getCompoundForm(new \stdClass(), $childOptions);
|
||||||
|
$form->add($child);
|
||||||
|
$form->submit([]);
|
||||||
|
|
||||||
|
$this->expectNoValidate();
|
||||||
|
|
||||||
|
$this->validator->validate($form, new Form());
|
||||||
|
|
||||||
|
$this->assertNoViolation();
|
||||||
|
}
|
||||||
|
|
||||||
public function testDontValidateIfNotSynchronized()
|
public function testDontValidateIfNotSynchronized()
|
||||||
{
|
{
|
||||||
$object = new \stdClass();
|
$object = new \stdClass();
|
||||||
|
|
|
@ -306,9 +306,9 @@ class Response
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we need to send extra expire info headers
|
// Check if we need to send extra expire info headers
|
||||||
if ('1.0' == $this->getProtocolVersion() && false !== strpos($this->headers->get('Cache-Control'), 'no-cache')) {
|
if ('1.0' == $this->getProtocolVersion() && false !== strpos($headers->get('Cache-Control'), 'no-cache')) {
|
||||||
$this->headers->set('pragma', 'no-cache');
|
$headers->set('pragma', 'no-cache');
|
||||||
$this->headers->set('expires', -1);
|
$headers->set('expires', -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->ensureIEOverSSLCompatibility($request);
|
$this->ensureIEOverSSLCompatibility($request);
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [[ $1 == force || ! $(docker ps -a | grep symfony-intl) ]]; then
|
||||||
|
docker rm -f symfony-intl
|
||||||
|
docker create --name symfony-intl -it -v /tmp:/tmp -v $(pwd):/app -w /app jakzal/php-intl:7.2-63.1 bash
|
||||||
|
docker start symfony-intl
|
||||||
|
docker exec symfony-intl bash -xc "apt-get update && apt-get -y install build-essential"
|
||||||
|
else
|
||||||
|
docker start symfony-intl
|
||||||
|
fi;
|
||||||
|
|
||||||
|
docker exec -u $(id -u):$(id -g) symfony-intl php src/Symfony/Component/Intl/Resources/bin/update-data.php
|
|
@ -233,7 +233,6 @@
|
||||||
"ms": "malay",
|
"ms": "malay",
|
||||||
"mt": "maltese",
|
"mt": "maltese",
|
||||||
"mua": "mundang",
|
"mua": "mundang",
|
||||||
"mul": "plure linguas",
|
|
||||||
"mus": "creek",
|
"mus": "creek",
|
||||||
"mwl": "mirandese",
|
"mwl": "mirandese",
|
||||||
"my": "birmano",
|
"my": "birmano",
|
||||||
|
@ -361,7 +360,6 @@
|
||||||
"ug": "uighur",
|
"ug": "uighur",
|
||||||
"uk": "ukrainiano",
|
"uk": "ukrainiano",
|
||||||
"umb": "umbundu",
|
"umb": "umbundu",
|
||||||
"und": "lingua incognite",
|
|
||||||
"ur": "urdu",
|
"ur": "urdu",
|
||||||
"uz": "uzbeko",
|
"uz": "uzbeko",
|
||||||
"vai": "vai",
|
"vai": "vai",
|
||||||
|
@ -388,7 +386,6 @@
|
||||||
"zh_Hant": "chinese traditional",
|
"zh_Hant": "chinese traditional",
|
||||||
"zu": "zulu",
|
"zu": "zulu",
|
||||||
"zun": "zuni",
|
"zun": "zuni",
|
||||||
"zxx": "sin contento linguistic",
|
|
||||||
"zza": "zaza"
|
"zza": "zaza"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
"ru": "Rusia",
|
"ru": "Rusia",
|
||||||
"th": "Thailand",
|
"th": "Thailand",
|
||||||
"tr": "Turki",
|
"tr": "Turki",
|
||||||
"und": "Basa Ora Dikenali",
|
|
||||||
"zh": "Tyonghwa",
|
"zh": "Tyonghwa",
|
||||||
"zh_Hant": "Tyonghwa (Tradisional)"
|
"zh_Hant": "Tyonghwa (Tradisional)"
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
"pt_BR": "Pōtikī Parahi",
|
"pt_BR": "Pōtikī Parahi",
|
||||||
"pt_PT": "Pōtikī Uropi",
|
"pt_PT": "Pōtikī Uropi",
|
||||||
"ru": "Ruhiana",
|
"ru": "Ruhiana",
|
||||||
"und": "Reo Tē Mōhiotia",
|
|
||||||
"zh": "Hainamana",
|
"zh": "Hainamana",
|
||||||
"zh_Hans": "Hainamana Māmā",
|
"zh_Hans": "Hainamana Māmā",
|
||||||
"zh_Hant": "Hainamana Tukuiho"
|
"zh_Hant": "Hainamana Tukuiho"
|
||||||
|
|
|
@ -232,7 +232,6 @@
|
||||||
"ms": "ملي",
|
"ms": "ملي",
|
||||||
"mt": "مالٽي",
|
"mt": "مالٽي",
|
||||||
"mua": "من دانگ",
|
"mua": "من دانگ",
|
||||||
"mul": "هڪ کان وڌيڪ ٻوليون",
|
|
||||||
"mus": "ڪريڪ",
|
"mus": "ڪريڪ",
|
||||||
"mwl": "مرانڊيز",
|
"mwl": "مرانڊيز",
|
||||||
"my": "برمي",
|
"my": "برمي",
|
||||||
|
@ -360,7 +359,6 @@
|
||||||
"ug": "يوغور",
|
"ug": "يوغور",
|
||||||
"uk": "يوڪراني",
|
"uk": "يوڪراني",
|
||||||
"umb": "اومبنڊو",
|
"umb": "اومبنڊو",
|
||||||
"und": "اڻڄاتل ٻولي",
|
|
||||||
"ur": "اردو",
|
"ur": "اردو",
|
||||||
"uz": "ازبڪ",
|
"uz": "ازبڪ",
|
||||||
"vai": "يا",
|
"vai": "يا",
|
||||||
|
@ -387,7 +385,6 @@
|
||||||
"zh_Hant": "روايتي چيني",
|
"zh_Hant": "روايتي چيني",
|
||||||
"zu": "زولو",
|
"zu": "زولو",
|
||||||
"zun": "زوني",
|
"zun": "زوني",
|
||||||
"zxx": "ڪوئي ٻولي جو مواد ڪونهي",
|
|
||||||
"zza": "زازا"
|
"zza": "زازا"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
"th": "Taaylandays",
|
"th": "Taaylandays",
|
||||||
"tr": "Turkish",
|
"tr": "Turkish",
|
||||||
"uk": "Yukreeniyaan",
|
"uk": "Yukreeniyaan",
|
||||||
"und": "Af aan la aqoon ama aan sax ahayn",
|
|
||||||
"ur": "Urduu",
|
"ur": "Urduu",
|
||||||
"vi": "Fiitnaamays",
|
"vi": "Fiitnaamays",
|
||||||
"yo": "Yoruuba",
|
"yo": "Yoruuba",
|
||||||
|
|
|
@ -226,7 +226,6 @@
|
||||||
"ms": "malaý dili",
|
"ms": "malaý dili",
|
||||||
"mt": "malta dili",
|
"mt": "malta dili",
|
||||||
"mua": "mundang dili",
|
"mua": "mundang dili",
|
||||||
"mul": "birnäçe dil",
|
|
||||||
"mus": "krik dili",
|
"mus": "krik dili",
|
||||||
"mwl": "mirand dili",
|
"mwl": "mirand dili",
|
||||||
"my": "birma dili",
|
"my": "birma dili",
|
||||||
|
@ -353,7 +352,6 @@
|
||||||
"ug": "uýgur dili",
|
"ug": "uýgur dili",
|
||||||
"uk": "ukrain dili",
|
"uk": "ukrain dili",
|
||||||
"umb": "umbundu dili",
|
"umb": "umbundu dili",
|
||||||
"und": "näbelli dil",
|
|
||||||
"ur": "urdu",
|
"ur": "urdu",
|
||||||
"uz": "özbek dili",
|
"uz": "özbek dili",
|
||||||
"vai": "wai dili",
|
"vai": "wai dili",
|
||||||
|
@ -380,7 +378,6 @@
|
||||||
"zh_Hant": "adaty hytaý dili",
|
"zh_Hant": "adaty hytaý dili",
|
||||||
"zu": "zulu dili",
|
"zu": "zulu dili",
|
||||||
"zun": "zuni dili",
|
"zun": "zuni dili",
|
||||||
"zxx": "dilçilige degişli mazmun ýok",
|
|
||||||
"zza": "zazaki dili"
|
"zza": "zazaki dili"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,7 +392,6 @@ abstract class AbstractLanguageDataProviderTest extends AbstractDataProviderTest
|
||||||
'ms',
|
'ms',
|
||||||
'mt',
|
'mt',
|
||||||
'mua',
|
'mua',
|
||||||
'mul',
|
|
||||||
'mus',
|
'mus',
|
||||||
'mwl',
|
'mwl',
|
||||||
'mwr',
|
'mwr',
|
||||||
|
@ -596,7 +595,6 @@ abstract class AbstractLanguageDataProviderTest extends AbstractDataProviderTest
|
||||||
'uga',
|
'uga',
|
||||||
'uk',
|
'uk',
|
||||||
'umb',
|
'umb',
|
||||||
'und',
|
|
||||||
'ur',
|
'ur',
|
||||||
'uz',
|
'uz',
|
||||||
'vai',
|
'vai',
|
||||||
|
@ -641,7 +639,6 @@ abstract class AbstractLanguageDataProviderTest extends AbstractDataProviderTest
|
||||||
'zh_Hant',
|
'zh_Hant',
|
||||||
'zu',
|
'zu',
|
||||||
'zun',
|
'zun',
|
||||||
'zxx',
|
|
||||||
'zza',
|
'zza',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ class GitRepositoryTest extends TestCase
|
||||||
$this->setExpectedException(RuntimeException::class);
|
$this->setExpectedException(RuntimeException::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mkdir($this->targetDir, '0777', true);
|
@mkdir($this->targetDir, 0777, true);
|
||||||
|
|
||||||
new GitRepository($this->targetDir);
|
new GitRepository($this->targetDir);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class ExpressionVoter implements VoterInterface
|
||||||
} elseif (null === $authChecker) {
|
} elseif (null === $authChecker) {
|
||||||
@trigger_error(sprintf('Argument 3 passed to "%s()" should be an instance of AuthorizationCheckerInterface, not passing it is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
@trigger_error(sprintf('Argument 3 passed to "%s()" should be an instance of AuthorizationCheckerInterface, not passing it is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED);
|
||||||
} elseif (!$authChecker instanceof AuthorizationCheckerInterface) {
|
} elseif (!$authChecker instanceof AuthorizationCheckerInterface) {
|
||||||
throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be an instance of %s or null, %s given.', __METHOD__, AuthorizationCheckerInterface::class, \is_object($authChecker) ? \get_class($authChecker) : \gettype($authChecker)));
|
throw new \TypeError(sprintf('Argument 3 passed to %s() must be an instance of %s or null, %s given.', __METHOD__, AuthorizationCheckerInterface::class, \is_object($authChecker) ? \get_class($authChecker) : \gettype($authChecker)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->expressionLanguage = $expressionLanguage;
|
$this->expressionLanguage = $expressionLanguage;
|
||||||
|
|
|
@ -330,6 +330,10 @@
|
||||||
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
|
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
|
||||||
<target>رمز المعرّف نشاط تجاري (BIC) هذا لا يرتبط مع IBAN {{ iban }}.</target>
|
<target>رمز المعرّف نشاط تجاري (BIC) هذا لا يرتبط مع IBAN {{ iban }}.</target>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="86">
|
||||||
|
<source>This value should be valid JSON.</source>
|
||||||
|
<target>هذه القيمة يجب أن تكون صالحة ل JSON.</target>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
namespace Symfony\Component\Workflow\Event;
|
namespace Symfony\Component\Workflow\Event;
|
||||||
|
|
||||||
use Symfony\Component\EventDispatcher\Event as BaseEvent;
|
use Symfony\Component\EventDispatcher\Event as BaseEvent;
|
||||||
use Symfony\Component\Workflow\Exception\InvalidArgumentException;
|
|
||||||
use Symfony\Component\Workflow\Marking;
|
use Symfony\Component\Workflow\Marking;
|
||||||
use Symfony\Component\Workflow\Transition;
|
use Symfony\Component\Workflow\Transition;
|
||||||
use Symfony\Component\Workflow\WorkflowInterface;
|
use Symfony\Component\Workflow\WorkflowInterface;
|
||||||
|
@ -49,7 +48,7 @@ class Event extends BaseEvent
|
||||||
} elseif ($workflow instanceof WorkflowInterface) {
|
} elseif ($workflow instanceof WorkflowInterface) {
|
||||||
$this->workflow = $workflow;
|
$this->workflow = $workflow;
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidArgumentException(sprintf('The 4th parameter of "%s" should be a "%s" instance instead.', __METHOD__, WorkflowInterface::class));
|
throw new \TypeError(sprintf('The 4th parameter of "%s" should be a "%s" instance instead.', __METHOD__, WorkflowInterface::class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class GuardEvent extends Event
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function __construct($subject, Marking $marking, Transition $transition, $workflowName = 'unnamed')
|
public function __construct($subject, Marking $marking, Transition $transition, $workflowName = null)
|
||||||
{
|
{
|
||||||
parent::__construct($subject, $marking, $transition, $workflowName);
|
parent::__construct($subject, $marking, $transition, $workflowName);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
<?php
|
<?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\Component\Workflow;
|
namespace Symfony\Component\Workflow;
|
||||||
|
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
|
|
Reference in New Issue