Skip to content

Commit

Permalink
Merge branch '4.4'
Browse files Browse the repository at this point in the history
* 4.4: (33 commits)
  [DI] fix processing of regular parameter bags by MergeExtensionConfigurationPass
  [FrameworkBundle] reset cache pools between requests
  [HttpFoundation] Accept must take the lead for Request::getPreferredFormat()
  [FrameworkBundle] Allow to use the BrowserKit assertions with Panther and API Platform's test client
  Use ConnectionRegistry instead of RegistryInterface.
  Fixes windows error
  Improving the request/response format autodetection
  [Messager] Simplified MessageBus::__construct()
  [WIP][Mailer] Overwrite envelope sender and recipients from config
  [Messenger] Added more test for MessageBus
  [Mime] Updated some PHPDoc contents
  [PropertyAccess] Adds entries to CHANGELOG and UPGRADE
  fixed typo
  [FrameworkBundle] Simplified some code in the DI configuration
  [Filesystem] added missing deprecations to UPGRADE-4.3.md
  [Filesystem] depreacte calling isAbsolutePath with a null
  Fix authentication for redis transport
  only decorate when an event dispatcher was passed
  [Messenger] Added support for auto trimming of redis streams
  [FrmaeworkBundle] More simplifications in the DI configuration
  ...
  • Loading branch information
nicolas-grekas committed Jul 4, 2019
2 parents 4067043 + a70e45f commit 955421d
Show file tree
Hide file tree
Showing 12 changed files with 398 additions and 245 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -29,6 +29,7 @@ CHANGELOG
4.3.0
-----

