10000 Merge branch '3.2' · symfony/symfony@811a6bf · GitHub
[go: up one dir, main page]

Skip to content

Commit 811a6bf

Browse files
committed
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
2 parents 6cc9dc7 + dc66960 commit 811a6bf

File tree

16 files changed

+133
-21
lines changed

16 files changed

+133
-21
lines changed

src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ private function groupByConnection(array $services, $isListener = false)
122122
}
123123
$instance['event'] = array($instance['event']);
124124

125-
if (isset($instance['lazy']) && $instance['lazy']) {
125+
if ($lazy = !empty($instance['lazy'])) {
126126
$this->container->getDefinition($id)->setPublic(true);
127127
}
128128
}

src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ protected function configure()
3333
$this
3434
->setName('cache:pool:clear')
3535
->setDefinition(array(
36-
new InputArgument('pools', InputArgument::IS_ARRAY, 'A list of cache pools or cache pool clearers'),
36+
new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'),
3737
))
3838
->setDescription('Clears cache pools')
3939
->setHelp(<<<'EOF'

src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ private function createUserProviders($config, ContainerBuilder $container)
570570
// Parses a <provider> tag and returns the id for the related user provider service
571571
private function createUserDaoProvider($name, $provider, ContainerBuilder $container)
572572
{
573-
$name = $this->getUserProviderId(strtolower($name));
573+
$name = $this->getUserProviderId($name);
574574

575575
// Doctrine Entity and In-memory DAO provider are managed by factories
576576
foreach ($this->userProviderFactories as $factory) {
@@ -594,7 +594,7 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta
594594
if (isset($provider['chain'])) {
595595
$providers = array();
596596
foreach ($provider['chain']['providers'] as $providerName) {
597-
$providers[] = new Reference($this->getUserProviderId(strtolower($providerName)));
597+
$providers[] = new Reference($this->getUserProviderId($providerName));
598598
}
599599

600600
$container
@@ -609,7 +609,7 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta
609609

610610
private function getUserProviderId($name)
611611
{
612-
return 'security.user.provider.concrete.'.$name;
612+
return 'security.user.provider.concrete.'.strtolower($name);
613613
}
614614

615615
private function createExceptionListener($container, $config, $id, $defaultEntryPoint, $stateless)

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
{{ include('@WebProfiler/Icon/translation.svg') }}
99
{% set status_color = collector.countMissings ? 'red' : collector.countFallbacks ? 'yellow' %}
1010
{% set error_count = collector.countMissings + collector.countFallbacks %}
11-
<span class="sf-toolbar-value">{{ error_count ?: collector.countdefines }}</span>
11+
<span class="sf-toolbar-value">{{ error_count ?: collector.countDefines }}</span>
1212
{% endset %}
1313

1414
{% set text %}
@@ -28,7 +28,7 @@
2828

2929
<div class="sf-toolbar-info-piece">
3030
<b>Defined messages</b>
31-
<span class="sf-toolbar-status">{{ collector.countdefines }}</span>
31+
<span class="sf-toolbar-status">{{ collector.countDefines }}</span>
3232
</div>
3333
{% endset %}
3434

@@ -65,7 +65,7 @@
6565

6666
<div class="metrics">
6767
<div class="metric">
68-
<span class="value">{{ collector.countdefines }}</span>
68+
<span class="value">{{ collector.countDefines }}</span>
6969
<span class="label">Defined messages</span>
7070
</div>
7171

@@ -96,7 +96,7 @@
9696

9797
<div class="sf-tabs">
9898
<div class="tab">
99-
<h3 class="tab-title">Defined <span class="badge">{{ messages_defined|length }}</span></h3>
99+
<h3 class="tab-title">Defined <span class="badge">{{ collector.countDefines }}</span></h3>
100100

101101
<div class="tab-content">
102102
<p class="help">
@@ -114,7 +114,7 @@
114114
</div>
115115

116116
<div class="tab">
117-
<h3 class="tab-title">Fallback <span class="badge">{{ messages_fallback|length }}</span></h3>
117+
<h3 class="tab-title">Fallback <span class="badge {{ collector.countFallbacks ? 'status-warning' }}">{{ collector.countFallbacks }}</span></h3>
118118

119119
<div class="tab-content">
120120
<p class="help">
@@ -133,7 +133,7 @@
133133
</div>
134134

135135
<div class="tab">
136-
<h3 class="tab-title">Missing <span class="badge">{{ messages_missing|length }}</span></h3>
136+
<h3 class="tab-title">Missing <span class="badge {{ collector.countMissings ? 'status-error' }}">{{ collector.countMissings }}</span></h3>
137137

138138
<div class="tab-content">
139139
<p class="help">
@@ -169,10 +169,10 @@
169169
{% for message in messages %}
170170
<tr>
171171
<td class="font-normal text-small">{{ message.locale }}</td>
172-
<td class="font-normal text-small text-bold">{{ message.domain }}</td>
172+
<td class="font-normal text-small text-bold nowrap">{{ message.domain }}</td>
173173
<td class="font-normal text-small">{{ message.count }}</td>
174174
<td>
175-
{{ message.id }}
175+
<span class="nowrap">{{ message.id }}</span>
176176

177177
{% if message.transChoiceNumber is not null %}
178178
<small class="newline">(pluralization is used)</small>
@@ -188,7 +188,7 @@
188188
</div>
189189
{% endif %}
190190
</td>
191-
<td>{{ message.translation }}</td>
191+
<td class="prewrap">{{ message.translation }}</td>
192192
</tr>
193193
{% endfor %}
194194
</tbody>

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ table tbody ul {
204204
.nowrap {
205205
white-space: pre;
206206
}
207+
.prewrap {
208+
white-space: pre-wrap;
209+
}
207210
.newline {
208211
display: block;
209212
}

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,31 @@ public function makePathRelative($endPath, $startPath)
446446
$startPathArr = explode('/', trim($startPath, '/'));
447447
$endPathArr = explode('/', trim($endPath, '/'));
448448

449+
if ('/' !== $startPath[0]) {
450+
array_shift($startPathArr);
451+
}
452+
453+
if ('/' !== $endPath[0]) {
454+
array_shift($endPathArr);
455+
}
456+
457+
$normalizePathArray = function ($pathSegments) {
458+
$result = array();
459+
460+
foreach ($pathSegments as $segment) {
461+
if ('..' === $segment) {
462+
array_pop($result);
463+
} else {
464+
$result[] = $segment;
465+
}
466+
}
467+
468+
return $result;
469+
};
470+
471+
$startPathArr = $normalizePathArray($startPathArr);
472+
$endPathArr = $normalizePathArray($endPathArr);
473+
449474
// Find for which directory the common path stops
450475
$index = 0;
451476
while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {

src/Symfony/Component/Filesystem/Tests/FilesystemTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1117,6 +1117,16 @@ public function providePathsForMakePathRelative()
11171117
array('/a/aab/bb/', '/b/aab', '../../a/aab/bb/'),
11181118
array('/aab/bb', '/aa', '../aab/bb/'),
11191119
array('/aab', '/aa', '../aab/'),
1120+
array('/aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1121+
array('/aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1122+
array('/aa/bb/../../cc', '/aa/../dd/..', 'cc/'),
1123+
array('/../aa/bb/cc', '/aa/dd/..', 'bb/cc/'),
1124+
array('/../../aa/../bb/cc', '/aa/dd/..', '../bb/cc/'),
1125+
array('C:/aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1126+
array('c:/aa/../bb/cc', 'c:/aa/dd/..', '../bb/cc/'),
1127+
array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'),
1128+
array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'),
1129+
array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'),
11201130
);
11211131

11221132
if ('\\' === DIRECTORY_SEPARATOR) {

src/Symfony/Component/HttpFoundation/Response.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,28 @@ public function __construct($content = '', $status = 200, $headers = array())
201201
$this->setContent($content);
202202
$this->setStatusCode($status);
203203
$this->setProtocolVersion('1.0');
204+
205+
// Deprecations
206+
$class = get_class($this);
207+
if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) {
208+
$class = get_parent_class($class);
209+
}
210+
if (isset(self::$deprecationsTriggered[$class])) {
211+
return;
212+
}
213+
214+
self::$deprecationsTriggered[$class] = true;
215+
foreach (self::$deprecatedMethods as $method) {
216+
$r = new \ReflectionMethod($class, $method);
217+
if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
218+
@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);
219+
}
220+
}
221+
222+
/* RFC2616 - 14.18 says all Responses need to have a Date */
223+
if (!$this->headers->has('Date')) {
224+
$this->setDate(new \DateTime(null, new \DateTimeZone('UTC')));
225+
}
204226
}
205227

206228
/**
@@ -329,6 +351,7 @@ public function sendHeaders()
329351
return $this;
330352
}
331353

354+
/* RFC2616 - 14.18 says all Responses need to have a Date */
332355
if (!$this->headers->has('Date')) {
333356
$this->setDate(\DateTime::createFromFormat('U', time()));
334357
}
@@ -642,6 +665,11 @@ public function mustRevalidate()
642665
*/
643666
public function getDate()
644667
{
668+
/*
669+
RFC2616 - 14.18 says all Responses need to have a Date.
670+
Make sure we provide one even if it the header
671+
has been removed in the meantime.
672+
*/
645673
if (!$this->headers->has('Date')) {
646674
$this->setDate(\DateTime::createFromFormat('U', time()));
647675
}

src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ class MockArraySessionStorage implements SessionStorageInterface
5858
protected $metadataBag;
5959

6060
/**
61-
* @var array
61+
* @var array|SessionBagInterface[]
6262
*/
63-
protected $bags;
63+
protected $bags = array();
6464

6565
/**
6666
* Constructor.

src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,10 @@ public function testGetDate()
276276
$this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the date when the header has been modified');
277277

278278
$response = new Response('', 200);
279+
$now = $this->createDateTimeNow();
279280
$response->headers->remove('Date');
280-
$this->assertInstanceOf('\DateTime', $response->getDate());
281+
$date = $response->getDate();
282+
$this->assertEquals($now->getTimestamp(), $date->getTimestamp(), '->getDate() returns the current Date when the header has previously been removed');
281283
}
282284

283285
public function testGetMaxAge()

src/Symfony/Component/HttpFoundation/Tests/Session/Storage/MockArraySessionStorageTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,30 @@ public function testGetId()
9797
$this->assertNotEquals('', $this->storage->getId());
9898
}
9999

100+
public function testClearClearsBags()
101+
{
102+
$this->storage->clear();
103+
104+
$this->assertSame(array(), $this->storage->getBag('attributes')->all());
105+
$this->assertSame(array(), $this->storage->getBag('flashes')->peekAll());
106+
}
107+
108+
public function testClearStartsSession()
109+
{
110+
$this->storage->clear();
111+
112+
$this->assertTrue($this->storage->isStarted());
113+
}
114+
115+
public function testClearWithNoBagsStartsSession()
116+
{
117+
$storage = new MockArraySessionStorage();
118+
119+
$storage->clear();
120+
121+
$this->assertTrue($storage->isStarted());
122+
}
123+
100124
/**
101125
* @expectedException \RuntimeException
102126
*/

src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ public function serialize()
150150
array(
151151
is_object($this->user) ? clone $this->user : $this->user,
152152
$this->authenticated,
153-
$this->roles,
153+
array_map(function ($role) { return clone $role; }, $this->roles),
154154
$this->attributes,
155155
)
156156
);

src/Symfony/Component/Security/Core/Tests/Authentication/Provider/UserAuthenticationProviderTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public function testAuthenticateWithPreservingRoleSwitchUserRole()
221221
$this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $authToken);
222222
$this->assertSame($user, $authToken->getUser());
223223
$this->assertContains(new Role('ROLE_FOO'), $authToken->getRoles(), '', false, false);
224-
$this->assertContains($switchUserRole, $authToken->getRoles());
224+
$this->assertContains($switchUserRole, $authToken->getRoles(), '', false, false);
225225
$this->assertEquals('foo', $authToken->getCredentials());
226226
$this->assertEquals(array('foo' => 'bar'), $authToken->getAttributes(), '->authenticate() copies token attributes');
227227
}

src/Symfony/Component/Security/Core/Tests/Authentication/Token/AbstractTokenTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
1616
use Symfony\Component\Security\Core\Role\Role;
1717
use Symfony\Component\Security\Core\Role\SwitchUserRole;
18+
use Symfony\Component\Security\Core\User\User;
1819

1920
class TestUser
2021
{
@@ -89,7 +90,7 @@ public function testEraseCredentials()
8990

9091
public function testSerialize()
9192
{
92-
$token = $this->getToken(array('ROLE_FOO'));
93+
$token = $this->getToken(array('ROLE_FOO', new Role('ROLE_BAR')));
9394
$token->setAttributes(array('foo' => 'bar'));
9495

9596
$uToken = unserialize(serialize($token));
@@ -98,6 +99,19 @@ public function testSerialize()
9899
$this->assertEquals($token->getAttributes(), $uToken->getAttributes());
99100
}
100101

102+
public function testSerializeWithRoleObjects()
103+
{
104+
$user = new User('name', 'password', array(new Role('ROLE_FOO'), new Role('ROLE_BAR')));
105+
$token = new ConcreteToken($user, $user->getRoles());
106+
107+
$serialized = serialize($token);
108+
$unserialized = unserialize($serialized);
109+
110+
$roles = $unserialized->getRoles();
111+
112+
$this->assertEquals($roles, $user->getRoles());
113+
}
114+
101115
public function testSerializeParent()
102116
{
103117
$user = new TestUser('fabien');

src/Symfony/Component/Validator/Constraints/UrlValidator.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ class UrlValidator extends ConstraintValidator
3333
\] # an IPv6 address
3434
)
3535
(:[0-9]+)? # a port (optional)
36-
(/?|/\S+|\?\S*|\#\S*) # a /, nothing, a / with something, a query or a fragment
36+
(?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path
37+
(?:\? (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional)
38+
(?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional)
3739
$~ixu';
3840

3941
/**

src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public function getValidUrls()
123123
array('http://symfony.com#'),
124124
array('http://symfony.com#fragment'),
125125
array('http://symfony.com/#fragment'),
126+
array('http://symfony.com/#one_more%20test'),
126127
);
127128
}
128129

@@ -163,6 +164,9 @@ public function getInvalidUrls()
163164
array('http://:password@@symfony.com'),
164165
array('http://username:passwordsymfony.com'),
165166
array('http://usern@me:password@symfony.com'),
167+
array('http://example.com/exploit.html?<script>alert(1);</script>'),
168+
array('http://example.com/exploit.html?hel lo'),
169+
array('http://example.com/exploit.html?not_a%hex'),
166170
);
167171
}
168172

0 commit comments

Comments
 (0)
0