8000 Merge branch '4.0' · symfony/symfony@bf4b09f · GitHub
[go: up one dir, main page]

Skip to content

Commit bf4b09f

Browse files
Merge branch '4.0'
* 4.0: [HttpFoundation] Add Session::isEmpty(), fix MockFileSessionStorage to behave like the native one [HttpKernel] Add a better error messages when passing a private or non-tagged controller Test the suggestion of already registered services [VarDumper] Dont use empty(), it chokes on eg GMP objects [Dotenv] Changed preg_match flags from null to 0 remove upgrade instructions for kernel.root_dir [HttpKernel] Arrays with scalar values passed to ESI fragment renderer throw deprecation notice [DependencyInjection] Add more information to the message when passing miss matching class. [HttpKernel] add a test for FilterControllerEvents
2 parents 7bab5b2 + 32dfdb3 commit bf4b09f

File tree

20 files changed

+285
-25
lines changed

20 files changed

+285
-25
lines changed

UPGRADE-4.0.md

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -598,12 +598,6 @@ HttpKernel
598598
tags: ['console.command']
599599
```
600600
601-
* Removed the `kernel.root_dir` parameter. Use the `kernel.project_dir` parameter
602-
instead.
603-
604-
* Removed the `Kernel::getRootDir()` method. Use the `Kernel::getProjectDir()`
605-
method instead.
606-
607601
* The `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` methods have been removed.
608602

609603
* Possibility to pass non-scalar values as URI attributes to the ESI and SSI

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AbstractFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ abstract class AbstractFactory implements SecurityFactoryInterface
2929
protected $options = array(
3030
'check_path' => '/login_check',
3131
'use_forward' => false,
32-
'require_previous_session' => true,
32+
'require_previous_session' => false,
3333
);
3434

3535
protected $defaultSuccessHandlerOptions = array(

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ public function __construct()
2828
$this->addOption('password_path', 'password');
2929
$this->defaultFailureHandlerOptions = array();
3030
$this->defaultSuccessHandlerOptions = array();
31-
$this->options['require_previous_session'] = false;
3231
}
3332

3433
/**

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,10 @@ private function createTypeAlternatives(TypedReference $reference)
337337
return ' '.$message;
338338
}
339339

340-
if (isset($this->ambiguousServiceTypes[$type])) {
340+
$servicesAndAliases = $this->container->getServiceIds();
341+
if (!$this->container->has($type) && false !== $key = array_search(strtolower($type), array_map('strtolower', $servicesAndAliases))) {
342+
return sprintf(' Did you mean "%s"?', $servicesAndAliases[$key]);
343+
} elseif (isset($this->ambiguousServiceTypes[$type])) {
341344
$message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
342345
} elseif (isset($this->types[$type])) {
343346
$message = sprintf('the existing "%s" service', $this->types[$type]);

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,24 @@ public function provideNotWireableCalls()
685685
);
686686
}
687687

688+
/**
689+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
690+
* @expectedExceptionMessage Cannot autowire service "foo": argument "$sam" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireableBecauseOfATypo()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\lesTilleuls" but no such service exists. Did you mean "Symfony\Component\DependencyInjection\Tests\Compiler\LesTilleuls"?
691+
*/
692+
public function testSuggestRegisteredServicesWithSimilarCase()
693+
{
694+
$container = new ContainerBuilder();
695+
696+
$container->register(LesTilleuls::class, LesTilleuls::class);
697+
$container->register('foo', NotWireable::class)->setAutowired(true)
698+
->addMethodCall('setNotAutowireableBecauseOfATypo', array())
699+
;
700+
701+
(new ResolveClassPass())->process($container);
702+
(new AutowireRequiredMethodsPass())->process($container);
703+
(new AutowirePass())->process($container);
704+
}
705+
688706
/**
689707
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
690708
* @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead.

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ public function setNotAutowireable(NotARealClass $n)
299299
{
300300
}
301301

302+
public function setNotAutowireableBecauseOfATypo(lesTilleuls $sam)
303+
{
304+
}
305+
302306
public function setBar()
303307
{
304308
}

src/Symfony/Component/Dotenv/Dotenv.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ private function lexVarname()
174174

175175
private function lexValue()
176176
{
177-
if (preg_match('/[ \t]*+(?:#.*)?$/Am', $this->data, $matches, null, $this->cursor)) {
177+
if (preg_match('/[ \t]*+(?:#.*)?$/Am', $this->data, $matches, 0, $this->cursor)) {
178178
$this->moveCursor($matches[0]);
179179
$this->skipEmptyLines();
180180

@@ -296,7 +296,7 @@ private function lexNestedExpression()
296296

297297
private function skipEmptyLines()
298298
{
299-
if (preg_match('/(?:\s*+(?:#[^\n]*+)?+)++/A', $this->data, $match, null, $this->cursor)) {
299+
if (preg_match('/(?:\s*+(?:#[^\n]*+)?+)++/A', $this->data, $match, 0, $this->cursor)) {
300300
$this->moveCursor($match[0]);
301301
}
302302
}

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
2828

2929
private $flashName;
3030
private $attributeName;
31+
private $data = array();
3132

3233
/**
3334
* @param SessionStorageInterface $storage A SessionStorageInterface instance
@@ -108,7 +109,7 @@ public function remove($name)
108109
*/
109110
public function clear()
110111
{
111-
$this->storage->getBag($this->attributeName)->clear();
112+
$this->getAttributeBag()->clear();
112113
}
113114

114115
/**
@@ -139,6 +140,22 @@ public function count()
139140
return count($this->getAttributeBag()->all());
140141
}
141142

143+
/**
144+
* @return bool
145+
*
146+
* @internal
147+
*/
148+
public function isEmpty()
149+
{
150+
foreach ($this->data as &$data) {
151+
if (!empty($data)) {
152+
return false;
153+
}
154+
}
155+
156+
return true;
157+
}
158+
142159
/**
143160
* {@inheritdoc}
144161
*/
@@ -210,15 +227,15 @@ public function getMetadataBag()
210227
*/
211228
public function registerBag(SessionBagInterface $bag)
212229
{
213-
$this->storage->registerBag($bag);
230+
$this->storage->registerBag(new SessionBagProxy($bag, $this->data));
214231
}
215232

216233
/**
217234
* {@inheritdoc}
218235
*/
219236
public function getBag($name)
220237
{
221-
return $this->storage->getBag($name);
238+
return $this->storage->getBag($name)->getBag();
222239
}
223240

224241
/**
@@ -240,6 +257,6 @@ public function getFlashBag()
240257
*/
241258
private function getAttributeBag()
242259
{
243-
return $this->storage->getBag($this->attributeName);
260+
return $this->storage->getBag($this->attributeName)->getBag();
244261
}
245262
}
Lines changed: 79 additions & 0 deletions
10000
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpFoundation\Session;
13+
14+
/**
15+
* @author Nicolas Grekas <p@tchwork.com>
16+
*
17+
* @internal
18+
*/
19+
final class SessionBagProxy implements SessionBagInterface
20+
{
21+
private $bag;
22+
private $data;
23+
24+
public function __construct(SessionBagInterface $bag, array &$data)
25+
{
26+
$this->bag = $bag;
27+
$this->data = &$data;
28+
}
29+
30+
/**
31+
* @return SessionBagInterface
32+
*/
33+
public function getBag()
34+
{
35+
return $this->bag;
36+
}
37+
38+
/**
39+
* @return bool
40+
*/
41+
public function isEmpty()
42+
{
43+
return empty($this->data[$this->bag->getStorageKey()]);
44+
}
45+
46+
/**
47+
* {@inheritdoc}
48+
*/
49+
public function getName()
50+
{
51+
return $this->bag->getName();
52+
}
53+
54+
/**
55+
* {@inheritdoc}
56+
*/
57+
public function initialize(array &$array)
58+
{
59+
$this->data[$this->bag->getStorageKey()] = &$array;
60+
61+
$this->bag->initialize($array);
62+
}
63+
64+
/**
65+
* {@inheritdoc}
66+
*/
67+
public function getStorageKey()
68+
{
69+
return $this->bag->getStorageKey();
70+
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
public function clear()
76+
{
77+
return $this->bag->clear();
78+
}
79+
}

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,26 @@ public function save()
9191
throw new \RuntimeException('Trying to save a session that was not started yet or was already closed');
9292
}
9393

94-
file_put_contents($this->getFilePath(), serialize($this->data));
94+
$data = $this->data;
95+
96+
foreach ($this->bags as $bag) {
97+
if (empty($data[$key = $bag->getStorageKey()])) {
98+
unset($data[$key]);
99+
}
100+
}
101+
if (array($key = $this->metadataBag->getStorageKey()) === array_keys($data)) {
102+
unset($data[$key]);
103+
}
104+
105+
try {
106+
if ($data) {
107+
file_put_contents($this->getFilePath(), serialize($data));
108+
} else {
109+
$this->destroy();
110+
}
111+
} finally {
112+
$this->data = $data;
113+
}
95114

96115
// this is needed for Silex, where the session object is re-used across requests
97116
// in functional tests. In Symfony, the container is rebooted, so we don't have

src/Symfony/Component/HttpFoundation/Tests/Session/SessionTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,22 @@ public function testGetMeta()
221221
{
222222
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\MetadataBag', $this->session->getMetadataBag());
223223
}
224+
225+
public function testIsEmpty()
226+
{
227+
$this->assertTrue($this->session->isEmpty());
228+
229+
$this->session->set('hello', 'world');
230+
$this->assertFalse($this->session->isEmpty());
231+
232+
$this->session->remove('hello');
233+
$this->assertTrue($this->session->isEmpty());
234+
235+
$flash = $this->session->getFlashBag();
236+
$flash->set('hello', 'world');
237+
$this->assertFalse($this->session->isEmpty());
238+
239+
$flash->get('hello');
240+
$this->assertTrue($this->session->isEmpty());
241+
}
224242
}

src/Symfony/Component/HttpKernel/Controller/ContainerControllerResolver.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Psr\Container\ContainerInterface;
1515
use Psr\Log\LoggerInterface;
16+
use Symfony\Component\DependencyInjection\Container;
1617
use Symfony\Component\HttpFoundation\Request;
1718

1819
/**
@@ -86,6 +87,15 @@ protected function instantiateController($class)
8687
return $this->container->get($class);
8788
}
8889

89-
return parent::instantiateController($class);
90+
try {
91+
return parent::instantiateController($class);
92+
} catch (\ArgumentCountError $e) {
93+
}
94+
95+
if ($this->container instanceof Container && in_array($class, $this->container->getRemovedIds(), true)) {
96+
throw new \LogicException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $class), 0, $e);
97+
}
98+
99+
throw $e;
90100
}
91101
}

src/Symfony/Component/HttpKernel/EventListener/AbstractTestSessionListener.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\HttpKernel\EventListener;
1313

1414
use Symfony\Component\HttpFoundation\Cookie;
15+
use Symfony\Component\HttpFoundation\Session\Session;
1516
use Symfony\Component\HttpFoundation\Session\SessionInterface;
1617
use Symfony\Component\HttpKernel\KernelEvents;
1718
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
@@ -60,8 +61,10 @@ public function onKernelResponse(FilterResponseEvent $event)
6061
$session = $event->getRequest()->getSession();
6162
if ($session && $session->isStarted()) {
6263
$session->save();
63-
$params = session_get_cookie_params();
64-
$event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
64+
if (!$session instanceof Session || !\method_exists($session, 'isEmpty') || !$session->isEmpty()) {
65+
$params = session_get_cookie_params();
66+
$event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly']));
67+
}
6568
}
6669
}
6770

src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ private function generateSignedFragmentUri($uri, Request $request): string
9898
private function containsNonScalars(array $values): bool
9999
{
100100
foreach ($values as $value) {
101-
if (is_array($value) && $this->containsNonScalars($value)) {
102-
return true;
101+
if (is_array($value)) {
102+
return $this->containsNonScalars($value);
103103
} elseif (!is_scalar($value) && null !== $value) {
104104
return true;
105105
}

0 commit comments

Comments
 (0)
0