Merge branch '5.0' into 5.1
* 5.0: fix merge Require PHPUnit 9.3 on PHP 8 [Cache] fix catching auth errors Fix CS [FrameworkBundle] set default session.handler alias if handler_id is not provided Fix CS Readability update Fix checks for phpunit releases on Composer 2 (resolves #37601) [Serializer] Support multiple levels of discriminator mapping Use hexadecimal numerals instead of hexadecimals in strings to represent error codes. [SCA] Minor fixes on tests [WebProfilerBundle] modified url generation to use absolute urls [Mailer] Fix reply-to functionality in the SendgridApiTransport [Mime] Fix compat with HTTP requests ticket_36879 - Fix mandrill raw http request setting from email/name
This commit is contained in:
commit
1b7714a05c
@ -93,7 +93,10 @@ $passthruOrFail = function ($command) {
|
||||
}
|
||||
};
|
||||
|
||||
if (PHP_VERSION_ID >= 70200) {
|
||||
if (PHP_VERSION_ID >= 80000) {
|
||||
// PHP 8 requires PHPUnit 9.3+
|
||||
$PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '9.3');
|
||||
} elseif (PHP_VERSION_ID >= 70200) {
|
||||
// PHPUnit 8 requires PHP 7.2+
|
||||
$PHPUNIT_VERSION = $getEnvVar('SYMFONY_PHPUNIT_VERSION', '8.3');
|
||||
} elseif (PHP_VERSION_ID >= 70100) {
|
||||
@ -194,7 +197,11 @@ if (!file_exists("$PHPUNIT_DIR/$PHPUNIT_VERSION_DIR/phpunit") || $configurationH
|
||||
'requires' => ['php' => '*'],
|
||||
];
|
||||
|
||||
if (1 === count($info['versions'])) {
|
||||
$stableVersions = array_filter($info['versions'], function($v) {
|
||||
return !preg_match('/-dev$|^dev-/', $v);
|
||||
});
|
||||
|
||||
if (!$stableVersions) {
|
||||
$passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress -s dev phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\"");
|
||||
} else {
|
||||
$passthruOrFail("$COMPOSER create-project --ignore-platform-reqs --no-install --prefer-dist --no-scripts --no-plugins --no-progress phpunit/phpunit $PHPUNIT_VERSION_DIR \"$PHPUNIT_VERSION.*\"");
|
||||
|
@ -956,6 +956,7 @@ class FrameworkExtension extends Extension
|
||||
// Set the handler class to be null
|
||||
$container->getDefinition('session.storage.native')->replaceArgument(1, null);
|
||||
$container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null);
|
||||
$container->setAlias('session.handler', 'session.handler.native_file')->setPrivate(true);
|
||||
} else {
|
||||
$container->resolveEnvPlaceholders($config['handler_id'], null, $usedEnvs);
|
||||
|
||||
|
@ -503,6 +503,7 @@ abstract class FrameworkExtensionTest extends TestCase
|
||||
$this->assertTrue($container->hasDefinition('session'), '->registerSessionConfiguration() loads session.xml');
|
||||
$this->assertNull($container->getDefinition('session.storage.native')->getArgument(1));
|
||||
$this->assertNull($container->getDefinition('session.storage.php_bridge')->getArgument(0));
|
||||
$this->assertSame('session.handler.native_file', (string) $container->getAlias('session.handler'));
|
||||
|
||||
$expected = ['session', 'initialized_session', 'logger'];
|
||||
$this->assertEquals($expected, array_keys($container->getDefinition('session_listener')->getArgument(0)->getValues()));
|
||||
|
@ -50,7 +50,7 @@ class UserPasswordEncoderCommandTest extends AbstractWebTestCase
|
||||
], ['interactive' => false]);
|
||||
|
||||
$this->assertStringContainsString('[ERROR] The password must not be empty.', $this->passwordEncoderCommandTester->getDisplay());
|
||||
$this->assertEquals($statusCode, 1);
|
||||
$this->assertEquals(1, $statusCode);
|
||||
}
|
||||
|
||||
public function testEncodePasswordBcrypt()
|
||||
|
@ -123,8 +123,15 @@ class ContentSecurityPolicyHandler
|
||||
|
||||
$headers = $this->getCspHeaders($response);
|
||||
|
||||
$types = [
|
||||
'script-src' => 'csp_script_nonce',
|
||||
'script-src-elem' => 'csp_script_nonce',
|
||||
'style-src' => 'csp_style_nonce',
|
||||
'style-src-elem' => 'csp_style_nonce',
|
||||
];
|
||||
|
||||
foreach ($headers as $header => $directives) {
|
||||
foreach (['script-src' => 'csp_script_nonce', 'script-src-elem' => 'csp_script_nonce', 'style-src' => 'csp_style_nonce', 'style-src-elem' => 'csp_style_nonce'] as $type => $tokenName) {
|
||||
foreach ($types as $type => $tokenName) {
|
||||
if ($this->authorizesInline($directives, $type)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -422,7 +422,7 @@
|
||||
newToken = (newToken || token);
|
||||
this.load(
|
||||
'sfwdt' + token,
|
||||
'{{ path("_wdt", { "token": "xxxxxx" })|escape('js') }}'.replace(/xxxxxx/, newToken),
|
||||
'{{ url("_wdt", { "token": "xxxxxx" })|escape('js') }}'.replace(/xxxxxx/, newToken),
|
||||
function(xhr, el) {
|
||||
|
||||
/* Evaluate in global scope scripts embedded inside the toolbar */
|
||||
@ -531,7 +531,7 @@
|
||||
sfwdt.innerHTML = '\
|
||||
<div class="sf-toolbarreset">\
|
||||
<div class="sf-toolbar-icon"><svg width="26" height="28" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 26 28" enable-background="new 0 0 26 28" xml:space="preserve"><path fill="#FFFFFF" d="M13 0C5.8 0 0 5.8 0 13c0 7.2 5.8 13 13 13c7.2 0 13-5.8 13-13C26 5.8 20.2 0 13 0z M20 7.5 c-0.6 0-1-0.3-1-0.9c0-0.2 0-0.4 0.2-0.6c0.1-0.3 0.2-0.3 0.2-0.4c0-0.3-0.5-0.4-0.7-0.4c-2 0.1-2.5 2.7-2.9 4.8l-0.2 1.1 c1.1 0.2 1.9 0 2.4-0.3c0.6-0.4-0.2-0.8-0.1-1.3C18 9.2 18.4 9 18.7 8.9c0.5 0 0.8 0.5 0.8 1c0 0.8-1.1 2-3.3 1.9 c-0.3 0-0.5 0-0.7-0.1L15 14.1c-0.4 1.7-0.9 4.1-2.6 6.2c-1.5 1.8-3.1 2.1-3.8 2.1c-1.3 0-2.1-0.6-2.2-1.6c0-0.9 0.8-1.4 1.3-1.4 c0.7 0 1.2 0.5 1.2 1.1c0 0.5-0.2 0.6-0.4 0.7c-0.1 0.1-0.3 0.2-0.3 0.4c0 0.1 0.1 0.3 0.4 0.3c0.5 0 0.9-0.3 1.2-0.5 c1.3-1 1.7-2.9 2.4-6.2l0.1-0.8c0.2-1.1 0.5-2.3 0.8-3.5c-0.9-0.7-1.4-1.5-2.6-1.8c-0.8-0.2-1.3 0-1.7 0.4C8.4 10 8.6 10.7 9 11.1 l0.7 0.7c0.8 0.9 1.3 1.7 1.1 2.7c-0.3 1.6-2.1 2.8-4.3 2.1c-1.9-0.6-2.2-1.9-2-2.7c0.2-0.6 0.7-0.8 1.2-0.6 c0.5 0.2 0.7 0.8 0.6 1.3c0 0.1 0 0.1-0.1 0.3C6 15 5.9 15.2 5.9 15.3c-0.1 0.4 0.4 0.7 0.8 0.8c0.8 0.3 1.7-0.2 1.9-0.9 c0.2-0.6-0.2-1.1-0.4-1.2l-0.8-0.9c-0.4-0.4-1.2-1.5-0.8-2.8c0.2-0.5 0.5-1 0.9-1.4c1-0.7 2-0.8 3-0.6c1.3 0.4 1.9 1.2 2.8 1.9 c0.5-1.3 1.1-2.6 2-3.8c0.9-1 2-1.7 3.3-1.8C20 4.8 21 5.4 21 6.3C21 6.7 20.8 7.5 20 7.5z"/></svg></div>\
|
||||
An error occurred while loading the web debug toolbar. <a href="{{ path("_profiler_home")|escape('js') }}' + newToken + '>Open the web profiler.</a>\
|
||||
An error occurred while loading the web debug toolbar. <a href="{{ url("_profiler_home")|escape('js') }}' + newToken + '>Open the web profiler.</a>\
|
||||
</div>\
|
||||
';
|
||||
sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar');
|
||||
|
@ -173,30 +173,30 @@ trait RedisTrait
|
||||
$initializer = function ($redis) use ($connect, $params, $dsn, $auth, $hosts) {
|
||||
try {
|
||||
@$redis->{$connect}($hosts[0]['host'] ?? $hosts[0]['path'], $hosts[0]['port'] ?? null, $params['timeout'], (string) $params['persistent_id'], $params['retry_interval']);
|
||||
|
||||
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
|
||||
$isConnected = $redis->isConnected();
|
||||
restore_error_handler();
|
||||
if (!$isConnected) {
|
||||
$error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : '';
|
||||
throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$error.'.');
|
||||
}
|
||||
|
||||
if ((null !== $auth && !$redis->auth($auth))
|
||||
|| ($params['dbindex'] && !$redis->select($params['dbindex']))
|
||||
|| ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout']))
|
||||
) {
|
||||
$e = preg_replace('/^ERR /', '', $redis->getLastError());
|
||||
throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e.'.');
|
||||
}
|
||||
|
||||
if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) {
|
||||
$redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
|
||||
}
|
||||
} catch (\RedisException $e) {
|
||||
throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e->getMessage());
|
||||
}
|
||||
|
||||
set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
|
||||
$isConnected = $redis->isConnected();
|
||||
restore_error_handler();
|
||||
if (!$isConnected) {
|
||||
$error = preg_match('/^Redis::p?connect\(\): (.*)/', $error, $error) ? sprintf(' (%s)', $error[1]) : '';
|
||||
throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$error.'.');
|
||||
}
|
||||
|
||||
if ((null !== $auth && !$redis->auth($auth))
|
||||
|| ($params['dbindex'] && !$redis->select($params['dbindex']))
|
||||
|| ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout']))
|
||||
) {
|
||||
$e = preg_replace('/^ERR /', '', $redis->getLastError());
|
||||
throw new InvalidArgumentException(sprintf('Redis connection "%s" failed: ', $dsn).$e.'.');
|
||||
}
|
||||
|
||||
if (0 < $params['tcp_keepalive'] && \defined('Redis::OPT_TCP_KEEPALIVE')) {
|
||||
$redis->setOption(\Redis::OPT_TCP_KEEPALIVE, $params['tcp_keepalive']);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -902,12 +902,12 @@ class ContainerBuilderTest extends TestCase
|
||||
->addTag('bar', ['bar' => 'bar'])
|
||||
->addTag('foo', ['foofoo' => 'foofoo'])
|
||||
;
|
||||
$this->assertEquals($builder->findTaggedServiceIds('foo'), [
|
||||
$this->assertEquals([
|
||||
'foo' => [
|
||||
['foo' => 'foo'],
|
||||
['foofoo' => 'foofoo'],
|
||||
],
|
||||
], '->findTaggedServiceIds() returns an array of service ids and its tag attributes');
|
||||
], $builder->findTaggedServiceIds('foo'), '->findTaggedServiceIds() returns an array of service ids and its tag attributes');
|
||||
$this->assertEquals([], $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services');
|
||||
}
|
||||
|
||||
|
@ -266,10 +266,10 @@ class DefinitionTest extends TestCase
|
||||
$def->addTag('foo', ['foo' => 'bar']);
|
||||
$this->assertEquals([[], ['foo' => 'bar']], $def->getTag('foo'), '->addTag() can adds the same tag several times');
|
||||
$def->addTag('bar', ['bar' => 'bar']);
|
||||
$this->assertEquals($def->getTags(), [
|
||||
$this->assertEquals([
|
||||
'foo' => [[], ['foo' => 'bar']],
|
||||
'bar' => [['bar' => 'bar']],
|
||||
], '->getTags() returns all tags');
|
||||
], $def->getTags(), '->getTags() returns all tags');
|
||||
}
|
||||
|
||||
public function testSetArgument()
|
||||
|
@ -170,25 +170,28 @@ class FormTest extends TestCase
|
||||
');
|
||||
|
||||
$this->assertEquals(
|
||||
array_keys($form->all()),
|
||||
['foo[2]', 'foo[3]', 'bar[foo][0]', 'bar[foo][foobar]']
|
||||
['foo[2]', 'foo[3]', 'bar[foo][0]', 'bar[foo][foobar]'],
|
||||
array_keys($form->all())
|
||||
);
|
||||
|
||||
$this->assertEquals($form->get('foo[2]')->getValue(), 'foo');
|
||||
$this->assertEquals($form->get('foo[3]')->getValue(), 'foo');
|
||||
$this->assertEquals($form->get('bar[foo][0]')->getValue(), 'foo');
|
||||
$this->assertEquals($form->get('bar[foo][foobar]')->getValue(), 'foo');
|
||||
$this->assertEquals('foo', $form->get('foo[2]')->getValue());
|
||||
$this->assertEquals('foo', $form->get('foo[3]')->getValue());
|
||||
$this->assertEquals('foo', $form->get('bar[foo][0]')->getValue());
|
||||
$this->assertEquals('foo', $form->get('bar[foo][foobar]')->getValue());
|
||||
|
||||
$form['foo[2]'] = 'bar';
|
||||
$form['foo[3]'] = 'bar';
|
||||
|
||||
$this->assertEquals($form->get('foo[2]')->getValue(), 'bar');
|
||||
$this->assertEquals($form->get('foo[3]')->getValue(), 'bar');
|
||||
$this->assertEquals('bar', $form->get('foo[2]')->getValue());
|
||||
$this->assertEquals('bar', $form->get('foo[3]')->getValue());
|
||||
|
||||
$form['bar'] = ['foo' => ['0' => 'bar', 'foobar' => 'foobar']];
|
||||
|
||||
$this->assertEquals($form->get('bar[foo][0]')->getValue(), 'bar');
|
||||
$this->assertEquals($form->get('bar[foo][foobar]')->getValue(), 'foobar');
|
||||
$this->assertEquals('bar', $form->get('bar[foo][0]')->getValue());
|
||||
$this->assertEquals(
|
||||
'foobar',
|
||||
$form->get('bar[foo][foobar]')->getValue()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -979,7 +982,7 @@ class FormTest extends TestCase
|
||||
|
||||
$nodes = $dom->getElementsByTagName('form');
|
||||
$form = new Form($nodes->item(0), 'http://example.com');
|
||||
$this->assertEquals($form->getPhpValues(), ['example' => '']);
|
||||
$this->assertEquals(['example' => ''], $form->getPhpValues());
|
||||
}
|
||||
|
||||
public function testGetReturnTypes()
|
||||
|
@ -161,9 +161,9 @@ class FlattenExceptionTest extends TestCase
|
||||
|
||||
$flattened = FlattenException::createFromThrowable($exception)->getPrevious();
|
||||
|
||||
$this->assertEquals($flattened->getMessage(), 'Oh noes!', 'The message is copied from the original exception.');
|
||||
$this->assertEquals($flattened->getCode(), 42, 'The code is copied from the original exception.');
|
||||
$this->assertEquals($flattened->getClass(), 'ParseError', 'The class is set to the class of the original exception');
|
||||
$this->assertEquals('Oh noes!', $flattened->getMessage(), 'The message is copied from the original exception.');
|
||||
$this->assertEquals(42, $flattened->getCode(), 'The code is copied from the original exception.');
|
||||
$this->assertEquals('ParseError', $flattened->getClass(), 'The class is set to the class of the original exception');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -289,7 +289,7 @@ class FlattenExceptionTest extends TestCase
|
||||
$this->assertSame(['resource', 'stream'], $array[$i++]);
|
||||
|
||||
$args = $array[$i++];
|
||||
$this->assertSame($args[0], 'object');
|
||||
$this->assertSame('object', $args[0]);
|
||||
$this->assertTrue('Closure' === $args[1] || is_subclass_of($args[1], '\Closure'), 'Expect object class name to be Closure or a subclass of Closure.');
|
||||
|
||||
$this->assertSame(['array', [['integer', 1], ['integer', 2]]], $array[$i++]);
|
||||
@ -304,7 +304,7 @@ class FlattenExceptionTest extends TestCase
|
||||
$this->assertSame(['float', INF], $array[$i++]);
|
||||
|
||||
// assertEquals() does not like NAN values.
|
||||
$this->assertEquals($array[$i][0], 'float');
|
||||
$this->assertEquals('float', $array[$i][0]);
|
||||
$this->assertNan($array[$i][1]);
|
||||
}
|
||||
|
||||
@ -344,7 +344,7 @@ class FlattenExceptionTest extends TestCase
|
||||
$flattened = FlattenException::createFromThrowable($exception);
|
||||
$trace = $flattened->getTrace();
|
||||
|
||||
$this->assertSame($trace[1]['args'][0], ['array', ['array', '*SKIPPED over 10000 entries*']]);
|
||||
$this->assertSame(['array', ['array', '*SKIPPED over 10000 entries*']], $trace[1]['args'][0]);
|
||||
|
||||
$serializeTrace = serialize($trace);
|
||||
|
||||
|
@ -620,20 +620,20 @@ class ResponseTest extends ResponseTestCase
|
||||
|
||||
$options = ['etag' => '"whatever"'];
|
||||
$response->setCache($options);
|
||||
$this->assertEquals($response->getEtag(), '"whatever"');
|
||||
$this->assertEquals('"whatever"', $response->getEtag());
|
||||
|
||||
$now = $this->createDateTimeNow();
|
||||
$options = ['last_modified' => $now];
|
||||
$response->setCache($options);
|
||||
$this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp());
|
||||
$this->assertEquals($now->getTimestamp(), $response->getLastModified()->getTimestamp());
|
||||
|
||||
$options = ['max_age' => 100];
|
||||
$response->setCache($options);
|
||||
$this->assertEquals($response->getMaxAge(), 100);
|
||||
$this->assertEquals(100, $response->getMaxAge());
|
||||
|
||||
$options = ['s_maxage' => 200];
|
||||
$response->setCache($options);
|
||||
$this->assertEquals($response->getMaxAge(), 200);
|
||||
$this->assertEquals(200, $response->getMaxAge());
|
||||
|
||||
$this->assertTrue($response->headers->hasCacheControlDirective('public'));
|
||||
$this->assertFalse($response->headers->hasCacheControlDirective('private'));
|
||||
|
@ -86,7 +86,7 @@ class MongoDbSessionHandlerTest extends TestCase
|
||||
->method('findOne')
|
||||
->willReturnCallback(function ($criteria) use ($testTimeout) {
|
||||
$this->assertArrayHasKey($this->options['id_field'], $criteria);
|
||||
$this->assertEquals($criteria[$this->options['id_field']], 'foo');
|
||||
$this->assertEquals('foo', $criteria[$this->options['id_field']]);
|
||||
|
||||
$this->assertArrayHasKey($this->options['expiry_field'], $criteria);
|
||||
$this->assertArrayHasKey('$gte', $criteria[$this->options['expiry_field']]);
|
||||
|
@ -83,10 +83,10 @@ class PhpBridgeSessionStorageTest extends TestCase
|
||||
$_SESSION['drak'] = 'loves symfony';
|
||||
$storage->getBag('attributes')->set('symfony', 'greatness');
|
||||
$key = $storage->getBag('attributes')->getStorageKey();
|
||||
$this->assertEquals($_SESSION[$key], ['symfony' => 'greatness']);
|
||||
$this->assertEquals($_SESSION['drak'], 'loves symfony');
|
||||
$this->assertEquals(['symfony' => 'greatness'], $_SESSION[$key]);
|
||||
$this->assertEquals('loves symfony', $_SESSION['drak']);
|
||||
$storage->clear();
|
||||
$this->assertEquals($_SESSION[$key], []);
|
||||
$this->assertEquals($_SESSION['drak'], 'loves symfony');
|
||||
$this->assertEquals([], $_SESSION[$key]);
|
||||
$this->assertEquals('loves symfony', $_SESSION['drak']);
|
||||
}
|
||||
}
|
||||
|
@ -228,9 +228,9 @@ class FileProfilerStorageTest extends TestCase
|
||||
|
||||
$records = $this->storage->find('', '', 3, 'GET', $start, time() + 3 * 60);
|
||||
$this->assertCount(3, $records, '->find() returns all previously added records');
|
||||
$this->assertEquals($records[0]['token'], 'time_2', '->find() returns records ordered by time in descendant order');
|
||||
$this->assertEquals($records[1]['token'], 'time_1', '->find() returns records ordered by time in descendant order');
|
||||
$this->assertEquals($records[2]['token'], 'time_0', '->find() returns records ordered by time in descendant order');
|
||||
$this->assertEquals('time_2', $records[0]['token'], '->find() returns records ordered by time in descendant order');
|
||||
$this->assertEquals('time_1', $records[1]['token'], '->find() returns records ordered by time in descendant order');
|
||||
$this->assertEquals('time_0', $records[2]['token'], '->find() returns records ordered by time in descendant order');
|
||||
|
||||
$records = $this->storage->find('', '', 3, 'GET', $start, time() + 2 * 60);
|
||||
$this->assertCount(2, $records, '->find() should return only first two of the previously added records');
|
||||
|
@ -25,9 +25,9 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
*/
|
||||
class Connection extends AbstractConnection
|
||||
{
|
||||
private const LDAP_INVALID_CREDENTIALS = '0x31';
|
||||
private const LDAP_TIMEOUT = '0x55';
|
||||
private const LDAP_ALREADY_EXISTS = '0x44';
|
||||
private const LDAP_INVALID_CREDENTIALS = 0x31;
|
||||
private const LDAP_TIMEOUT = 0x55;
|
||||
private const LDAP_ALREADY_EXISTS = 0x44;
|
||||
|
||||
/** @var bool */
|
||||
private $bound = false;
|
||||
|
@ -94,12 +94,12 @@ class AdapterTest extends LdapTestCase
|
||||
$ldap->getConnection()->bind('cn=admin,dc=symfony,dc=com', 'symfony');
|
||||
|
||||
$query = $ldap->createQuery('cn=Fabien Potencier,dc=symfony,dc=com', '(objectclass=*)', [
|
||||
'scope' => Query::SCOPE_BASE,
|
||||
'scope' => Query::SCOPE_BASE,
|
||||
]);
|
||||
$result = $query->execute();
|
||||
|
||||
$entry = $result[0];
|
||||
$this->assertEquals($result->count(), 1);
|
||||
$this->assertEquals(1, $result->count());
|
||||
$this->assertEquals(['Fabien Potencier'], $entry->getAttribute('cn'));
|
||||
}
|
||||
|
||||
@ -116,8 +116,8 @@ class AdapterTest extends LdapTestCase
|
||||
$subtree_count = $ldap->createQuery('ou=Components,dc=symfony,dc=com', '(objectclass=*)')->execute()->count();
|
||||
|
||||
$this->assertNotEquals($one_level_result->count(), $subtree_count);
|
||||
$this->assertEquals($one_level_result->count(), 1);
|
||||
$this->assertEquals($one_level_result[0]->getAttribute('ou'), ['Ldap']);
|
||||
$this->assertEquals(1, $one_level_result->count());
|
||||
$this->assertEquals(['Ldap'], $one_level_result[0]->getAttribute('ou'));
|
||||
}
|
||||
|
||||
public function testLdapPagination()
|
||||
|
@ -186,7 +186,7 @@ class LdapManagerTest extends LdapTestCase
|
||||
|
||||
$result = $this->executeSearchQuery(1);
|
||||
$renamedEntry = $result[0];
|
||||
$this->assertEquals($renamedEntry->getAttribute('cn')[0], 'Kevin');
|
||||
$this->assertEquals('Kevin', $renamedEntry->getAttribute('cn')[0]);
|
||||
|
||||
$oldRdn = $entry->getAttribute('cn')[0];
|
||||
$entryManager->rename($renamedEntry, 'cn='.$oldRdn);
|
||||
|
@ -59,8 +59,9 @@ class MandrillHttpTransportTest extends TestCase
|
||||
$body = json_decode($options['body'], true);
|
||||
$message = $body['raw_message'];
|
||||
$this->assertSame('KEY', $body['key']);
|
||||
$this->assertSame('Fabien', $body['from_name']);
|
||||
$this->assertSame('fabpot@symfony.com', $body['from_email']);
|
||||
$this->assertSame('saif.gmati@symfony.com', $body['to'][0]);
|
||||
$this->assertSame('Fabien <fabpot@symfony.com>', $body['from_email']);
|
||||
|
||||
$this->assertStringContainsString('Subject: Hello!', $message);
|
||||
$this->assertStringContainsString('To: Saif Eddin <saif.gmati@symfony.com>', $message);
|
||||
|
@ -51,7 +51,8 @@ class MandrillHttpTransport extends AbstractHttpTransport
|
||||
'to' => array_map(function (Address $recipient): string {
|
||||
return $recipient->getAddress();
|
||||
}, $envelope->getRecipients()),
|
||||
'from_email' => $envelope->getSender()->toString(),
|
||||
'from_email' => $envelope->getSender()->getAddress(),
|
||||
'from_name' => $envelope->getSender()->getName(),
|
||||
'raw_message' => $message->toString(),
|
||||
],
|
||||
]);
|
||||
|
@ -166,4 +166,30 @@ class SendgridApiTransportTest extends TestCase
|
||||
$this->assertArrayHasKey('foo', $payload['headers']);
|
||||
$this->assertEquals('bar', $payload['headers']['foo']);
|
||||
}
|
||||
|
||||
public function testReplyTo()
|
||||
{
|
||||
$from = 'from@example.com';
|
||||
$to = 'to@example.com';
|
||||
$replyTo = 'replyto@example.com';
|
||||
$email = new Email();
|
||||
$email->from($from)
|
||||
->to($to)
|
||||
->replyTo($replyTo)
|
||||
->text('content');
|
||||
$envelope = new Envelope(new Address($from), [new Address($to)]);
|
||||
|
||||
$transport = new SendgridApiTransport('ACCESS_KEY');
|
||||
$method = new \ReflectionMethod(SendgridApiTransport::class, 'getPayload');
|
||||
$method->setAccessible(true);
|
||||
$payload = $method->invoke($transport, $email, $envelope);
|
||||
|
||||
$this->assertArrayHasKey('from', $payload);
|
||||
$this->assertArrayHasKey('email', $payload['from']);
|
||||
$this->assertSame($from, $payload['from']['email']);
|
||||
|
||||
$this->assertArrayHasKey('reply_to', $payload);
|
||||
$this->assertArrayHasKey('email', $payload['reply_to']);
|
||||
$this->assertSame($replyTo, $payload['reply_to']['email']);
|
||||
}
|
||||
}
|
||||
|
@ -93,11 +93,16 @@ class SendgridApiTransport extends AbstractApiTransport
|
||||
if ($emails = array_map($addressStringifier, $email->getBcc())) {
|
||||
$personalization['bcc'] = $emails;
|
||||
}
|
||||
if ($emails = array_map($addressStringifier, $email->getReplyTo())) {
|
||||
// Email class supports an array of reply-to addresses,
|
||||
// but SendGrid only supports a single address
|
||||
$payload['reply_to'] = $emails[0];
|
||||
}
|
||||
|
||||
$payload['personalizations'][] = $personalization;
|
||||
|
||||
// these headers can't be overwritten according to Sendgrid docs
|
||||
// see https://developers.pepipost.com/migration-api/new-subpage/email-send
|
||||
// see https://sendgrid.api-docs.io/v3.0/mail-send/mail-send-errors#-Headers-Errors
|
||||
$headersToBypass = ['x-sg-id', 'x-sg-eid', 'received', 'dkim-signature', 'content-transfer-encoding', 'from', 'to', 'cc', 'bcc', 'subject', 'content-type', 'reply-to'];
|
||||
foreach ($email->getHeaders()->all() as $name => $header) {
|
||||
if (\in_array($name, $headersToBypass, true)) {
|
||||
|
@ -158,7 +158,8 @@ final class ParameterizedHeader extends UnstructuredHeader
|
||||
*/
|
||||
private function getEndOfParameterValue(string $value, bool $encoded = false, bool $firstLine = false): string
|
||||
{
|
||||
if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) {
|
||||
$forceHttpQuoting = 'content-disposition' === strtolower($this->getName()) && 'form-data' === $this->getValue();
|
||||
if ($forceHttpQuoting || !preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) {
|
||||
$value = '"'.$value.'"';
|
||||
}
|
||||
$prepend = '=';
|
||||
|
@ -131,7 +131,7 @@ class TextPart extends AbstractPart
|
||||
if ($this->charset) {
|
||||
$headers->setHeaderParameter('Content-Type', 'charset', $this->charset);
|
||||
}
|
||||
if ($this->name) {
|
||||
if ($this->name && 'form-data' !== $this->disposition) {
|
||||
$headers->setHeaderParameter('Content-Type', 'name', $this->name);
|
||||
}
|
||||
$headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding);
|
||||
|
@ -41,9 +41,9 @@ class PhpExecutableFinderTest extends TestCase
|
||||
$f = new PhpExecutableFinder();
|
||||
|
||||
if ('phpdbg' === \PHP_SAPI) {
|
||||
$this->assertEquals($f->findArguments(), ['-qrr'], '::findArguments() returns phpdbg arguments');
|
||||
$this->assertEquals(['-qrr'], $f->findArguments(), '::findArguments() returns phpdbg arguments');
|
||||
} else {
|
||||
$this->assertEquals($f->findArguments(), [], '::findArguments() returns no arguments');
|
||||
$this->assertEquals([], $f->findArguments(), '::findArguments() returns no arguments');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,8 +223,9 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
|
||||
throw new RuntimeException(sprintf('The type "%s" has no mapped class for the abstract object "%s".', $type, $class));
|
||||
}
|
||||
|
||||
$class = $mappedClass;
|
||||
$reflectionClass = new \ReflectionClass($class);
|
||||
if ($mappedClass !== $class) {
|
||||
return $this->instantiateObject($data, $mappedClass, $context, new \ReflectionClass($mappedClass), $allowedAttributes, $format);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format);
|
||||
|
@ -19,6 +19,7 @@ use Symfony\Component\Serializer\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorMapping;
|
||||
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorResolverInterface;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadata;
|
||||
use Symfony\Component\Serializer\Mapping\ClassMetadataInterface;
|
||||
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
|
||||
@ -235,6 +236,43 @@ class AbstractObjectNormalizerTest extends TestCase
|
||||
$this->assertInstanceOf(DummySecondChildQuux::class, $normalizedData->quux);
|
||||
}
|
||||
|
||||
public function testDenormalizeWithNestedDiscriminatorMap()
|
||||
{
|
||||
$classDiscriminatorResolver = new class() implements ClassDiscriminatorResolverInterface {
|
||||
public function getMappingForClass(string $class): ?ClassDiscriminatorMapping
|
||||
{
|
||||
switch ($class) {
|
||||
case AbstractDummy::class:
|
||||
return new ClassDiscriminatorMapping('type', [
|
||||
'foo' => AbstractDummyFirstChild::class,
|
||||
]);
|
||||
case AbstractDummyFirstChild::class:
|
||||
return new ClassDiscriminatorMapping('nested_type', [
|
||||
'bar' => AbstractDummySecondChild::class,
|
||||
]);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getMappingForMappedObject($object): ?ClassDiscriminatorMapping
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTypeForMappedObject($object): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
$normalizer = new AbstractObjectNormalizerDummy(null, null, null, $classDiscriminatorResolver);
|
||||
|
||||
$denormalizedData = $normalizer->denormalize(['type' => 'foo', 'nested_type' => 'bar'], AbstractDummy::class);
|
||||
|
||||
$this->assertInstanceOf(AbstractDummySecondChild::class, $denormalizedData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that additional attributes throw an exception if no metadata factory is specified.
|
||||
*/
|
||||
|
@ -180,9 +180,9 @@ class PhpEngineTest extends TestCase
|
||||
|
||||
$this->loader->setTemplate('global.php', '<?php echo $global; ?>');
|
||||
|
||||
$this->assertEquals($engine->render('global.php'), 'global variable');
|
||||
$this->assertEquals('global variable', $engine->render('global.php'));
|
||||
|
||||
$this->assertEquals($engine->render('global.php', ['global' => 'overwritten']), 'overwritten');
|
||||
$this->assertEquals('overwritten', $engine->render('global.php', ['global' => 'overwritten']));
|
||||
}
|
||||
|
||||
public function testGetLoader()
|
||||
|
Reference in New Issue
Block a user