Merge branch '3.2'
* 3.2: [Bridge\Doctrine] Fix change breaking doctrine-bundle test suite [WebProfilerBundle] Include badge status in translation tabs [FrameworkBundle] Cache pool clear command requires at least 1 pool [HttpFoundation][bugfix] should always be initialized MockArraySessionStorage: updated phpdoc for $bags so that IDE autocompletion would work normalize paths before making them relative removed test that does not test anything fixed tests #21809 [SecurityBundle] bugfix: if security provider's name contains upper cases then container didn't compile [WebProfilerBundle] Fix for CSS attribute at Profiler Translation Page Set Date header in Response constructor already [Validator] fix URL validator to detect non supported chars according to RFC 3986 [Security] Fixed roles serialization on token from user object
This commit is contained in:
commit
811a6bf5eb
@ -122,7 +122,7 @@ class RegisterEventListenersAndSubscribersPass implements CompilerPassInterface
|
||||
}
|
||||
$instance['event'] = array($instance['event']);
|
||||
|
||||
if (isset($instance['lazy']) && $instance['lazy']) {
|
||||
if ($lazy = !empty($instance['lazy'])) {
|
||||
$this->container->getDefinition($id)->setPublic(true);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ final class CachePoolClearCommand extends ContainerAwareCommand
|
||||
$this
|
||||
->setName('cache:pool:clear')
|
||||
->setDefinition(array(
|
||||
new InputArgument('pools', InputArgument::IS_ARRAY, 'A list of cache pools or cache pool clearers'),
|
||||
new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'),
|
||||
))
|
||||
->setDescription('Clears cache pools')
|
||||
->setHelp(<<<'EOF'
|
||||
|
@ -570,7 +570,7 @@ class SecurityExtension extends Extension
|
||||
// Parses a <provider> tag and returns the id for the related user provider service
|
||||
private function createUserDaoProvider($name, $provider, ContainerBuilder $container)
|
||||
{
|
||||
$name = $this->getUserProviderId(strtolower($name));
|
||||
$name = $this->getUserProviderId($name);
|
||||
|
||||
// Doctrine Entity and In-memory DAO provider are managed by factories
|
||||
foreach ($this->userProviderFactories as $factory) {
|
||||
@ -594,7 +594,7 @@ class SecurityExtension extends Extension
|
||||
if (isset($provider['chain'])) {
|
||||
$providers = array();
|
||||
foreach ($provider['chain']['providers'] as $providerName) {
|
||||
$providers[] = new Reference($this->getUserProviderId(strtolower($providerName)));
|
||||
$providers[] = new Reference($this->getUserProviderId($providerName));
|
||||
}
|
||||
|
||||
$container
|
||||
@ -609,7 +609,7 @@ class SecurityExtension extends Extension
|
||||
|
||||
private function getUserProviderId($name)
|
||||
{
|
||||
return 'security.user.provider.concrete.'.$name;
|
||||
return 'security.user.provider.concrete.'.strtolower($name);
|
||||
}
|
||||
|
||||
private function createExceptionListener($container, $config, $id, $defaultEntryPoint, $stateless)
|
||||
|
@ -8,7 +8,7 @@
|
||||
{{ include('@WebProfiler/Icon/translation.svg') }}
|
||||
{% set status_color = collector.countMissings ? 'red' : collector.countFallbacks ? 'yellow' %}
|
||||
{% set error_count = collector.countMissings + collector.countFallbacks %}
|
||||
<span class="sf-toolbar-value">{{ error_count ?: collector.countdefines }}</span>
|
||||
<span class="sf-toolbar-value">{{ error_count ?: collector.countDefines }}</span>
|
||||
{% endset %}
|
||||
|
||||
{% set text %}
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
<div class="sf-toolbar-info-piece">
|
||||
<b>Defined messages</b>
|
||||
<span class="sf-toolbar-status">{{ collector.countdefines }}</span>
|
||||
<span class="sf-toolbar-status">{{ collector.countDefines }}</span>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
|
||||
<div class="metrics">
|
||||
<div class="metric">
|
||||
<span class="value">{{ collector.countdefines }}</span>
|
||||
<span class="value">{{ collector.countDefines }}</span>
|
||||
<span class="label">Defined messages</span>
|
||||
</div>
|
||||
|
||||
@ -96,7 +96,7 @@
|
||||
|
||||
<div class="sf-tabs">
|
||||
<div class="tab">
|
||||
<h3 class="tab-title">Defined <span class="badge">{{ messages_defined|length }}</span></h3>
|
||||
<h3 class="tab-title">Defined <span class="badge">{{ collector.countDefines }}</span></h3>
|
||||
|
||||
<div class="tab-content">
|
||||
<p class="help">
|
||||
@ -114,7 +114,7 @@
|
||||
</div>
|
||||
|
||||
<div class="tab">
|
||||
<h3 class="tab-title">Fallback <span class="badge">{{ messages_fallback|length }}</span></h3>
|
||||
<h3 class="tab-title">Fallback <span class="badge {{ collector.countFallbacks ? 'status-warning' }}">{{ collector.countFallbacks }}</span></h3>
|
||||
|
||||
<div class="tab-content">
|
||||
<p class="help">
|
||||
@ -133,7 +133,7 @@
|
||||
</div>
|
||||
|
||||
<div class="tab">
|
||||
<h3 class="tab-title">Missing <span class="badge">{{ messages_missing|length }}</span></h3>
|
||||
<h3 class="tab-title">Missing <span class="badge {{ collector.countMissings ? 'status-error' }}">{{ collector.countMissings }}</span></h3>
|
||||
|
||||
<div class="tab-content">
|
||||
<p class="help">
|
||||
@ -169,10 +169,10 @@
|
||||
{% for message in messages %}
|
||||
<tr>
|
||||
<td class="font-normal text-small">{{ message.locale }}</td>
|
||||
<td class="font-normal text-small text-bold">{{ message.domain }}</td>
|
||||
<td class="font-normal text-small text-bold nowrap">{{ message.domain }}</td>
|
||||
<td class="font-normal text-small">{{ message.count }}</td>
|
||||
<td>
|
||||
{{ message.id }}
|
||||
<span class="nowrap">{{ message.id }}</span>
|
||||
|
||||
{% if message.transChoiceNumber is not null %}
|
||||
<small class="newline">(pluralization is used)</small>
|
||||
@ -188,7 +188,7 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ message.translation }}</td>
|
||||
<td class="prewrap">{{ message.translation }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
@ -204,6 +204,9 @@ table tbody ul {
|
||||
.nowrap {
|
||||
white-space: pre;
|
||||
}
|
||||
.prewrap {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
.newline {
|
||||
display: block;
|
||||
}
|
||||
|
@ -446,6 +446,31 @@ class Filesystem
|
||||
$startPathArr = explode('/', trim($startPath, '/'));
|
||||
$endPathArr = explode('/', trim($endPath, '/'));
|
||||
|
||||
if ('/' !== $startPath[0]) {
|
||||
array_shift($startPathArr);
|
||||
}
|
||||
|
||||
if ('/' !== $endPath[0]) {
|
||||
array_shift($endPathArr);
|
||||
}
|
||||
|
||||
$normalizePathArray = function ($pathSegments) {
|
||||
$result = array();
|
||||
|
||||
foreach ($pathSegments as $segment) {
|
||||
if ('..' === $segment) {
|
||||
array_pop($result);
|
||||
} else {
|
||||
$result[] = $segment;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
};
|
||||
|
||||
$startPathArr = $normalizePathArray($startPathArr);
|
||||
$endPathArr = $normalizePathArray($endPathArr);
|
||||
|
||||
// Find for which directory the common path stops
|
||||
$index = 0;
|
||||
while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
|
||||
|
@ -1117,6 +1117,16 @@ class FilesystemTest extends FilesystemTestCase
|
||||
array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'),
|
||||
array('/aab/bb', '/aa', '../aab/bb/'),
|
||||
array('/aab', '/aa', '../aab/'),
|
||||
array('/aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
|
||||
array('/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
|
||||
array('/aa/bb/../../cc', '/aa/../dd/..', 'cc/'),
|
||||
array('/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
|
||||
array('/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
|
||||
array('C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
|
||||
array('c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'),
|
||||
array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'),
|
||||
array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
|
||||
array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'),
|
||||
);
|
||||
|
||||
if ('\\' === DIRECTORY_SEPARATOR) {
|
||||
|
@ -201,6 +201,28 @@ class Response
|
||||
$this->setContent($content);
|
||||
$this->setStatusCode($status);
|
||||
$this->setProtocolVersion('1.0');
|
||||
|
||||
// Deprecations
|
||||
$class = get_class($this);
|
||||
if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) {
|
||||
$class = get_parent_class($class);
|
||||
}
|
||||
if (isset(self::$deprecationsTriggered[$class])) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$deprecationsTriggered[$class] = true;
|
||||
foreach (self::$deprecatedMethods as $method) {
|
||||
$r = new \ReflectionMethod($class, $method);
|
||||
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
|
||||
@trigger_error(sprintf('Extending %s::%s() in %s is deprecated since version 3.2 and won\'t be supported anymore in 4.0 as it will be final.', __CLASS__, $method, $class), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
|
||||
/* RFC2616 - 14.18 says all Responses need to have a Date */
|
||||
if (!$this->headers->has('Date')) {
|
||||
$this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -329,6 +351,7 @@ class Response
|
||||
return $this;
|
||||
}
|
||||
|
||||
/* RFC2616 - 14.18 says all Responses need to have a Date */
|
||||
if (!$this->headers->has('Date')) {
|
||||
$this->setDate(\DateTime::createFromFormat('U', time()));
|
||||
}
|
||||
@ -642,6 +665,11 @@ class Response
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
/*
|
||||
RFC2616 - 14.18 says all Responses need to have a Date.
|
||||
Make sure we provide one even if it the header
|
||||
has been removed in the meantime.
|
||||
*/
|
||||
if (!$this->headers->has('Date')) {
|
||||
$this->setDate(\DateTime::createFromFormat('U', time()));
|
||||
}
|
||||
|
@ -58,9 +58,9 @@ class MockArraySessionStorage implements SessionStorageInterface
|
||||
protected $metadataBag;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @var array|SessionBagInterface[]
|
||||
*/
|
||||
protected $bags;
|
||||
protected $bags = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -276,8 +276,10 @@ class ResponseTest extends ResponseTestCase
|
||||
$this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the date when the header has been modified');
|
||||
|
||||
$response = new Response('', 200);
|
||||
$now = $this->createDateTimeNow();
|
||||
$response->headers->remove('Date');
|
||||
$this->assertInstanceOf('\DateTime', $response->getDate());
|
||||
$date = $response->getDate();
|
||||
$this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the current Date when the header has previously been removed');
|
||||
}
|
||||
|
||||
public function testGetMaxAge()
|
||||
|
@ -97,6 +97,30 @@ class MockArraySessionStorageTest extends TestCase
|
||||
$this->assertNotEquals('', $this->storage->getId());
|
||||
}
|
||||
|
||||
public function testClearClearsBags()
|
||||
{
|
||||
$this->storage->clear();
|
||||
|
||||
$this->assertSame(array(), $this->storage->getBag('attributes')->all());
|
||||
$this->assertSame(array(), $this->storage->getBag('flashes')->peekAll());
|
||||
}
|
||||
|
||||
public function testClearStartsSession()
|
||||
{
|
||||
$this->storage->clear();
|
||||
|
||||
$this->assertTrue($this->storage->isStarted());
|
||||
}
|
||||
|
||||
public function testClearWithNoBagsStartsSession()
|
||||
{
|
||||
$storage = new MockArraySessionStorage();
|
||||
|
||||
$storage->clear();
|
||||
|
||||
$this->assertTrue($storage->isStarted());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \RuntimeException
|
||||
*/
|
||||
|
@ -150,7 +150,7 @@ abstract class AbstractToken implements TokenInterface
|
||||
array(
|
||||
is_object($this->user) ? clone $this->user : $this->user,
|
||||
$this->authenticated,
|
||||
$this->roles,
|
||||
array_map(function ($role) { return clone $role; }, $this->roles),
|
||||
$this->attributes,
|
||||
)
|
||||
);
|
||||
|
@ -221,7 +221,7 @@ class UserAuthenticationProviderTest extends TestCase
|
||||
$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
|
||||
$this->assertSame($user, $authToken->getUser());
|
||||
$this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false);
|
||||
$this->assertContains($switchUserRole, $authToken->getRoles());
|
||||
$this->assertContains($switchUserRole, $authToken->getRoles(), '', false, false);
|
||||
$this->assertEquals('foo', $authToken->getCredentials());
|
||||
$this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
|
||||
use Symfony\Component\Security\Core\Role\Role;
|
||||
use Symfony\Component\Security\Core\Role\SwitchUserRole;
|
||||
use Symfony\Component\Security\Core\User\User;
|
||||
|
||||
class TestUser
|
||||
{
|
||||
@ -89,7 +90,7 @@ class AbstractTokenTest extends TestCase
|
||||
|
||||
public function testSerialize()
|
||||
{
|
||||
$token = $this->getToken(array('ROLE_FOO'));
|
||||
$token = $this->getToken(array('ROLE_FOO', new Role('ROLE_BAR')));
|
||||
$token->setAttributes(array('foo' => 'bar'));
|
||||
|
||||
$uToken = unserialize(serialize($token));
|
||||
@ -98,6 +99,19 @@ class AbstractTokenTest extends TestCase
|
||||
$this->assertEquals($token->getAttributes(), $uToken->getAttributes());
|
||||
}
|
||||
|
||||
public function testSerializeWithRoleObjects()
|
||||
{
|
||||
$user = new User('name', 'password', array(new Role('ROLE_FOO'), new Role('ROLE_BAR')));
|
||||
$token = new ConcreteToken($user, $user->getRoles());
|
||||
|
||||
$serialized = serialize($token);
|
||||
$unserialized = unserialize($serialized);
|
||||
|
||||
$roles = $unserialized->getRoles();
|
||||
|
||||
$this->assertEquals($roles, $user->getRoles());
|
||||
}
|
||||
|
||||
public function testSerializeParent()
|
||||
{
|
||||
$user = new TestUser('fabien');
|
||||
|
@ -33,7 +33,9 @@ class UrlValidator extends ConstraintValidator
|
||||
\] # an IPv6 address
|
||||
)
|
||||
(:[0-9]+)? # a port (optional)
|
||||
(/?|/\S+|\?\S*|\#\S*) # a /, nothing, a / with something, a query or a fragment
|
||||
(?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path
|
||||
(?:\? (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional)
|
||||
(?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional)
|
||||
$~ixu';
|
||||
|
||||
/**
|
||||
|
@ -123,6 +123,7 @@ class UrlValidatorTest extends ConstraintValidatorTestCase
|
||||
array('http://symfony.com#'),
|
||||
array('http://symfony.com#fragment'),
|
||||
array('http://symfony.com/#fragment'),
|
||||
array('http://symfony.com/#one_more%20test'),
|
||||
);
|
||||
}
|
||||
|
||||
@ -163,6 +164,9 @@ class UrlValidatorTest extends ConstraintValidatorTestCase
|
||||
array('http://:password@@symfony.com'),
|
||||
array('http://username:passwordsymfony.com'),
|
||||
array('http://usern@me:password@symfony.com'),
|
||||
array('http://example.com/exploit.html?<script>alert(1);</script>'),
|
||||
array('http://example.com/exploit.html?hel lo'),
|
||||
array('http://example.com/exploit.html?not_a%hex'),
|
||||
);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user