* Deprecated the `framework.templating` option, use Twig instead.
* Added `WebTestAssertionsTrait` (included by default in `WebTestCase`)
* Renamed `Client` to `KernelBrowser`
* Not passing the project directory to the constructor of the `AssetsInstallCommand` is deprecated. This argument will
Expand Down
55 changes: 32 additions & 23 deletions DependencyInjection/Configuration.php
Expand Up @@ -297,10 +297,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode)
->cannotBeEmpty()
->end()
->arrayNode('initial_marking')
->beforeNormalization()
->ifTrue(function ($v) { return !\is_array($v); })
->then(function ($v) { return [$v]; })
->end()
->beforeNormalization()->castToArray()->end()
->defaultValue([])
->prototype('scalar')->end()
->end()
Expand Down Expand Up @@ -533,10 +530,7 @@ private function addRequestSection(ArrayNodeDefinition $rootNode)
->ifTrue(function ($v) { return \is_array($v) && isset($v['mime_type']); })
->then(function ($v) { return $v['mime_type']; })
->end()
->beforeNormalization()
->ifTrue(function ($v) { return !\is_array($v); })
->then(function ($v) { return [$v]; })
->end()
->beforeNormalization()->castToArray()->end()
->prototype('scalar')->end()
->end()
->end()
Expand All @@ -562,10 +556,7 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode)
->scalarNode('base_path')->defaultValue('')->end()
->arrayNode('base_urls')
->requiresAtLeastOneElement()
->beforeNormalization()
->ifTrue(function ($v) { return !\is_array($v); })
->then(function ($v) { return [$v]; })
->end()
->beforeNormalization()->castToArray()->end()
->prototype('scalar')->end()
->end()
->end()
Expand Down Expand Up @@ -607,10 +598,7 @@ private function addAssetsSection(ArrayNodeDefinition $rootNode)
->scalarNode('base_path')->defaultValue('')->end()
->arrayNode('base_urls')
->requiresAtLeastOneElement()
->beforeNormalization()
->ifTrue(function ($v) { return !\is_array($v); })
->then(function ($v) { return [$v]; })
->end()
->beforeNormalization()->castToArray()->end()
->prototype('scalar')->end()
->end()
->end()
Expand Down Expand Up @@ -684,10 +672,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode)
->defaultValue(['loadValidatorMetadata'])
->prototype('scalar')->end()
->treatFalseLike([])
->validate()
->ifTrue(function ($v) { return !\is_array($v); })
->then(function ($v) { return (array) $v; })
->end()
->validate()->castToArray()->end()
->end()
->scalarNode('translation_domain')->defaultValue('validators')->end()
->enumNode('email_validation_mode')->values(['html5', 'loose', 'strict'])->end()
Expand Down Expand Up @@ -1061,9 +1046,14 @@ function ($a) {
->end()
->arrayNode('retry_strategy')
->addDefaultsIfNotSet()
->validate()
->ifTrue(function ($v) { return null !== $v['service'] && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay'])); })
->thenInvalid('"service" cannot be used along with the other retry_strategy options.')
->beforeNormalization()
->always(function ($v) {
if (isset($v['service']) && (isset($v['max_retries']) || isset($v['delay']) || isset($v['multiplier']) || isset($v['max_delay']))) {
throw new \InvalidArgumentException('The "service" cannot be used along with the other "retry_strategy" options.');
}

return $v;
})
->end()
->children()
->scalarNode('service')->defaultNull()->info('Service id to override the retry strategy entirely')->end()
Expand Down Expand Up @@ -1280,6 +1270,9 @@ private function addHttpClientSection(ArrayNodeDefinition $rootNode)
->scalarNode('auth_bearer')
->info('A token enabling HTTP Bearer authorization.')
->end()
->scalarNode('auth_ntlm')
->info('A "username:password" pair to use Microsoft NTLM authentication (requires the cURL extension).')
->end()
->arrayNode('query')
->info('Associative array of query string values merged with the base URI.')
->useAttributeAsKey('key')
Expand Down Expand Up @@ -1391,6 +1384,22 @@ private function addMailerSection(ArrayNodeDefinition $rootNode)
->{!class_exists(FullStack::class) && class_exists(Mailer::class) ? 'canBeDisabled' : 'canBeEnabled'}()
->children()
->scalarNode('dsn')->defaultValue('smtp://null')->end()
->arrayNode('envelope')
->info('Mailer Envelope configuration')
->children()
->scalarNode('sender')->end()
->arrayNode('recipients')
->performNoDeepMerging()
->beforeNormalization()
->ifArray()
->then(function ($v) {
return array_filter(array_values($v));
})
->end()
->prototype('scalar')->end()
->end()
->end()
->end()
->end()
->end()
->end()
Expand Down
7 changes: 7 additions & 0 deletions DependencyInjection/FrameworkExtension.php
Expand Up @@ -1763,6 +1763,13 @@ private function registerMailerConfiguration(array $config, ContainerBuilder $co

$loader->load('mailer.xml');
$container->getDefinition('mailer.default_transport')->setArgument(0, $config['dsn']);

$recipients = $config['envelope']['recipients'] ?? null;
$sender = $config['envelope']['sender'] ?? null;

$envelopeListener = $container->getDefinition('mailer.envelope_listener');
$envelopeListener->setArgument(0, $sender);
$envelopeListener->setArgument(1, $recipients);
}

/**
Expand Down
16 changes: 8 additions & 8 deletions Resources/config/cache.xml
Expand Up @@ -8,7 +8,7 @@
<defaults public="false" />

<service id="cache.app" parent="cache.adapter.filesystem" public="true">
<tag name="cache.pool" clearer="cache.app_clearer" reset="reset" />
<tag name="cache.pool" clearer="cache.app_clearer" />
</service>

<service id="cache.app.taggable" class="Symfony\Component\Cache\Adapter\TagAwareAdapter">
Expand Down Expand Up @@ -41,7 +41,7 @@

<service id="cache.adapter.system" class="Symfony\Component\Cache\Adapter\AdapterInterface" abstract="true">
<factory class="Symfony\Component\Cache\Adapter\AbstractAdapter" method="createSystemCache" />
<tag name="cache.pool" clearer="cache.system_clearer" />
<tag name="cache.pool" clearer="cache.system_clearer" reset="reset" />
<tag name="monolog.logger" channel="cache" />
<argument /> <!-- namespace -->
<argument>0</argument> <!-- default lifetime -->
Expand All @@ -51,7 +51,7 @@
</service>

<service id="cache.adapter.apcu" class="Symfony\Component\Cache\Adapter\ApcuAdapter" abstract="true">
<tag name="cache.pool" clearer="cache.default_clearer" />
<tag name="cache.pool" clearer="cache.default_clearer" reset="reset" />
<tag name="monolog.logger" channel="cache" />
<argument /> <!-- namespace -->
<argument>0</argument> <!-- default lifetime -->
Expand All @@ -62,7 +62,7 @@
</service>

<service id="cache.adapter.doctrine" class="Symfony\Component\Cache\Adapter\DoctrineAdapter" abstract="true">
<tag name="cache.pool" provider="cache.default_doctrine_provider" clearer="cache.default_clearer" />
<tag name="cache.pool" provider="cache.default_doctrine_provider" clearer="cache.default_clearer" reset="reset" />
<tag name="monolog.logger" channel="cache" />
<argument /> <!-- Doctrine provider service -->
<argument /> <!-- namespace -->
Expand All @@ -73,7 +73,7 @@
</service>

<service id="cache.adapter.filesystem" class="Symfony\Component\Cache\Adapter\FilesystemAdapter" abstract="true">
<tag name="cache.pool" clearer="cache.default_clearer" />
<tag name="cache.pool" clearer="cache.default_clearer" reset="reset" />
<tag name="monolog.logger" channel="cache" />
<argument /> <!-- namespace -->
<argument>0</argument> <!-- default lifetime -->
Expand All @@ -85,14 +85,14 @@
</service>

<service id="cache.adapter.psr6" class="Symfony\Component\Cache\Adapter\ProxyAdapter" abstract="true">
<tag name="cache.pool" provider="cache.default_psr6_provider" clearer="cache.default_clearer" />
<tag name="cache.pool" provider="cache.default_psr6_provider" clearer="cache.default_clearer" reset="reset" />
<argument /> <!-- PSR-6 provider service -->
<argument /> <!-- namespace -->
<argument>0</argument> <!-- default lifetime -->
</service>

<service id="cache.adapter.redis" class="Symfony\Component\Cache\Adapter\RedisAdapter" abstract="true">
<tag name="cache.pool" provider="cache.default_redis_provider" clearer="cache.default_clearer" />
<tag name="cache.pool" provider="cache.default_redis_provider" clearer="cache.default_clearer" reset="reset" />
<tag name="monolog.logger" channel="cache" />
<argument /> <!-- Redis connection service -->
<argument /> <!-- namespace -->
Expand Down Expand Up @@ -129,7 +129,7 @@
</service>

<service id="cache.adapter.array" class="Symfony\Component\Cache\Adapter\ArrayAdapter" abstract="true">
<tag name="cache.pool" clearer="cache.default_clearer" />
<tag name="cache.pool" clearer="cache.default_clearer" reset="reset" />
<tag name="monolog.logger" channel="cache" />
<argument>0</argument> <!-- default lifetime -->
<call method="setLogger">
Expand Down
6 changes: 6 additions & 0 deletions Resources/config/mailer.xml
Expand Up @@ -25,5 +25,11 @@
<argument type="service" id="mailer.default_transport" />
<tag name="messenger.message_handler" />
</service>

<service id="mailer.envelope_listener" class="Symfony\Component\Mailer\EventListener\EnvelopeListener">
<argument /> <!-- sender -->
<argument /> <!-- recipients -->
<tag name="kernel.event_subscriber"/>
</service>
</services>
</container>
159 changes: 159 additions & 0 deletions Test/BrowserKitAssertionsTrait.php
@@ -0,0 +1,159 @@
<?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\Bundle\FrameworkBundle\Test;

use PHPUnit\Framework\Constraint\LogicalAnd;
use PHPUnit\Framework\Constraint\LogicalNot;
use Symfony\Component\BrowserKit\AbstractBrowser;
use Symfony\Component\BrowserKit\Test\Constraint as BrowserKitConstraint;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Test\Constraint as ResponseConstraint;

/**
* Ideas borrowed from Laravel Dusk's assertions.
*
* @see https://laravel.com/docs/5.7/dusk#available-assertions
*/
trait BrowserKitAssertionsTrait
{
public static function assertResponseIsSuccessful(string $message = ''): void
{
self::assertThat(self::getResponse(), new ResponseConstraint\ResponseIsSuccessful(), $message);
}

public static function assertResponseStatusCodeSame(int $expectedCode, string $message = ''): void
{
self::assertThat(self::getResponse(), new ResponseConstraint\ResponseStatusCodeSame($expectedCode), $message);
}

public static function assertResponseRedirects(string $expectedLocation = null, int $expectedCode = null, string $message = ''): void
{
$constraint = new ResponseConstraint\ResponseIsRedirected();
if ($expectedLocation) {
$constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseHeaderSame('Location', $expectedLocation));
}
if ($expectedCode) {
$constraint = LogicalAnd::fromConstraints($constraint, new ResponseConstraint\ResponseStatusCodeSame($expectedCode));
}

self::assertThat(self::getResponse(), $constraint, $message);
}

public static function assertResponseHasHeader(string $headerName, string $message = ''): void
{
self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHasHeader($headerName), $message);
}

public static function assertResponseNotHasHeader(string $headerName, string $message = ''): void
{
self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHasHeader($headerName)), $message);
}

