Merge branch '4.4' into 5.0
* 4.4: [Debug] fix ClassNotFoundFatalErrorHandler [Routing] Fix using a custom matcher & generator dumper class [Serializer] Fix cache in MetadataAwareNameConverter [Dotenv] Fixed infinite loop with missing quote followed by quoted value [HttpClient] Added missing sprintf [TwigBridge] button_widget now has its title attr translated even if its label = null or false [PhpUnitBridge] When using phpenv + phpenv-composer plugin, composer executable is wrapped into a bash script [Messenger] Added check if json_encode succeeded [Messenger] Added check if json_encode succeeded [FrameworkBundle][ContainerLintCommand] Only skip .errored. services [HttpClient] fix exception in case of PSR17 discovery failure [DependencyInjection] Handle ServiceClosureArgument for callable in container linting fix processing chain adapter based cache pool [HttpKernel] release lock explicitly [Security] Prevent canceled remember-me cookie from being accepted [FrameworkBundle][TranslationUpdateCommand] Do not output positive feedback on stderr [Security\Guard] Fix missing typehints do not render preferred choices as selected
This commit is contained in:
commit
d65de0f772
@ -106,7 +106,7 @@ $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar')
|
|||||||
|| ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`))
|
|| ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer.phar`) : `which composer.phar 2> /dev/null`))
|
||||||
|| ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer`) : `which composer 2> /dev/null`))
|
|| ($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? preg_replace('/[\r\n].*/', '', `where.exe composer`) : `which composer 2> /dev/null`))
|
||||||
|| file_exists($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? `git rev-parse --show-toplevel 2> NUL` : `git rev-parse --show-toplevel 2> /dev/null`).DIRECTORY_SEPARATOR.'composer.phar')
|
|| file_exists($COMPOSER = rtrim('\\' === DIRECTORY_SEPARATOR ? `git rev-parse --show-toplevel 2> NUL` : `git rev-parse --show-toplevel 2> /dev/null`).DIRECTORY_SEPARATOR.'composer.phar')
|
||||||
? $PHP.' '.escapeshellarg($COMPOSER)
|
? (file_get_contents($COMPOSER, null, 0, 18) === '#!/usr/bin/env php' ? $PHP : '').' '.escapeshellarg($COMPOSER) // detect shell wrappers by looking at the shebang
|
||||||
: 'composer';
|
: 'composer';
|
||||||
|
|
||||||
$SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'.($PHPUNIT_VERSION < 6.0 ? ' symfony/yaml': ''));
|
$SYMFONY_PHPUNIT_REMOVE = $getEnvVar('SYMFONY_PHPUNIT_REMOVE', 'phpspec/prophecy'.($PHPUNIT_VERSION < 6.0 ? ' symfony/yaml': ''));
|
||||||
|
@ -65,12 +65,14 @@
|
|||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- if preferred_choices|length > 0 -%}
|
{%- if preferred_choices|length > 0 -%}
|
||||||
{% set options = preferred_choices %}
|
{% set options = preferred_choices %}
|
||||||
|
{% set render_preferred_choices = true %}
|
||||||
{{- block('choice_widget_options') -}}
|
{{- block('choice_widget_options') -}}
|
||||||
{%- if choices|length > 0 and separator is not none -%}
|
{%- if choices|length > 0 and separator is not none -%}
|
||||||
<option disabled="disabled">{{ separator }}</option>
|
<option disabled="disabled">{{ separator }}</option>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- set options = choices -%}
|
{%- set options = choices -%}
|
||||||
|
{%- set render_preferred_choices = false -%}
|
||||||
{{- block('choice_widget_options') -}}
|
{{- block('choice_widget_options') -}}
|
||||||
</select>
|
</select>
|
||||||
{%- endblock choice_widget_collapsed -%}
|
{%- endblock choice_widget_collapsed -%}
|
||||||
@ -83,7 +85,7 @@
|
|||||||
{{- block('choice_widget_options') -}}
|
{{- block('choice_widget_options') -}}
|
||||||
</optgroup>
|
</optgroup>
|
||||||
{%- else -%}
|
{%- else -%}
|
||||||
<option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}</option>
|
<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_translation_domain) }}</option>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{%- endblock choice_widget_options -%}
|
{%- endblock choice_widget_options -%}
|
||||||
@ -226,13 +228,11 @@
|
|||||||
'%name%': name,
|
'%name%': name,
|
||||||
'%id%': id,
|
'%id%': id,
|
||||||
}) %}
|
}) %}
|
||||||
{%- elseif label is same as(false) -%}
|
{%- elseif label is not same as(false) -%}
|
||||||
{% set translation_domain = false %}
|
|
||||||
{%- else -%}
|
|
||||||
{% set label = name|humanize %}
|
{% set label = name|humanize %}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ translation_domain is same as(false) ? label : label|trans(label_translation_parameters, translation_domain) }}</button>
|
<button type="{{ type|default('button') }}" {{ block('button_attributes') }}>{{ translation_domain is same as(false) or label is same as(false) ? label : label|trans(label_translation_parameters, translation_domain) }}</button>
|
||||||
{%- endblock button_widget -%}
|
{%- endblock button_widget -%}
|
||||||
|
|
||||||
{%- block submit_widget -%}
|
{%- block submit_widget -%}
|
||||||
|
@ -160,12 +160,14 @@
|
|||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if preferred_choices|length > 0 -%}
|
{%- if preferred_choices|length > 0 -%}
|
||||||
{% set options = preferred_choices %}
|
{% set options = preferred_choices %}
|
||||||
|
{% set render_preferred_choices = true %}
|
||||||
{{- block('choice_widget_options') -}}
|
{{- block('choice_widget_options') -}}
|
||||||
{% if choices|length > 0 and separator is not none -%}
|
{% if choices|length > 0 and separator is not none -%}
|
||||||
<option disabled="disabled">{{ separator }}</option>
|
<option disabled="disabled">{{ separator }}</option>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{% set options = choices -%}
|
{% set options = choices -%}
|
||||||
|
{%- set render_preferred_choices = false -%}
|
||||||
{{- block('choice_widget_options') -}}
|
{{- block('choice_widget_options') -}}
|
||||||
</select>
|
</select>
|
||||||
{%- endblock choice_widget_collapsed %}
|
{%- endblock choice_widget_collapsed %}
|
||||||
|
@ -546,6 +546,31 @@ abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSingleChoiceWithSelectedPreferred()
|
||||||
|
{
|
||||||
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [
|
||||||
|
'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'],
|
||||||
|
'preferred_choices' => ['&a'],
|
||||||
|
'multiple' => false,
|
||||||
|
'expanded' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->assertWidgetMatchesXpath($form->createView(), ['separator' => '-- sep --', 'attr' => ['class' => 'my&class']],
|
||||||
|
'/select
|
||||||
|
[@name="name"]
|
||||||
|
[@class="my&class form-control"]
|
||||||
|
[not(@required)]
|
||||||
|
[
|
||||||
|
./option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"]
|
||||||
|
/following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"]
|
||||||
|
/following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"]
|
||||||
|
/following-sibling::option[@value="&b"][.="[trans]Choice&B[/trans]"]
|
||||||
|
]
|
||||||
|
[count(./option)=4]
|
||||||
|
'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSingleChoiceWithPreferredAndNoSeparator()
|
public function testSingleChoiceWithPreferredAndNoSeparator()
|
||||||
{
|
{
|
||||||
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [
|
$form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [
|
||||||
|
@ -102,11 +102,12 @@ final class ContainerLintCommand extends Command
|
|||||||
$refl->setAccessible(true);
|
$refl->setAccessible(true);
|
||||||
$refl->setValue($parameterBag, true);
|
$refl->setValue($parameterBag, true);
|
||||||
|
|
||||||
$passConfig = $container->getCompilerPassConfig();
|
$skippedIds = [];
|
||||||
$passConfig->setRemovingPasses([]);
|
foreach ($container->getServiceIds() as $serviceId) {
|
||||||
$passConfig->setAfterRemovingPasses([]);
|
if (0 === strpos($serviceId, '.errored.')) {
|
||||||
|
$skippedIds[$serviceId] = true;
|
||||||
$skippedIds = $kernelContainer->getRemovedIds();
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$container->setParameter('container.build_hash', 'lint_container');
|
$container->setParameter('container.build_hash', 'lint_container');
|
||||||
|
@ -175,12 +175,12 @@ EOF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$errorIo->title('Translation Messages Extractor and Dumper');
|
$io->title('Translation Messages Extractor and Dumper');
|
||||||
$errorIo->comment(sprintf('Generating "<info>%s</info>" translation files for "<info>%s</info>"', $input->getArgument('locale'), $currentName));
|
$io->comment(sprintf('Generating "<info>%s</info>" translation files for "<info>%s</info>"', $input->getArgument('locale'), $currentName));
|
||||||
|
|
||||||
// load any messages from templates
|
// load any messages from templates
|
||||||
$extractedCatalogue = new MessageCatalogue($input->getArgument('locale'));
|
$extractedCatalogue = new MessageCatalogue($input->getArgument('locale'));
|
||||||
$errorIo->comment('Parsing templates...');
|
$io->comment('Parsing templates...');
|
||||||
$this->extractor->setPrefix($input->getOption('prefix'));
|
$this->extractor->setPrefix($input->getOption('prefix'));
|
||||||
foreach ($viewsPaths as $path) {
|
foreach ($viewsPaths as $path) {
|
||||||
if (is_dir($path) || is_file($path)) {
|
if (is_dir($path) || is_file($path)) {
|
||||||
@ -190,7 +190,7 @@ EOF
|
|||||||
|
|
||||||
// load any existing messages from the translation files
|
// load any existing messages from the translation files
|
||||||
$currentCatalogue = new MessageCatalogue($input->getArgument('locale'));
|
$currentCatalogue = new MessageCatalogue($input->getArgument('locale'));
|
||||||
$errorIo->comment('Loading translation files...');
|
$io->comment('Loading translation files...');
|
||||||
foreach ($transPaths as $path) {
|
foreach ($transPaths as $path) {
|
||||||
if (is_dir($path)) {
|
if (is_dir($path)) {
|
||||||
$this->reader->read($path, $currentCatalogue);
|
$this->reader->read($path, $currentCatalogue);
|
||||||
@ -258,7 +258,7 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('xlf' === $input->getOption('output-format')) {
|
if ('xlf' === $input->getOption('output-format')) {
|
||||||
$errorIo->comment(sprintf('Xliff output version is <info>%s</info>', $input->getOption('xliff-version')));
|
$io->comment(sprintf('Xliff output version is <info>%s</info>', $input->getOption('xliff-version')));
|
||||||
}
|
}
|
||||||
|
|
||||||
$resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was');
|
$resultMessage = sprintf('%d message%s successfully extracted', $extractedMessagesCount, $extractedMessagesCount > 1 ? 's were' : ' was');
|
||||||
@ -270,7 +270,7 @@ EOF
|
|||||||
|
|
||||||
// save the files
|
// save the files
|
||||||
if (true === $input->getOption('force')) {
|
if (true === $input->getOption('force')) {
|
||||||
$errorIo->comment('Writing files...');
|
$io->comment('Writing files...');
|
||||||
|
|
||||||
$bundleTransPath = false;
|
$bundleTransPath = false;
|
||||||
foreach ($transPaths as $path) {
|
foreach ($transPaths as $path) {
|
||||||
@ -290,7 +290,7 @@ EOF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$errorIo->success($resultMessage.'.');
|
$io->success($resultMessage.'.');
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class ClearRememberMeTest extends AbstractWebTestCase
|
|||||||
$this->assertNotNull($cookieJar->get('REMEMBERME'));
|
$this->assertNotNull($cookieJar->get('REMEMBERME'));
|
||||||
|
|
||||||
$client->request('GET', '/foo');
|
$client->request('GET', '/foo');
|
||||||
$this->assertSame(200, $client->getResponse()->getStatusCode());
|
$this->assertRedirect($client->getResponse(), '/login');
|
||||||
$this->assertNull($cookieJar->get('REMEMBERME'));
|
$this->assertNull($cookieJar->get('REMEMBERME'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
"symfony/security-core": "^4.4|^5.0",
|
"symfony/security-core": "^4.4|^5.0",
|
||||||
"symfony/security-csrf": "^4.4|^5.0",
|
"symfony/security-csrf": "^4.4|^5.0",
|
||||||
"symfony/security-guard": "^4.4|^5.0",
|
"symfony/security-guard": "^4.4|^5.0",
|
||||||
"symfony/security-http": "^4.4.1|^5.0.1"
|
"symfony/security-http": "^4.4.3|^5.0.3"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/doctrine-bundle": "^2.0",
|
"doctrine/doctrine-bundle": "^2.0",
|
||||||
|
@ -103,7 +103,12 @@ class CachePoolPass implements CompilerPassInterface
|
|||||||
if (ChainAdapter::class === $class) {
|
if (ChainAdapter::class === $class) {
|
||||||
$adapters = [];
|
$adapters = [];
|
||||||
foreach ($adapter->getArgument(0) as $provider => $adapter) {
|
foreach ($adapter->getArgument(0) as $provider => $adapter) {
|
||||||
|
if ($adapter instanceof ChildDefinition) {
|
||||||
|
$chainedPool = $adapter;
|
||||||
|
} else {
|
||||||
$chainedPool = $adapter = new ChildDefinition($adapter);
|
$chainedPool = $adapter = new ChildDefinition($adapter);
|
||||||
|
}
|
||||||
|
|
||||||
$chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]];
|
$chainedTags = [\is_int($provider) ? [] : ['provider' => $provider]];
|
||||||
$chainedClass = '';
|
$chainedClass = '';
|
||||||
|
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
namespace Symfony\Component\Cache\Tests\DependencyInjection;
|
namespace Symfony\Component\Cache\Tests\DependencyInjection;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\Cache\Adapter\ApcuAdapter;
|
||||||
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
use Symfony\Component\Cache\Adapter\ArrayAdapter;
|
||||||
|
use Symfony\Component\Cache\Adapter\ChainAdapter;
|
||||||
use Symfony\Component\Cache\Adapter\RedisAdapter;
|
use Symfony\Component\Cache\Adapter\RedisAdapter;
|
||||||
use Symfony\Component\Cache\DependencyInjection\CachePoolPass;
|
use Symfony\Component\Cache\DependencyInjection\CachePoolPass;
|
||||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||||
@ -174,4 +176,42 @@ class CachePoolPassTest extends TestCase
|
|||||||
|
|
||||||
$this->cachePoolPass->process($container);
|
$this->cachePoolPass->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testChainAdapterPool()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->setParameter('kernel.container_class', 'app');
|
||||||
|
$container->setParameter('kernel.project_dir', 'foo');
|
||||||
|
|
||||||
|
$container->register('cache.adapter.array', ArrayAdapter::class)
|
||||||
|
->addTag('cache.pool');
|
||||||
|
$container->register('cache.adapter.apcu', ApcuAdapter::class)
|
||||||
|
->setArguments([null, 0, null])
|
||||||
|
->addTag('cache.pool');
|
||||||
|
$container->register('cache.chain', ChainAdapter::class)
|
||||||
|
->addArgument(['cache.adapter.array', 'cache.adapter.apcu'])
|
||||||
|
->addTag('cache.pool');
|
||||||
|
$container->setDefinition('cache.app', new ChildDefinition('cache.chain'))
|
||||||
|
->addTag('cache.pool');
|
||||||
|
$container->setDefinition('doctrine.result_cache_pool', new ChildDefinition('cache.app'))
|
||||||
|
->addTag('cache.pool');
|
||||||
|
|
||||||
|
$this->cachePoolPass->process($container);
|
||||||
|
|
||||||
|
$appCachePool = $container->getDefinition('cache.app');
|
||||||
|
$this->assertInstanceOf(ChildDefinition::class, $appCachePool);
|
||||||
|
$this->assertSame('cache.chain', $appCachePool->getParent());
|
||||||
|
|
||||||
|
$chainCachePool = $container->getDefinition('cache.chain');
|
||||||
|
$this->assertNotInstanceOf(ChildDefinition::class, $chainCachePool);
|
||||||
|
$this->assertCount(2, $chainCachePool->getArgument(0));
|
||||||
|
$this->assertInstanceOf(ChildDefinition::class, $chainCachePool->getArgument(0)[0]);
|
||||||
|
$this->assertSame('cache.adapter.array', $chainCachePool->getArgument(0)[0]->getParent());
|
||||||
|
$this->assertInstanceOf(ChildDefinition::class, $chainCachePool->getArgument(0)[1]);
|
||||||
|
$this->assertSame('cache.adapter.apcu', $chainCachePool->getArgument(0)[1]->getParent());
|
||||||
|
|
||||||
|
$doctrineCachePool = $container->getDefinition('doctrine.result_cache_pool');
|
||||||
|
$this->assertInstanceOf(ChildDefinition::class, $doctrineCachePool);
|
||||||
|
$this->assertSame('cache.app', $doctrineCachePool->getParent());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||||
use Symfony\Component\DependencyInjection\Container;
|
use Symfony\Component\DependencyInjection\Container;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
|
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
|
||||||
@ -219,6 +220,10 @@ final class CheckTypeDeclarationsPass extends AbstractRecursivePass
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (\in_array($type, ['callable', 'Closure'], true) && $value instanceof ServiceClosureArgument) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ('iterable' === $type && (\is_array($value) || $value instanceof \Traversable || $value instanceof IteratorArgument)) {
|
if ('iterable' === $type && (\is_array($value) || $value instanceof \Traversable || $value instanceof IteratorArgument)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
|||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass;
|
use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass;
|
use Symfony\Component\DependencyInjection\Compiler\ResolveParameterPlaceHoldersPass;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
@ -697,4 +698,28 @@ class CheckTypeDeclarationsPassTest extends TestCase
|
|||||||
|
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testProcessSuccessWhenPassingServiceClosureArgumentToCallable()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$container->register('bar', BarMethodCall::class)
|
||||||
|
->addMethodCall('setCallable', [new ServiceClosureArgument(new Reference('foo'))]);
|
||||||
|
|
||||||
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessSuccessWhenPassingServiceClosureArgumentToClosure()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$container->register('bar', BarMethodCall::class)
|
||||||
|
->addMethodCall('setClosure', [new ServiceClosureArgument(new Reference('foo'))]);
|
||||||
|
|
||||||
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
|
$this->addToAssertionCount(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,4 +40,8 @@ class BarMethodCall
|
|||||||
public function setCallable(callable $callable): void
|
public function setCallable(callable $callable): void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setClosure(\Closure $closure): void
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,7 +272,10 @@ final class Dotenv
|
|||||||
$this->cursor += 1 + $len;
|
$this->cursor += 1 + $len;
|
||||||
} elseif ('"' === $this->data[$this->cursor]) {
|
} elseif ('"' === $this->data[$this->cursor]) {
|
||||||
$value = '';
|
$value = '';
|
||||||
++$this->cursor;
|
|
||||||
|
if (++$this->cursor === $this->end) {
|
||||||
|
throw $this->createFormatException('Missing quote to end the value');
|
||||||
|
}
|
||||||
|
|
||||||
while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) {
|
while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) {
|
||||||
$value .= $this->data[$this->cursor];
|
$value .= $this->data[$this->cursor];
|
||||||
|
@ -40,6 +40,7 @@ class DotenvTest extends TestCase
|
|||||||
['FOO', "Missing = in the environment variable declaration in \".env\" at line 1.\n...FOO...\n ^ line 1 offset 3"],
|
['FOO', "Missing = in the environment variable declaration in \".env\" at line 1.\n...FOO...\n ^ line 1 offset 3"],
|
||||||
['FOO="foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO=\"foo...\n ^ line 1 offset 8"],
|
['FOO="foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO=\"foo...\n ^ line 1 offset 8"],
|
||||||
['FOO=\'foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO='foo...\n ^ line 1 offset 8"],
|
['FOO=\'foo', "Missing quote to end the value in \".env\" at line 1.\n...FOO='foo...\n ^ line 1 offset 8"],
|
||||||
|
["FOO=\"foo\nBAR=\"bar\"", "Missing quote to end the value in \".env\" at line 1.\n...FOO=\"foo\\nBAR=\"bar\"...\n ^ line 1 offset 18"],
|
||||||
['FOO=\'foo'."\n", "Missing quote to end the value in \".env\" at line 1.\n...FOO='foo\\n...\n ^ line 1 offset 9"],
|
['FOO=\'foo'."\n", "Missing quote to end the value in \".env\" at line 1.\n...FOO='foo\\n...\n ^ line 1 offset 9"],
|
||||||
['export FOO', "Unable to unset an environment variable in \".env\" at line 1.\n...export FOO...\n ^ line 1 offset 10"],
|
['export FOO', "Unable to unset an environment variable in \".env\" at line 1.\n...export FOO...\n ^ line 1 offset 10"],
|
||||||
['FOO=${FOO', "Unclosed braces on variable expansion in \".env\" at line 1.\n...FOO=\${FOO...\n ^ line 1 offset 9"],
|
['FOO=${FOO', "Unclosed braces on variable expansion in \".env\" at line 1.\n...FOO=\${FOO...\n ^ line 1 offset 9"],
|
||||||
|
@ -30,6 +30,10 @@ class ClassNotFoundErrorEnhancerTest extends TestCase
|
|||||||
// get class loaders wrapped by DebugClassLoader
|
// get class loaders wrapped by DebugClassLoader
|
||||||
if ($function[0] instanceof DebugClassLoader) {
|
if ($function[0] instanceof DebugClassLoader) {
|
||||||
$function = $function[0]->getClassLoader();
|
$function = $function[0]->getClassLoader();
|
||||||
|
|
||||||
|
if (!\is_array($function)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($function[0] instanceof ComposerClassLoader) {
|
if ($function[0] instanceof ComposerClassLoader) {
|
||||||
|
@ -16,6 +16,7 @@ use Http\Client\Exception\NetworkException;
|
|||||||
use Http\Client\Exception\RequestException;
|
use Http\Client\Exception\RequestException;
|
||||||
use Http\Client\HttpAsyncClient;
|
use Http\Client\HttpAsyncClient;
|
||||||
use Http\Client\HttpClient as HttplugInterface;
|
use Http\Client\HttpClient as HttplugInterface;
|
||||||
|
use Http\Discovery\Exception\NotFoundException;
|
||||||
use Http\Discovery\Psr17FactoryDiscovery;
|
use Http\Discovery\Psr17FactoryDiscovery;
|
||||||
use Http\Message\RequestFactory;
|
use Http\Message\RequestFactory;
|
||||||
use Http\Message\StreamFactory;
|
use Http\Message\StreamFactory;
|
||||||
@ -75,9 +76,13 @@ final class HttplugClient implements HttplugInterface, HttpAsyncClient, RequestF
|
|||||||
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
|
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
|
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
|
||||||
$this->responseFactory = $this->responseFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
|
$this->responseFactory = $this->responseFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
|
||||||
$this->streamFactory = $this->streamFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
|
$this->streamFactory = $this->streamFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been found. Try running "composer require nyholm/psr7".', 0, $e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->waitLoop = new HttplugWaitLoop($this->client, $this->promisePool, $this->responseFactory, $this->streamFactory);
|
$this->waitLoop = new HttplugWaitLoop($this->client, $this->promisePool, $this->responseFactory, $this->streamFactory);
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace Symfony\Component\HttpClient;
|
namespace Symfony\Component\HttpClient;
|
||||||
|
|
||||||
|
use Http\Discovery\Exception\NotFoundException;
|
||||||
use Http\Discovery\Psr17FactoryDiscovery;
|
use Http\Discovery\Psr17FactoryDiscovery;
|
||||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||||
use Nyholm\Psr7\Request;
|
use Nyholm\Psr7\Request;
|
||||||
@ -68,9 +69,13 @@ final class Psr18Client implements ClientInterface, RequestFactoryInterface, Str
|
|||||||
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
|
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\Psr18Client" as no PSR-17 factories have been provided. Try running "composer require nyholm/psr7".');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
|
$psr17Factory = class_exists(Psr17Factory::class, false) ? new Psr17Factory() : null;
|
||||||
$this->responseFactory = $this->responseFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
|
$this->responseFactory = $this->responseFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findResponseFactory();
|
||||||
$this->streamFactory = $this->streamFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
|
$this->streamFactory = $this->streamFactory ?? $psr17Factory ?? Psr17FactoryDiscovery::findStreamFactory();
|
||||||
|
} catch (NotFoundException $e) {
|
||||||
|
throw new \LogicException('You cannot use the "Symfony\Component\HttpClient\HttplugClient" as no PSR-17 factories have been found. Try running "composer require nyholm/psr7".', 0, $e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -353,7 +353,7 @@ trait ResponseTrait
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('' !== $chunk && null !== $response->content && \strlen($chunk) !== fwrite($response->content, $chunk)) {
|
if ('' !== $chunk && null !== $response->content && \strlen($chunk) !== fwrite($response->content, $chunk)) {
|
||||||
$multi->handlesActivity[$j] = [null, new TransportException('Failed writing %d bytes to the response buffer.', \strlen($chunk))];
|
$multi->handlesActivity[$j] = [null, new TransportException(sprintf('Failed writing %d bytes to the response buffer.', \strlen($chunk)))];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,7 +475,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct()
|
public function release()
|
||||||
{
|
{
|
||||||
flock($this->lock, LOCK_UN);
|
flock($this->lock, LOCK_UN);
|
||||||
fclose($this->lock);
|
fclose($this->lock);
|
||||||
@ -553,7 +553,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
|
$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
|
||||||
unset($cache);
|
$cache->release();
|
||||||
$this->container = require $cachePath;
|
$this->container = require $cachePath;
|
||||||
$this->container->set('kernel', $this);
|
$this->container->set('kernel', $this);
|
||||||
|
|
||||||
|
@ -186,6 +186,18 @@ class ConnectionTest extends TestCase
|
|||||||
$redis->del('messenger-getnonblocking');
|
$redis->del('messenger-getnonblocking');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testJsonError()
|
||||||
|
{
|
||||||
|
$redis = new \Redis();
|
||||||
|
$connection = Connection::fromDsn('redis://localhost/json-error', [], $redis);
|
||||||
|
try {
|
||||||
|
$connection->add("\xB1\x31", []);
|
||||||
|
} catch (TransportException $e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertSame('Malformed UTF-8 characters, possibly incorrectly encoded', $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
public function testMaxEntries()
|
public function testMaxEntries()
|
||||||
{
|
{
|
||||||
$redis = $this->getMockBuilder(\Redis::class)->disableOriginalConstructor()->getMock();
|
$redis = $this->getMockBuilder(\Redis::class)->disableOriginalConstructor()->getMock();
|
||||||
|
@ -248,6 +248,10 @@ class Connection
|
|||||||
'uniqid' => uniqid('', true),
|
'uniqid' => uniqid('', true),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (false === $message) {
|
||||||
|
throw new TransportException(json_last_error_msg());
|
||||||
|
}
|
||||||
|
|
||||||
$score = (int) ($this->getCurrentTimeInMilliseconds() + $delayInMs);
|
$score = (int) ($this->getCurrentTimeInMilliseconds() + $delayInMs);
|
||||||
$added = $this->connection->zadd($this->queue, ['NX'], $score, $message);
|
$added = $this->connection->zadd($this->queue, ['NX'], $score, $message);
|
||||||
} else {
|
} else {
|
||||||
@ -256,6 +260,10 @@ class Connection
|
|||||||
'headers' => $headers,
|
'headers' => $headers,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (false === $message) {
|
||||||
|
throw new TransportException(json_last_error_msg());
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->maxEntries) {
|
if ($this->maxEntries) {
|
||||||
$added = $this->connection->xadd($this->stream, '*', ['message' => $message], $this->maxEntries, true);
|
$added = $this->connection->xadd($this->stream, '*', ['message' => $message], $this->maxEntries, true);
|
||||||
} else {
|
} else {
|
||||||
|
@ -45,7 +45,7 @@ class GuardAuthenticationListener extends AbstractListener
|
|||||||
* @param string $providerKey The provider (i.e. firewall) key
|
* @param string $providerKey The provider (i.e. firewall) key
|
||||||
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
|
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
|
||||||
*/
|
*/
|
||||||
public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, string $providerKey, $guardAuthenticators, LoggerInterface $logger = null)
|
public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, string $providerKey, iterable $guardAuthenticators, LoggerInterface $logger = null)
|
||||||
{
|
{
|
||||||
if (empty($providerKey)) {
|
if (empty($providerKey)) {
|
||||||
throw new \InvalidArgumentException('$providerKey must not be empty.');
|
throw new \InvalidArgumentException('$providerKey must not be empty.');
|
||||||
|
@ -48,7 +48,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface
|
|||||||
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
|
* @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
|
||||||
* @param string $providerKey The provider (i.e. firewall) key
|
* @param string $providerKey The provider (i.e. firewall) key
|
||||||
*/
|
*/
|
||||||
public function __construct($guardAuthenticators, UserProviderInterface $userProvider, string $providerKey, UserCheckerInterface $userChecker, UserPasswordEncoderInterface $passwordEncoder = null)
|
public function __construct(iterable $guardAuthenticators, UserProviderInterface $userProvider, string $providerKey, UserCheckerInterface $userChecker, UserPasswordEncoderInterface $passwordEncoder = null)
|
||||||
{
|
{
|
||||||
$this->guardAuthenticators = $guardAuthenticators;
|
$this->guardAuthenticators = $guardAuthenticators;
|
||||||
$this->userProvider = $userProvider;
|
$this->userProvider = $userProvider;
|
||||||
|
@ -94,6 +94,10 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface
|
|||||||
*/
|
*/
|
||||||
final public function autoLogin(Request $request): ?TokenInterface
|
final public function autoLogin(Request $request): ?TokenInterface
|
||||||
{
|
{
|
||||||
|
if (($cookie = $request->attributes->get(self::COOKIE_ATTR_NAME)) && null === $cookie->getValue()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (null === $cookie = $request->cookies->get($this->options['name'])) {
|
if (null === $cookie = $request->cookies->get($this->options['name'])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,17 @@ class AbstractRememberMeServicesTest extends TestCase
|
|||||||
$this->assertNull($service->autoLogin(new Request()));
|
$this->assertNull($service->autoLogin(new Request()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAutoLoginReturnsNullAfterLoginFail()
|
||||||
|
{
|
||||||
|
$service = $this->getService(null, ['name' => 'foo', 'path' => null, 'domain' => null]);
|
||||||
|
|
||||||
|
$request = new Request();
|
||||||
|
$request->cookies->set('foo', 'foo');
|
||||||
|
|
||||||
|
$service->loginFail($request);
|
||||||
|
$this->assertNull($service->autoLogin($request));
|
||||||
|
}
|
||||||
|
|
||||||
public function testAutoLoginThrowsExceptionWhenImplementationDoesNotReturnUserInterface()
|
public function testAutoLoginThrowsExceptionWhenImplementationDoesNotReturnUserInterface()
|
||||||
{
|
{
|
||||||
$this->expectException('RuntimeException');
|
$this->expectException('RuntimeException');
|
||||||
|
@ -47,7 +47,7 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface
|
|||||||
return $this->normalizeFallback($propertyName, $class, $format, $context);
|
return $this->normalizeFallback($propertyName, $class, $format, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset(self::$normalizeCache[$class][$propertyName])) {
|
if (!\array_key_exists($class, self::$normalizeCache) || !\array_key_exists($propertyName, self::$normalizeCache[$class])) {
|
||||||
self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class);
|
self::$normalizeCache[$class][$propertyName] = $this->getCacheValueForNormalization($propertyName, $class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$cacheKey = $this->getCacheKey($class, $context);
|
$cacheKey = $this->getCacheKey($class, $context);
|
||||||
if (!isset(self::$denormalizeCache[$cacheKey][$propertyName])) {
|
if (!\array_key_exists($cacheKey, self::$denormalizeCache) || !\array_key_exists($propertyName, self::$denormalizeCache[$cacheKey])) {
|
||||||
self::$denormalizeCache[$cacheKey][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class, $context);
|
self::$denormalizeCache[$cacheKey][$propertyName] = $this->getCacheValueForDenormalization($propertyName, $class, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$attributesMetadata = $this->metadataFactory->getMetadataFor($class)->getAttributesMetadata();
|
$attributesMetadata = $this->metadataFactory->getMetadataFor($class)->getAttributesMetadata();
|
||||||
if (!isset($attributesMetadata[$propertyName])) {
|
if (!\array_key_exists($propertyName, $attributesMetadata)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ final class MetadataAwareNameConverter implements AdvancedNameConverterInterface
|
|||||||
private function getCacheValueForDenormalization(string $propertyName, string $class, array $context): ?string
|
private function getCacheValueForDenormalization(string $propertyName, string $class, array $context): ?string
|
||||||
{
|
{
|
||||||
$cacheKey = $this->getCacheKey($class, $context);
|
$cacheKey = $this->getCacheKey($class, $context);
|
||||||
if (!isset(self::$attributesMetadataCache[$cacheKey])) {
|
if (!\array_key_exists($cacheKey, self::$attributesMetadataCache)) {
|
||||||
self::$attributesMetadataCache[$cacheKey] = $this->getCacheValueForAttributesMetadata($class, $context);
|
self::$attributesMetadataCache[$cacheKey] = $this->getCacheValueForAttributesMetadata($class, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user