public static function assertResponseHeaderSame(string $headerName, string $expectedValue, string $message = ''): void
{
self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue), $message);
}

public static function assertResponseHeaderNotSame(string $headerName, string $expectedValue, string $message = ''): void
{
self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHeaderSame($headerName, $expectedValue)), $message);
}

public static function assertResponseHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
{
self::assertThat(self::getResponse(), new ResponseConstraint\ResponseHasCookie($name, $path, $domain), $message);
}

public static function assertResponseNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
{
self::assertThat(self::getResponse(), new LogicalNot(new ResponseConstraint\ResponseHasCookie($name, $path, $domain)), $message);
}

public static function assertResponseCookieValueSame(string $name, string $expectedValue, string $path = '/', string $domain = null, string $message = ''): void
{
self::assertThat(self::getResponse(), LogicalAnd::fromConstraints(
new ResponseConstraint\ResponseHasCookie($name, $path, $domain),
new ResponseConstraint\ResponseCookieValueSame($name, $expectedValue, $path, $domain)
), $message);
}

public static function assertBrowserHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
{
self::assertThat(self::getClient(), new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain), $message);
}

public static function assertBrowserNotHasCookie(string $name, string $path = '/', string $domain = null, string $message = ''): void
{
self::assertThat(self::getClient(), new LogicalNot(new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain)), $message);
}

public static function assertBrowserCookieValueSame(string $name, string $expectedValue, bool $raw = false, string $path = '/', string $domain = null, string $message = ''): void
{
self::assertThat(self::getClient(), LogicalAnd::fromConstraints(
new BrowserKitConstraint\BrowserHasCookie($name, $path, $domain),
new BrowserKitConstraint\BrowserCookieValueSame($name, $expectedValue, $raw, $path, $domain)
), $message);
}

public static function assertRequestAttributeValueSame(string $name, string $expectedValue, string $message = ''): void
{
self::assertThat(self::getRequest(), new ResponseConstraint\RequestAttributeValueSame($name, $expectedValue), $message);
}

public static function assertRouteSame($expectedRoute, array $parameters = [], string $message = ''): void
{
$constraint = new ResponseConstraint\RequestAttributeValueSame('_route', $expectedRoute);
$constraints = [];
foreach ($parameters as $key => $value) {
$constraints[] = new ResponseConstraint\RequestAttributeValueSame($key, $value);
}
if ($constraints) {
$constraint = LogicalAnd::fromConstraints($constraint, ...$constraints);
}

self::assertThat(self::getRequest(), $constraint, $message);
}

private static function getClient(AbstractBrowser $newClient = null): ?AbstractBrowser
{
static $client;

if (0 < \func_num_args()) {
return $client = $newClient;
}

if (!$client instanceof AbstractBrowser) {
static::fail(sprintf('A client must be set to make assertions on it. Did you forget to call "%s::createClient()"?', __CLASS__));
}

return $client;
}

private static function getResponse(): Response
{
if (!$response = self::getClient()->getResponse()) {
static::fail('A client must have an HTTP Response to make assertions. Did you forget to make an HTTP request?');
}

return $response;
}

private static function getRequest(): Request
{
if (!$request = self::getClient()->getRequest()) {
static::fail('A client must have an HTTP Request to make assertions. Did you forget to make an HTTP request?');
}

return $request;
}
}

0 comments on commit 955421d

Please sign in to comment.