diff --git a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php
index 413b476f29..596fcdd84d 100644
--- a/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php
+++ b/src/Symfony/Bridge/Monolog/Handler/FingersCrossed/NotFoundActivationStrategy.php
@@ -42,7 +42,7 @@ class NotFoundActivationStrategy extends ErrorLevelActivationStrategy
$isActivated
&& isset($record['context']['exception'])
&& $record['context']['exception'] instanceof HttpException
- && $record['context']['exception']->getStatusCode() == 404
+ && 404 == $record['context']['exception']->getStatusCode()
&& ($request = $this->requestStack->getMasterRequest())
) {
return !preg_match($this->blacklist, $request->getPathInfo());
diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php
index 1c84ff32c0..ab1cda6702 100644
--- a/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php
+++ b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php
@@ -11,7 +11,6 @@
namespace Symfony\Bridge\PhpUnit\Legacy;
-use PHPUnit\Framework\Test;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Warning;
diff --git a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_eval_d_deprecation.phpt b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_eval_d_deprecation.phpt
index 8fa436e201..8390d16332 100644
--- a/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_eval_d_deprecation.phpt
+++ b/src/Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak_vendors_on_eval_d_deprecation.phpt
@@ -15,7 +15,7 @@ while (!file_exists($vendor.'/vendor')) {
define('PHPUNIT_COMPOSER_INSTALL', $vendor.'/vendor/autoload.php');
require PHPUNIT_COMPOSER_INSTALL;
require_once __DIR__.'/../../bootstrap.php';
-eval("@trigger_error('who knows where I come from?', E_USER_DEPRECATED);")
+eval("@trigger_error('who knows where I come from?', E_USER_DEPRECATED);");
?>
--EXPECTF--
diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
index 1c3451bbeb..59497dc961 100644
--- a/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
+++ b/src/Symfony/Bridge/Twig/NodeVisitor/Scope.php
@@ -20,7 +20,7 @@ class Scope
private $data = array();
private $left = false;
- public function __construct(Scope $parent = null)
+ public function __construct(self $parent = null)
{
$this->parent = $parent;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
index 31a12dbaba..ee4edf3172 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
@@ -129,16 +129,34 @@ EOF
$this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
}
- $containerDir = $fs->exists($warmupDir.'/'.$containerDir) ? false : $containerDir;
-
- $fs->rename($realCacheDir, $oldCacheDir);
- $fs->rename($warmupDir, $realCacheDir);
-
- if ($containerDir) {
- $fs->rename($oldCacheDir.'/'.$containerDir, $realCacheDir.'/'.$containerDir);
- touch($realCacheDir.'/'.$containerDir.'.legacy');
+ if (!$fs->exists($warmupDir.'/'.$containerDir)) {
+ $fs->rename($realCacheDir.'/'.$containerDir, $warmupDir.'/'.$containerDir);
+ touch($warmupDir.'/'.$containerDir.'.legacy');
}
+ if ('/' === \DIRECTORY_SEPARATOR && $mounts = @file('/proc/mounts')) {
+ foreach ($mounts as $mount) {
+ $mount = array_slice(explode(' ', $mount), 1, -3);
+ if (!\in_array(array_pop($mount), array('vboxfs', 'nfs'))) {
+ continue;
+ }
+ $mount = implode(' ', $mount).'/';
+
+ if (0 === strpos($realCacheDir, $mount)) {
+ $io->note('For better performances, you should move the cache and log directories to a non-shared folder of the VM.');
+ $oldCacheDir = false;
+ break;
+ }
+ }
+ }
+
+ if ($oldCacheDir) {
+ $fs->rename($realCacheDir, $oldCacheDir);
+ } else {
+ $fs->remove($realCacheDir);
+ }
+ $fs->rename($warmupDir, $realCacheDir);
+
if ($output->isVerbose()) {
$io->comment('Removing old cache directory...');
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php
index 9fd2064928..452845cea8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php
@@ -12,7 +12,6 @@
namespace Symfony\Bundle\FrameworkBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
-use Symfony\Component\HttpFoundation\File\File;
class ControllerTest extends ControllerTraitTest
{
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
index 3282966f47..f0d8c0dc5a 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
@@ -197,14 +197,15 @@ class SecurityExtension extends Extension
$configId = 'security.firewall.map.config.'.$name;
- list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId);
+ list($matcher, $listeners, $exceptionListener, $logoutListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId);
$contextId = 'security.firewall.map.context.'.$name;
$context = $container->setDefinition($contextId, new ChildDefinition('security.firewall.context'));
$context
->replaceArgument(0, new IteratorArgument($listeners))
->replaceArgument(1, $exceptionListener)
- ->replaceArgument(2, new Reference($configId))
+ ->replaceArgument(2, $logoutListener)
+ ->replaceArgument(3, new Reference($configId))
;
$contextRefs[$contextId] = new Reference($contextId);
@@ -250,7 +251,7 @@ class SecurityExtension extends Extension
// Security disabled?
if (false === $firewall['security']) {
- return array($matcher, array(), null);
+ return array($matcher, array(), null, null);
}
$config->replaceArgument(4, $firewall['stateless']);
@@ -289,16 +290,15 @@ class SecurityExtension extends Extension
$config->replaceArgument(6, $contextKey);
// Logout listener
+ $logoutListenerId = null;
if (isset($firewall['logout'])) {
- $listenerKeys[] = 'logout';
- $listenerId = 'security.logout_listener.'.$id;
- $listener = $container->setDefinition($listenerId, new ChildDefinition('security.logout_listener'));
- $listener->replaceArgument(3, array(
+ $logoutListenerId = 'security.logout_listener.'.$id;
+ $logoutListener = $container->setDefinition($logoutListenerId, new ChildDefinition('security.logout_listener'));
+ $logoutListener->replaceArgument(3, array(
'csrf_parameter' => $firewall['logout']['csrf_parameter'],
'csrf_token_id' => $firewall['logout']['csrf_token_id'],
'logout_path' => $firewall['logout']['path'],
));
- $listeners[] = new Reference($listenerId);
// add logout success handler
if (isset($firewall['logout']['success_handler'])) {
@@ -308,16 +308,16 @@ class SecurityExtension extends Extension
$logoutSuccessHandler = $container->setDefinition($logoutSuccessHandlerId, new ChildDefinition('security.logout.success_handler'));
$logoutSuccessHandler->replaceArgument(1, $firewall['logout']['target']);
}
- $listener->replaceArgument(2, new Reference($logoutSuccessHandlerId));
+ $logoutListener->replaceArgument(2, new Reference($logoutSuccessHandlerId));
// add CSRF provider
if (isset($firewall['logout']['csrf_token_generator'])) {
- $listener->addArgument(new Reference($firewall['logout']['csrf_token_generator']));
+ $logoutListener->addArgument(new Reference($firewall['logout']['csrf_token_generator']));
}
// add session logout handler
if (true === $firewall['logout']['invalidate_session'] && false === $firewall['stateless']) {
- $listener->addMethodCall('addHandler', array(new Reference('security.logout.handler.session')));
+ $logoutListener->addMethodCall('addHandler', array(new Reference('security.logout.handler.session')));
}
// add cookie logout handler
@@ -326,12 +326,12 @@ class SecurityExtension extends Extension
$cookieHandler = $container->setDefinition($cookieHandlerId, new ChildDefinition('security.logout.handler.cookie_clearing'));
$cookieHandler->addArgument($firewall['logout']['delete_cookies']);
- $listener->addMethodCall('addHandler', array(new Reference($cookieHandlerId)));
+ $logoutListener->addMethodCall('addHandler', array(new Reference($cookieHandlerId)));
}
// add custom handlers
foreach ($firewall['logout']['handlers'] as $handlerId) {
- $listener->addMethodCall('addHandler', array(new Reference($handlerId)));
+ $logoutListener->addMethodCall('addHandler', array(new Reference($handlerId)));
}
// register with LogoutUrlGenerator
@@ -391,7 +391,7 @@ class SecurityExtension extends Extension
$config->replaceArgument(10, $listenerKeys);
$config->replaceArgument(11, isset($firewall['switch_user']) ? $firewall['switch_user'] : null);
- return array($matcher, $listeners, $exceptionListener);
+ return array($matcher, $listeners, $exceptionListener, null !== $logoutListenerId ? new Reference($logoutListenerId) : null);
}
private function createContextListener($container, $contextKey)
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
index dfc2bea84e..9cbdd2061e 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
@@ -141,6 +141,7 @@
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php
index 2375e6b0e3..a3b7f15406 100644
--- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php
+++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php
@@ -12,6 +12,7 @@
namespace Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
+use Symfony\Component\Security\Http\Firewall\LogoutListener;
/**
* This is a wrapper around the actual firewall configuration which allows us
@@ -23,13 +24,24 @@ class FirewallContext
{
private $listeners;
private $exceptionListener;
+ private $logoutListener;
private $config;
- public function __construct(iterable $listeners, ExceptionListener $exceptionListener = null, FirewallConfig $config = null)
+ /**
+ * @param LogoutListener|null $logoutListener
+ */
+ public function __construct(iterable $listeners, ExceptionListener $exceptionListener = null, $logoutListener = null, FirewallConfig $config = null)
{
$this->listeners = $listeners;
$this->exceptionListener = $exceptionListener;
- $this->config = $config;
+ if ($logoutListener instanceof FirewallConfig) {
+ $this->config = $logoutListener;
+ } elseif (null === $logoutListener || $logoutListener instanceof LogoutListener) {
+ $this->logoutListener = $logoutListener;
+ $this->config = $config;
+ } else {
+ throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be instance of %s or null, %s given.', __METHOD__, LogoutListener::class, is_object($logoutListener) ? get_class($logoutListener) : gettype($logoutListener)));
+ }
}
public function getConfig()
@@ -46,4 +58,9 @@ class FirewallContext
{
return $this->exceptionListener;
}
+
+ public function getLogoutListener()
+ {
+ return $this->logoutListener;
+ }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php
index 3b98b0e4ca..e11d5dc0f5 100644
--- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php
+++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php
@@ -40,10 +40,10 @@ class FirewallMap implements FirewallMapInterface
$context = $this->getFirewallContext($request);
if (null === $context) {
- return array(array(), null);
+ return array(array(), null, null);
}
- return array($context->getListeners(), $context->getExceptionListener());
+ return array($context->getListeners(), $context->getExceptionListener(), $context->getLogoutListener());
}
/**
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
index 1366a2608c..7e5ecd5d9e 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php
@@ -71,7 +71,7 @@ abstract class CompleteConfigurationTest extends TestCase
$arguments = $contextDef->getArguments();
$listeners[] = array_map('strval', $arguments['index_0']->getValues());
- $configDef = $container->getDefinition((string) $arguments['index_2']);
+ $configDef = $container->getDefinition((string) $arguments['index_3']);
$configs[] = array_values($configDef->getArguments());
}
@@ -99,7 +99,6 @@ abstract class CompleteConfigurationTest extends TestCase
null,
null,
array(
- 'logout',
'switch_user',
'x509',
'remote_user',
@@ -171,7 +170,6 @@ abstract class CompleteConfigurationTest extends TestCase
array(),
array(
'security.channel_listener',
- 'security.logout_listener.secure',
'security.authentication.listener.x509.secure',
'security.authentication.listener.remote_user.secure',
'security.authentication.listener.form.secure',
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php
new file mode 100644
index 0000000000..7eeb7c2117
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LogoutTest.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
+
+class LogoutTest extends WebTestCase
+{
+ public function testSessionLessRememberMeLogout()
+ {
+ $client = $this->createClient(array('test_case' => 'RememberMeLogout', 'root_config' => 'config.yml'));
+
+ $client->request('POST', '/login', array(
+ '_username' => 'johannes',
+ '_password' => 'test',
+ ));
+
+ $cookieJar = $client->getCookieJar();
+ $cookieJar->expire(session_name());
+
+ $this->assertNotNull($cookieJar->get('REMEMBERME'));
+
+ $client->request('GET', '/logout');
+
+ $this->assertNull($cookieJar->get('REMEMBERME'));
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/bundles.php
new file mode 100644
index 0000000000..d90f774abd
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/bundles.php
@@ -0,0 +1,18 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+use Symfony\Bundle\SecurityBundle\SecurityBundle;
+use Symfony\Bundle\FrameworkBundle\FrameworkBundle;
+
+return array(
+ new FrameworkBundle(),
+ new SecurityBundle(),
+);
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/config.yml
new file mode 100644
index 0000000000..60e9cb89a2
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/config.yml
@@ -0,0 +1,25 @@
+imports:
+ - { resource: ./../config/framework.yml }
+
+security:
+ encoders:
+ Symfony\Component\Security\Core\User\User: plaintext
+
+ providers:
+ in_memory:
+ memory:
+ users:
+ johannes: { password: test, roles: [ROLE_USER] }
+
+ firewalls:
+ default:
+ form_login:
+ check_path: login
+ remember_me: true
+ require_previous_session: false
+ remember_me:
+ always_remember_me: true
+ secret: key
+ logout: ~
+ anonymous: ~
+ stateless: true
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/routing.yml
new file mode 100644
index 0000000000..1dddfca2f8
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/RememberMeLogout/routing.yml
@@ -0,0 +1,5 @@
+login:
+ path: /login
+
+logout:
+ path: /logout
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php
index 983e828821..520a129716 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php
@@ -16,6 +16,7 @@ use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
use Symfony\Bundle\SecurityBundle\Security\FirewallContext;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
+use Symfony\Component\Security\Http\Firewall\LogoutListener;
class FirewallContextTest extends TestCase
{
@@ -23,6 +24,7 @@ class FirewallContextTest extends TestCase
{
$config = new FirewallConfig('main', 'user_checker', 'request_matcher');
$exceptionListener = $this->getExceptionListenerMock();
+ $logoutListener = $this->getLogoutListenerMock();
$listeners = array(
$this
->getMockBuilder(ListenerInterface::class)
@@ -30,10 +32,11 @@ class FirewallContextTest extends TestCase
->getMock(),
);
- $context = new FirewallContext($listeners, $exceptionListener, $config);
+ $context = new FirewallContext($listeners, $exceptionListener, $logoutListener, $config);
$this->assertEquals($listeners, $context->getListeners());
$this->assertEquals($exceptionListener, $context->getExceptionListener());
+ $this->assertEquals($logoutListener, $context->getLogoutListener());
$this->assertEquals($config, $context->getConfig());
}
@@ -44,4 +47,12 @@ class FirewallContextTest extends TestCase
->disableOriginalConstructor()
->getMock();
}
+
+ private function getLogoutListenerMock()
+ {
+ return $this
+ ->getMockBuilder(LogoutListener::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php
index 3e6f0a1ac7..42162369cb 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php
@@ -20,6 +20,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
+use Symfony\Component\Security\Http\Firewall\LogoutListener;
class FirewallMapTest extends TestCase
{
@@ -35,7 +36,7 @@ class FirewallMapTest extends TestCase
$firewallMap = new FirewallMap($container, $map);
- $this->assertEquals(array(array(), null), $firewallMap->getListeners($request));
+ $this->assertEquals(array(array(), null, null), $firewallMap->getListeners($request));
$this->assertNull($firewallMap->getFirewallConfig($request));
$this->assertFalse($request->attributes->has(self::ATTRIBUTE_FIREWALL_CONTEXT));
}
@@ -51,7 +52,7 @@ class FirewallMapTest extends TestCase
$firewallMap = new FirewallMap($container, $map);
- $this->assertEquals(array(array(), null), $firewallMap->getListeners($request));
+ $this->assertEquals(array(array(), null, null), $firewallMap->getListeners($request));
$this->assertNull($firewallMap->getFirewallConfig($request));
$this->assertFalse($request->attributes->has(self::ATTRIBUTE_FIREWALL_CONTEXT));
}
@@ -71,6 +72,9 @@ class FirewallMapTest extends TestCase
$exceptionListener = $this->getMockBuilder(ExceptionListener::class)->disableOriginalConstructor()->getMock();
$firewallContext->expects($this->once())->method('getExceptionListener')->willReturn($exceptionListener);
+ $logoutListener = $this->getMockBuilder(LogoutListener::class)->disableOriginalConstructor()->getMock();
+ $firewallContext->expects($this->once())->method('getLogoutListener')->willReturn($logoutListener);
+
$matcher = $this->getMockBuilder(RequestMatcherInterface::class)->getMock();
$matcher->expects($this->once())
->method('matches')
@@ -82,7 +86,7 @@ class FirewallMapTest extends TestCase
$firewallMap = new FirewallMap($container, array('security.firewall.map.context.foo' => $matcher));
- $this->assertEquals(array(array($listener), $exceptionListener), $firewallMap->getListeners($request));
+ $this->assertEquals(array(array($listener), $exceptionListener, $logoutListener), $firewallMap->getListeners($request));
$this->assertEquals($firewallConfig, $firewallMap->getFirewallConfig($request));
$this->assertEquals('security.firewall.map.context.foo', $request->attributes->get(self::ATTRIBUTE_FIREWALL_CONTEXT));
}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig
index be77f89103..88a5829905 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig
@@ -7,10 +7,8 @@
'default': '#999',
'section': '#444',
'event_listener': '#00B8F5',
- 'event_listener_loading': '#00B8F5',
'template': '#66CC00',
'doctrine': '#FF6633',
- 'propel': '#FF6633',
} %}
{% endif %}
diff --git a/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php b/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php
index e4b08790ad..91763e5a9f 100644
--- a/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php
+++ b/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php
@@ -119,31 +119,30 @@ class CacheDataCollector extends DataCollector implements LateDataCollectorInter
);
/** @var TraceableAdapterEvent $call */
foreach ($calls as $call) {
- $statistics[$name]['calls'] += 1;
+ ++$statistics[$name]['calls'];
$statistics[$name]['time'] += $call->end - $call->start;
if ('getItem' === $call->name) {
- $statistics[$name]['reads'] += 1;
+ ++$statistics[$name]['reads'];
if ($call->hits) {
- $statistics[$name]['hits'] += 1;
+ ++$statistics[$name]['hits'];
} else {
- $statistics[$name]['misses'] += 1;
+ ++$statistics[$name]['misses'];
}
} elseif ('getItems' === $call->name) {
- $count = $call->hits + $call->misses;
- $statistics[$name]['reads'] += $count;
+ $statistics[$name]['reads'] += $call->hits + $call->misses;
$statistics[$name]['hits'] += $call->hits;
- $statistics[$name]['misses'] += $count - $call->misses;
+ $statistics[$name]['misses'] += $call->misses;
} elseif ('hasItem' === $call->name) {
- $statistics[$name]['reads'] += 1;
+ ++$statistics[$name]['reads'];
if (false === $call->result) {
- $statistics[$name]['misses'] += 1;
+ ++$statistics[$name]['misses'];
} else {
- $statistics[$name]['hits'] += 1;
+ ++$statistics[$name]['hits'];
}
} elseif ('save' === $call->name) {
- $statistics[$name]['writes'] += 1;
+ ++$statistics[$name]['writes'];
} elseif ('deleteItem' === $call->name) {
- $statistics[$name]['deletes'] += 1;
+ ++$statistics[$name]['deletes'];
}
}
if ($statistics[$name]['reads']) {
diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php
index b8e05d9e41..9fc6177c6b 100644
--- a/src/Symfony/Component/Cache/Traits/RedisTrait.php
+++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php
@@ -126,9 +126,12 @@ trait RedisTrait
throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e->getMessage(), $dsn));
}
- if (@!$redis->isConnected()) {
- $e = ($e = error_get_last()) && preg_match('/^Redis::p?connect\(\): (.*)/', $e['message'], $e) ? sprintf(' (%s)', $e[1]) : '';
- throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $e, $dsn));
+ 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 failed%s: %s', $error, $dsn));
}
if ((null !== $auth && !$redis->auth($auth))
diff --git a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php
index 9d61c9cd83..10b4a7a9b4 100644
--- a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php
+++ b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php
@@ -55,7 +55,7 @@ class XmlUtilsTest extends TestCase
XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate'));
$this->fail();
} catch (\InvalidArgumentException $e) {
- $this->assertRegExp('/The XML file "[\w:\/\\\.~+-]+" is not valid\./', $e->getMessage());
+ $this->assertRegExp('/The XML file ".+" is not valid\./', $e->getMessage());
}
$this->assertInstanceOf('DOMDocument', XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate')));
diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php
index f42ee945f5..b64d9af361 100644
--- a/src/Symfony/Component/Console/Command/Command.php
+++ b/src/Symfony/Component/Console/Command/Command.php
@@ -218,12 +218,11 @@ class Command
if (null !== $this->processTitle) {
if (function_exists('cli_set_process_title')) {
- if (false === @cli_set_process_title($this->processTitle)) {
+ if (!@cli_set_process_title($this->processTitle)) {
if ('Darwin' === PHP_OS) {
$output->writeln('Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.');
} else {
- $error = error_get_last();
- trigger_error($error['message'], E_USER_WARNING);
+ cli_set_process_title($this->processTitle);
}
}
} elseif (function_exists('setproctitle')) {
diff --git a/src/Symfony/Component/CssSelector/Node/Specificity.php b/src/Symfony/Component/CssSelector/Node/Specificity.php
index 11228f7246..9b35cb4116 100644
--- a/src/Symfony/Component/CssSelector/Node/Specificity.php
+++ b/src/Symfony/Component/CssSelector/Node/Specificity.php
@@ -40,7 +40,7 @@ class Specificity
$this->c = $c;
}
- public function plus(Specificity $specificity): Specificity
+ public function plus(self $specificity): self
{
return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c);
}
@@ -56,7 +56,7 @@ class Specificity
*
* @return int
*/
- public function compareTo(Specificity $specificity)
+ public function compareTo(self $specificity)
{
if ($this->a !== $specificity->a) {
return $this->a > $specificity->a ? 1 : -1;
diff --git a/src/Symfony/Component/CssSelector/XPath/Translator.php b/src/Symfony/Component/CssSelector/XPath/Translator.php
index 28478b3db7..73b548215d 100644
--- a/src/Symfony/Component/CssSelector/XPath/Translator.php
+++ b/src/Symfony/Component/CssSelector/XPath/Translator.php
@@ -114,7 +114,7 @@ class Translator implements TranslatorInterface
return ($prefix ?: '').$this->nodeToXPath($selector);
}
- public function registerExtension(Extension\ExtensionInterface $extension): Translator
+ public function registerExtension(Extension\ExtensionInterface $extension): self
{
$this->extensions[$extension->getName()] = $extension;
@@ -139,7 +139,7 @@ class Translator implements TranslatorInterface
return $this->extensions[$name];
}
- public function registerParserShortcut(ParserInterface $shortcut): Translator
+ public function registerParserShortcut(ParserInterface $shortcut): self
{
$this->shortcutParsers[] = $shortcut;
diff --git a/src/Symfony/Component/CssSelector/XPath/XPathExpr.php b/src/Symfony/Component/CssSelector/XPath/XPathExpr.php
index 8090df9907..638cbd0fe0 100644
--- a/src/Symfony/Component/CssSelector/XPath/XPathExpr.php
+++ b/src/Symfony/Component/CssSelector/XPath/XPathExpr.php
@@ -43,7 +43,7 @@ class XPathExpr
return $this->element;
}
- public function addCondition(string $condition): XPathExpr
+ public function addCondition(string $condition): self
{
$this->condition = $this->condition ? sprintf('(%s) and (%s)', $this->condition, $condition) : $condition;
@@ -55,7 +55,7 @@ class XPathExpr
return $this->condition;
}
- public function addNameTest(): XPathExpr
+ public function addNameTest(): self
{
if ('*' !== $this->element) {
$this->addCondition('name() = '.Translator::getXpathLiteral($this->element));
@@ -65,7 +65,7 @@ class XPathExpr
return $this;
}
- public function addStarPrefix(): XPathExpr
+ public function addStarPrefix(): self
{
$this->path .= '*/';
diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php
index 5dbdd69338..2702b4157f 100644
--- a/src/Symfony/Component/Debug/ErrorHandler.php
+++ b/src/Symfony/Component/Debug/ErrorHandler.php
@@ -380,14 +380,16 @@ class ErrorHandler
public function handleError($type, $message, $file, $line)
{
// Level is the current error reporting level to manage silent error.
+ $level = error_reporting();
+ $silenced = 0 === ($level & $type);
// Strong errors are not authorized to be silenced.
- $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
+ $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
$log = $this->loggedErrors & $type;
$throw = $this->thrownErrors & $type & $level;
$type &= $level | $this->screamedErrors;
if (!$type || (!$log && !$throw)) {
- return $type && $log;
+ return !$silenced && $type && $log;
}
$scope = $this->scopedErrors & $type;
@@ -493,7 +495,7 @@ class ErrorHandler
}
}
- return $type && $log;
+ return !$silenced && $type && $log;
}
/**
diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
index afe16ea4f7..eee8e9dc57 100644
--- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
+++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php
@@ -65,6 +65,30 @@ class ErrorHandlerTest extends TestCase
}
}
+ public function testErrorGetLast()
+ {
+ $handler = ErrorHandler::register();
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $handler->setDefaultLogger($logger);
+ $handler->screamAt(E_ALL);
+
+ try {
+ @trigger_error('Hello', E_USER_WARNING);
+ $expected = array(
+ 'type' => E_USER_WARNING,
+ 'message' => 'Hello',
+ 'file' => __FILE__,
+ 'line' => __LINE__ - 5,
+ );
+ $this->assertSame($expected, error_get_last());
+ } catch (\Exception $e) {
+ restore_error_handler();
+ restore_exception_handler();
+
+ throw $e;
+ }
+ }
+
public function testNotice()
{
ErrorHandler::register();
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
index 5d2d4429e4..901dc06ffa 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php
@@ -118,8 +118,12 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
$class = $definition->getClass();
- if (!$r = $this->container->getReflectionClass($class)) {
- throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
+ try {
+ if (!$r = $this->container->getReflectionClass($class)) {
+ throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
+ }
+ } catch (\ReflectionException $e) {
+ throw new RuntimeException(sprintf('Invalid service "%s": %s.', $this->currentId, lcfirst(rtrim($e->getMessage(), '.'))));
}
if (!$r = $r->getConstructor()) {
if ($required) {
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
index d3b379034b..b153b84764 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
@@ -120,6 +120,6 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
return false;
}
- return true;
+ return $this->container->getDefinition($ids[0])->isShared();
}
}
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
index c82a974360..0051fb5ac3 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php
@@ -27,6 +27,7 @@ class ResolveBindingsPass extends AbstractRecursivePass
{
private $usedBindings = array();
private $unusedBindings = array();
+ private $errorMessages = array();
/**
* {@inheritdoc}
@@ -37,11 +38,19 @@ class ResolveBindingsPass extends AbstractRecursivePass
parent::process($container);
foreach ($this->unusedBindings as list($key, $serviceId)) {
- throw new InvalidArgumentException(sprintf('Unused binding "%s" in service "%s".', $key, $serviceId));
+ $message = sprintf('Unused binding "%s" in service "%s".', $key, $serviceId);
+ if ($this->errorMessages) {
+ $message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : '');
+ }
+ foreach ($this->errorMessages as $m) {
+ $message .= "\n - ".$m;
+ }
+ throw new InvalidArgumentException($message);
}
} finally {
$this->usedBindings = array();
$this->unusedBindings = array();
+ $this->errorMessages = array();
}
}
@@ -94,6 +103,7 @@ class ResolveBindingsPass extends AbstractRecursivePass
$calls[] = array($constructor, $value->getArguments());
}
} catch (RuntimeException $e) {
+ $this->errorMessages[] = $e->getMessage();
$this->container->getDefinition($this->currentId)->addError($e->getMessage());
return parent::processValue($value, $isRoot);
diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php
index 9ecb2a21c3..78a8e3c327 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php
@@ -30,7 +30,7 @@ class InstanceofConfigurator extends AbstractServiceConfigurator
/**
* Defines an instanceof-conditional to be applied to following service definitions.
*/
- final public function instanceof(string $fqcn): InstanceofConfigurator
+ final public function instanceof(string $fqcn): self
{
return $this->parent->instanceof($fqcn);
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php
index bb60af4d19..78556b2ed2 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php
@@ -92,7 +92,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
$this->assertNotSame($container->getDefinition('bar'), $arguments[2]);
}
- public function testProcessInlinesMixedServicesLoop()
+ public function testProcessDoesNotInlineMixedServicesLoop()
{
$container = new ContainerBuilder();
$container
@@ -108,7 +108,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
$this->process($container);
- $this->assertEquals($container->getDefinition('foo')->getArgument(0), $container->getDefinition('bar'));
+ $this->assertEquals(new Reference('bar'), $container->getDefinition('foo')->getArgument(0));
}
/**
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
index 16e486afaf..65f5ceb80f 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php
@@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy;
+use Symfony\Component\DependencyInjection\Tests\Fixtures\ParentNotExists;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
use Symfony\Component\DependencyInjection\TypedReference;
@@ -61,6 +62,21 @@ class ResolveBindingsPassTest extends TestCase
$pass->process($container);
}
+ /**
+ * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
+ * @expectedExceptionMessageRegexp Unused binding "$quz" in service [\s\S]+ Invalid service ".*\\ParentNotExists": class NotExists not found\.
+ */
+ public function testMissingParent()
+ {
+ $container = new ContainerBuilder();
+
+ $definition = $container->register(ParentNotExists::class, ParentNotExists::class);
+ $definition->setBindings(array('$quz' => '123'));
+
+ $pass = new ResolveBindingsPass();
+ $pass->process($container);
+ }
+
public function testTypedReferenceSupport()
{
$container = new ContainerBuilder();
diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php
index db5df5cbeb..046dbb940e 100644
--- a/src/Symfony/Component/Filesystem/Filesystem.php
+++ b/src/Symfony/Component/Filesystem/Filesystem.php
@@ -22,6 +22,8 @@ use Symfony\Component\Filesystem\Exception\FileNotFoundException;
*/
class Filesystem
{
+ private static $lastError;
+
/**
* Copies a file.
*
@@ -96,12 +98,11 @@ class Filesystem
continue;
}
- if (true !== @mkdir($dir, $mode, true)) {
- $error = error_get_last();
+ if (!self::box('mkdir', $dir, $mode, true)) {
if (!is_dir($dir)) {
// The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
- if ($error) {
- throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
+ if (self::$lastError) {
+ throw new IOException(sprintf('Failed to create "%s": %s.', $dir, self::$lastError), 0, null, $dir);
}
throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
}
@@ -170,20 +171,17 @@ class Filesystem
foreach ($files as $file) {
if (is_link($file)) {
// See https://bugs.php.net/52176
- if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
- $error = error_get_last();
- throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
+ if (!(self::box('unlink', $file) || '\\' !== DIRECTORY_SEPARATOR || self::box('rmdir', $file)) && file_exists($file)) {
+ throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, self::$lastError));
}
} elseif (is_dir($file)) {
$this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
- if (!@rmdir($file) && file_exists($file)) {
- $error = error_get_last();
- throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
+ if (!self::box('rmdir', $file) && file_exists($file)) {
+ throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, self::$lastError));
}
- } elseif (!@unlink($file) && file_exists($file)) {
- $error = error_get_last();
- throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
+ } elseif (!self::box('unlink', $file) && file_exists($file)) {
+ throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, self::$lastError));
}
}
}
@@ -337,16 +335,14 @@ class Filesystem
$this->mkdir(dirname($targetDir));
- $ok = false;
if (is_link($targetDir)) {
- if (readlink($targetDir) != $originDir) {
- $this->remove($targetDir);
- } else {
- $ok = true;
+ if (readlink($targetDir) === $originDir) {
+ return;
}
+ $this->remove($targetDir);
}
- if (!$ok && true !== @symlink($originDir, $targetDir)) {
+ if (!self::box('symlink', $originDir, $targetDir)) {
$this->linkException($originDir, $targetDir, 'symbolic');
}
}
@@ -378,7 +374,7 @@ class Filesystem
$this->remove($targetFile);
}
- if (true !== @link($originFile, $targetFile)) {
+ if (!self::box('link', $originFile, $targetFile)) {
$this->linkException($originFile, $targetFile, 'hard');
}
}
@@ -391,9 +387,8 @@ class Filesystem
*/
private function linkException($origin, $target, $linkType)
{
- $report = error_get_last();
- if (is_array($report)) {
- if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
+ if (self::$lastError) {
+ if ('\\' === DIRECTORY_SEPARATOR && false !== strpos(self::$lastError, 'error code(1314)')) {
throw new IOException(sprintf('Unable to create %s link due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?', $linkType), 0, null, $target);
}
}
@@ -743,4 +738,29 @@ class Filesystem
return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
}
+
+ private static function box($func)
+ {
+ self::$lastError = null;
+ \set_error_handler(__CLASS__.'::handleError');
+ try {
+ $result = \call_user_func_array($func, \array_slice(\func_get_args(), 1));
+ \restore_error_handler();
+
+ return $result;
+ } catch (\Throwable $e) {
+ } catch (\Exception $e) {
+ }
+ \restore_error_handler();
+
+ throw $e;
+ }
+
+ /**
+ * @internal
+ */
+ public static function handleError($type, $msg)
+ {
+ self::$lastError = $msg;
+ }
}
diff --git a/src/Symfony/Component/Finder/SplFileInfo.php b/src/Symfony/Component/Finder/SplFileInfo.php
index 6516113a3e..b8143ed799 100644
--- a/src/Symfony/Component/Finder/SplFileInfo.php
+++ b/src/Symfony/Component/Finder/SplFileInfo.php
@@ -66,12 +66,11 @@ class SplFileInfo extends \SplFileInfo
*/
public function getContents()
{
- $level = error_reporting(0);
+ set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
$content = file_get_contents($this->getPathname());
- error_reporting($level);
+ restore_error_handler();
if (false === $content) {
- $error = error_get_last();
- throw new \RuntimeException($error['message']);
+ throw new \RuntimeException($error);
}
return $content;
diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php
index 921ae2829c..a0e9b636c5 100644
--- a/src/Symfony/Component/Form/FormInterface.php
+++ b/src/Symfony/Component/Form/FormInterface.php
@@ -29,7 +29,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable
* @throws Exception\LogicException when trying to set a parent for a form with
* an empty name
*/
- public function setParent(FormInterface $parent = null);
+ public function setParent(self $parent = null);
/**
* Returns the parent form.
diff --git a/src/Symfony/Component/Form/FormView.php b/src/Symfony/Component/Form/FormView.php
index 21a3d5036a..9fbca43796 100644
--- a/src/Symfony/Component/Form/FormView.php
+++ b/src/Symfony/Component/Form/FormView.php
@@ -51,7 +51,7 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable
private $methodRendered = false;
- public function __construct(FormView $parent = null)
+ public function __construct(self $parent = null)
{
$this->parent = $parent;
}
diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php
index 7f1abc7c57..8cc1df5f52 100644
--- a/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php
+++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php
@@ -11,6 +11,15 @@
namespace Symfony\Component\Form\Tests;
+use Symfony\Component\Form\Extension\Core\Type\ButtonType;
+use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
+use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
+use Symfony\Component\Form\Extension\Core\Type\DateType;
+use Symfony\Component\Form\Extension\Core\Type\FileType;
+use Symfony\Component\Form\Extension\Core\Type\MoneyType;
+use Symfony\Component\Form\Extension\Core\Type\PercentType;
+use Symfony\Component\Form\Extension\Core\Type\RadioType;
+use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormError;
/**
@@ -22,7 +31,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
{
public function testRow()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
+ $form = $this->factory->createNamed('name', TextType::class);
$form->addError(new FormError('[trans]Error![/trans]'));
$view = $form->createView();
$html = $this->renderRow($view);
@@ -47,7 +56,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testLabelOnForm()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType');
+ $form = $this->factory->createNamed('name', DateType::class);
$view = $form->createView();
$this->renderWidget($view, array('label' => 'foo'));
$html = $this->renderLabel($view);
@@ -62,7 +71,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testLabelDoesNotRenderFieldAttributes()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
+ $form = $this->factory->createNamed('name', TextType::class);
$html = $this->renderLabel($form->createView(), null, array(
'attr' => array(
'class' => 'my&class',
@@ -79,7 +88,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testLabelWithCustomAttributesPassedDirectly()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
+ $form = $this->factory->createNamed('name', TextType::class);
$html = $this->renderLabel($form->createView(), null, array(
'label_attr' => array(
'class' => 'my&class',
@@ -96,7 +105,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testLabelWithCustomTextAndCustomAttributesPassedDirectly()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
+ $form = $this->factory->createNamed('name', TextType::class);
$html = $this->renderLabel($form->createView(), 'Custom label', array(
'label_attr' => array(
'class' => 'my&class',
@@ -114,7 +123,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
+ $form = $this->factory->createNamed('name', TextType::class, null, array(
'label' => 'Custom label',
));
$html = $this->renderLabel($form->createView(), null, array(
@@ -134,7 +143,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testLegendOnExpandedType()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, null, array(
'label' => 'Custom label',
'expanded' => true,
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
@@ -153,7 +162,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testHelp()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array(
+ $form = $this->factory->createNamed('name', TextType::class, null, array(
'help' => 'Help text test!',
));
$view = $form->createView();
@@ -170,7 +179,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testErrors()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType');
+ $form = $this->factory->createNamed('name', TextType::class);
$form->addError(new FormError('[trans]Error 1[/trans]'));
$form->addError(new FormError('[trans]Error 2[/trans]'));
$view = $form->createView();
@@ -195,7 +204,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testErrorWithNoLabel()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', array('label' => false));
+ $form = $this->factory->createNamed('name', TextType::class, array('label' => false));
$form->addError(new FormError('[trans]Error 1[/trans]'));
$view = $form->createView();
$html = $this->renderLabel($view);
@@ -205,7 +214,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testCheckedCheckbox()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', true);
+ $form = $this->factory->createNamed('name', CheckboxType::class, true);
$this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
'/div
@@ -222,7 +231,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceAttributesWithMainAttributes()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'multiple' => false,
'expanded' => false,
@@ -245,7 +254,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleExpandedChoiceAttributesWithMainAttributes()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'multiple' => false,
'expanded' => true,
@@ -278,7 +287,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testUncheckedCheckbox()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false);
+ $form = $this->factory->createNamed('name', CheckboxType::class, false);
$this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
'/div
@@ -294,7 +303,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testCheckboxWithValue()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false, array(
+ $form = $this->factory->createNamed('name', CheckboxType::class, false, array(
'value' => 'foo&bar',
));
@@ -312,7 +321,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpanded()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'multiple' => false,
'expanded' => true,
@@ -343,7 +352,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedWithLabelsAsFalse()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => false,
'multiple' => false,
@@ -373,7 +382,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedWithLabelsSetByCallable()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
'choice_label' => function ($choice, $label, $value) {
if ('&b' === $choice) {
@@ -417,7 +426,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedWithLabelsSetFalseByCallable()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => function () {
return false;
@@ -449,7 +458,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedWithoutTranslation()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'multiple' => false,
'expanded' => true,
@@ -481,7 +490,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedAttributes()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')),
'multiple' => false,
@@ -513,7 +522,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedWithPlaceholder()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'multiple' => false,
'expanded' => true,
@@ -553,7 +562,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, '&a', array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'multiple' => false,
'expanded' => true,
@@ -594,7 +603,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testSingleChoiceExpandedWithBooleanValue()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', true, array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, true, array(
'choices' => array('Choice&A' => '1', 'Choice&B' => '0'),
'multiple' => false,
'expanded' => true,
@@ -625,7 +634,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testMultipleChoiceExpanded()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, array('&a', '&c'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
'multiple' => true,
'expanded' => true,
@@ -664,7 +673,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testMultipleChoiceExpandedWithLabelsAsFalse()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, array('&a'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => false,
'multiple' => true,
@@ -694,7 +703,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testMultipleChoiceExpandedWithLabelsSetByCallable()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, array('&a'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
'choice_label' => function ($choice, $label, $value) {
if ('&b' === $choice) {
@@ -738,7 +747,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, array('&a'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'),
'choice_label' => function () {
return false;
@@ -770,7 +779,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testMultipleChoiceExpandedWithoutTranslation()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, array('&a', '&c'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
'multiple' => true,
'expanded' => true,
@@ -810,7 +819,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testMultipleChoiceExpandedAttributes()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array(
+ $form = $this->factory->createNamed('name', ChoiceType::class, array('&a', '&c'), array(
'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'),
'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')),
'multiple' => true,
@@ -850,7 +859,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testCheckedRadio()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', true);
+ $form = $this->factory->createNamed('name', RadioType::class, true);
$this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
'/div
@@ -872,7 +881,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testUncheckedRadio()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false);
+ $form = $this->factory->createNamed('name', RadioType::class, false);
$this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
'/div
@@ -893,7 +902,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testRadioWithValue()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false, array(
+ $form = $this->factory->createNamed('name', RadioType::class, false, array(
'value' => 'foo&bar',
));
@@ -917,7 +926,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testButtonAttributeNameRepeatedIfTrue()
{
- $form = $this->factory->createNamed('button', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, array(
+ $form = $this->factory->createNamed('button', ButtonType::class, null, array(
'attr' => array('foo' => true),
));
@@ -929,7 +938,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testFile()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\FileType');
+ $form = $this->factory->createNamed('name', FileType::class);
$this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class form-control-file')),
'/input
@@ -940,7 +949,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testMoney()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType', 1234.56, array(
+ $form = $this->factory->createNamed('name', MoneyType::class, 1234.56, array(
'currency' => 'EUR',
));
@@ -968,7 +977,7 @@ abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest
public function testPercent()
{
- $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PercentType', 0.1);
+ $form = $this->factory->createNamed('name', PercentType::class, 0.1);
$this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')),
'/div
diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php
index 9cbe941581..1f24323251 100644
--- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php
+++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php
@@ -2000,7 +2000,7 @@ class ChoiceTypeTest extends BaseTypeTest
$this->assertEquals('_09name', $view->vars['full_name']);
}
- /**
+ /**
* @dataProvider provideTrimCases
*/
public function testTrimIsDisabled($multiple, $expanded)
diff --git a/src/Symfony/Component/HttpFoundation/File/File.php b/src/Symfony/Component/HttpFoundation/File/File.php
index 4e6887a52a..44ac392511 100644
--- a/src/Symfony/Component/HttpFoundation/File/File.php
+++ b/src/Symfony/Component/HttpFoundation/File/File.php
@@ -93,9 +93,11 @@ class File extends \SplFileInfo
{
$target = $this->getTargetFile($directory, $name);
- if (!@rename($this->getPathname(), $target)) {
- $error = error_get_last();
- throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
+ set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
+ $renamed = rename($this->getPathname(), $target);
+ restore_error_handler();
+ if (!$renamed) {
+ throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
}
@chmod($target, 0666 & ~umask());
diff --git a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php
index c4abec390d..252f46ad8e 100644
--- a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php
+++ b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php
@@ -207,9 +207,11 @@ class UploadedFile extends File
$target = $this->getTargetFile($directory, $name);
- if (!@move_uploaded_file($this->getPathname(), $target)) {
- $error = error_get_last();
- throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message'])));
+ set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
+ $moved = move_uploaded_file($this->getPathname(), $target);
+ restore_error_handler();
+ if (!$moved) {
+ throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error)));
}
@chmod($target, 0666 & ~umask());
diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php
index 26c13ebd15..82240738ce 100644
--- a/src/Symfony/Component/HttpFoundation/Request.php
+++ b/src/Symfony/Component/HttpFoundation/Request.php
@@ -1243,7 +1243,7 @@ class Request
*
* @param string $format The format
*
- * @return string The associated mime type (null if not found)
+ * @return string|null The associated mime type (null if not found)
*/
public function getMimeType($format)
{
diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php
index 5ae3d52cc3..43f07f25de 100644
--- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php
+++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php
@@ -674,14 +674,16 @@ class PdoSessionHandler extends AbstractSessionHandler
{
switch ($this->driver) {
case 'mysql':
+ // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced.
+ $lockId = \substr($sessionId, 0, 64);
// should we handle the return value? 0 on timeout, null on error
// we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout
$stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)');
- $stmt->bindValue(':key', $sessionId, \PDO::PARAM_STR);
+ $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR);
$stmt->execute();
$releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)');
- $releaseStmt->bindValue(':key', $sessionId, \PDO::PARAM_STR);
+ $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR);
return $releaseStmt;
case 'pgsql':
@@ -833,7 +835,7 @@ class PdoSessionHandler extends AbstractSessionHandler
/**
* Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data.
*/
- private function getMergeStatement(string $sessionId, string $data, int$maxlifetime): ?\PDOStatement
+ private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement
{
switch (true) {
case 'mysql' === $this->driver:
diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php
index b35727962e..b4af82ddf6 100644
--- a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php
+++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php
@@ -300,7 +300,7 @@ class ResponseTest extends ResponseTestCase
$response = new Response();
$response->headers->set('Cache-Control', 'must-revalidate');
$response->headers->set('Expires', -1);
- $this->assertLessThanOrEqual(time() - 2*86400, $response->getExpires()->format('U'));
+ $this->assertLessThanOrEqual(time() - 2 * 86400, $response->getExpires()->format('U'));
$response = new Response();
$this->assertNull($response->getMaxAge(), '->getMaxAge() returns null if no freshness information available');
diff --git a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php
index 646adc074b..86683d55de 100644
--- a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php
+++ b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php
@@ -34,7 +34,7 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
}
foreach ($reflection->getParameters() as $param) {
- $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull());
+ $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull());
}
return $arguments;
@@ -47,12 +47,25 @@ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
*
* @return null|string
*/
- private function getType(\ReflectionParameter $parameter)
+ private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function)
{
if (!$type = $parameter->getType()) {
return;
}
+ $name = $type->getName();
+ $lcName = strtolower($name);
- return $type->getName();
+ if ('self' !== $lcName && 'parent' !== $lcName) {
+ return $name;
+ }
+ if (!$function instanceof \ReflectionMethod) {
+ return;
+ }
+ if ('self' === $lcName) {
+ return $function->getDeclaringClass()->name;
+ }
+ if ($parent = $function->getDeclaringClass()->getParentClass()) {
+ return $parent->name;
+ }
}
}
diff --git a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
index 98a397a2e6..f7cf446e52 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
@@ -14,6 +14,7 @@ namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\KernelEvents;
@@ -129,12 +130,6 @@ class RouterListener implements EventSubscriberInterface
unset($parameters['_route'], $parameters['_controller']);
$request->attributes->set('_route_params', $parameters);
} catch (ResourceNotFoundException $e) {
- if ($this->debug && $e instanceof NoConfigurationException) {
- $event->setResponse($this->createWelcomeResponse());
-
- return;
- }
-
$message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());
if ($referer = $request->headers->get('referer')) {
@@ -149,11 +144,23 @@ class RouterListener implements EventSubscriberInterface
}
}
+ public function onKernelException(GetResponseForExceptionEvent $event)
+ {
+ if (!$this->debug || !($e = $event->getException()) instanceof NotFoundHttpException) {
+ return;
+ }
+
+ if ($e->getPrevious() instanceof NoConfigurationException) {
+ $event->setResponse($this->createWelcomeResponse());
+ }
+ }
+
public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => array(array('onKernelRequest', 32)),
KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
+ KernelEvents::EXCEPTION => array('onKernelException', -64),
);
}
diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profile.php b/src/Symfony/Component/HttpKernel/Profiler/Profile.php
index f03c872672..bb18c7bcab 100644
--- a/src/Symfony/Component/HttpKernel/Profiler/Profile.php
+++ b/src/Symfony/Component/HttpKernel/Profiler/Profile.php
@@ -71,7 +71,7 @@ class Profile
/**
* Sets the parent token.
*/
- public function setParent(Profile $parent)
+ public function setParent(self $parent)
{
$this->parent = $parent;
}
@@ -210,7 +210,7 @@ class Profile
/**
* Adds the child token.
*/
- public function addChild(Profile $child)
+ public function addChild(self $child)
{
$this->children[] = $child;
$child->setParent($this);
diff --git a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php
index 2ddc6e7a5e..a667705f50 100644
--- a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php
@@ -117,11 +117,11 @@ class ArgumentMetadataFactoryTest extends TestCase
), $arguments);
}
- private function signature1(ArgumentMetadataFactoryTest $foo, array $bar, callable $baz)
+ private function signature1(self $foo, array $bar, callable $baz)
{
}
- private function signature2(ArgumentMetadataFactoryTest $foo = null, FakeClassThatDoesNotExist $bar = null, ImportedAndFake $baz = null)
+ private function signature2(self $foo = null, FakeClassThatDoesNotExist $bar = null, ImportedAndFake $baz = null)
{
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php
index 760366c694..05d8d787aa 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php
@@ -6,21 +6,6 @@ use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException;
class UnprocessableEntityHttpExceptionTest extends HttpExceptionTest
{
- /**
- * Test that setting the headers using the setter function
- * is working as expected.
- *
- * @param array $headers The headers to set
- *
- * @dataProvider headerDataProvider
- */
- public function testHeadersSetter($headers)
- {
- $exception = new UnprocessableEntityHttpException(10);
- $exception->setHeaders($headers);
- $this->assertSame($headers, $exception->getHeaders());
- }
-
protected function createException()
{
return new UnprocessableEntityHttpException();
diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php
index d47287a1fb..4dae039c11 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php
@@ -6,17 +6,7 @@ use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
class UnsupportedMediaTypeHttpExceptionTest extends HttpExceptionTest
{
- /**
- * @dataProvider headerDataProvider
- */
- public function testHeadersSetter($headers)
- {
- $exception = new UnsupportedMediaTypeHttpException(10);
- $exception->setHeaders($headers);
- $this->assertSame($headers, $exception->getHeaders());
- }
-
- protected function createException($headers = array())
+ protected function createException()
{
return new UnsupportedMediaTypeHttpException();
}
diff --git a/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php b/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php
index 243c3c5c5a..2d5f0ca5ad 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php
@@ -44,7 +44,7 @@ class ProfilerTest extends TestCase
public function testReset()
{
$collector = $this->getMockBuilder(DataCollectorInterface::class)
- ->setMethods(['collect', 'getName', 'reset'])
+ ->setMethods(array('collect', 'getName', 'reset'))
->getMock();
$collector->expects($this->any())->method('getName')->willReturn('mock');
$collector->expects($this->once())->method('reset');
diff --git a/src/Symfony/Component/Ldap/Ldap.php b/src/Symfony/Component/Ldap/Ldap.php
index 26fd4f946c..de1ab1a249 100644
--- a/src/Symfony/Component/Ldap/Ldap.php
+++ b/src/Symfony/Component/Ldap/Ldap.php
@@ -70,7 +70,7 @@ final class Ldap implements LdapInterface
*
* @return static
*/
- public static function create($adapter, array $config = array()): Ldap
+ public static function create($adapter, array $config = array()): self
{
if (!isset(self::$adapterMap[$adapter])) {
throw new DriverNotFoundException(sprintf(
diff --git a/src/Symfony/Component/Lock/Store/FlockStore.php b/src/Symfony/Component/Lock/Store/FlockStore.php
index 64438fd461..bf72eaefe2 100644
--- a/src/Symfony/Component/Lock/Store/FlockStore.php
+++ b/src/Symfony/Component/Lock/Store/FlockStore.php
@@ -78,8 +78,7 @@ class FlockStore implements StoreInterface
);
// Silence error reporting
- set_error_handler(function () {
- });
+ set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; });
if (!$handle = fopen($fileName, 'r')) {
if ($handle = fopen($fileName, 'x')) {
chmod($fileName, 0444);
@@ -91,8 +90,7 @@ class FlockStore implements StoreInterface
restore_error_handler();
if (!$handle) {
- $error = error_get_last();
- throw new LockStorageException($error['message'], 0, null);
+ throw new LockStorageException($error, 0, null);
}
// On Windows, even if PHP doc says the contrary, LOCK_NB works, see
diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php
index 8edd6b5c89..68b4154b10 100644
--- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php
+++ b/src/Symfony/Component/OptionsResolver/OptionsResolver.php
@@ -975,7 +975,7 @@ class OptionsResolver implements Options
* parameters should usually not be included in messages aimed at
* non-technical people.
*
- * @param mixed $value The value to return the type of
+ * @param mixed $value The value to return the type of
*/
private function formatTypeOf($value, ?string $type): string
{
diff --git a/src/Symfony/Component/Process/ExecutableFinder.php b/src/Symfony/Component/Process/ExecutableFinder.php
index d042a5b13a..1ec6526d45 100644
--- a/src/Symfony/Component/Process/ExecutableFinder.php
+++ b/src/Symfony/Component/Process/ExecutableFinder.php
@@ -77,7 +77,7 @@ class ExecutableFinder
}
foreach ($suffixes as $suffix) {
foreach ($dirs as $dir) {
- if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
+ if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || @is_executable($file))) {
return $file;
}
}
diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php
index f5f301a7ea..abc41b6630 100644
--- a/src/Symfony/Component/Process/PhpExecutableFinder.php
+++ b/src/Symfony/Component/Process/PhpExecutableFinder.php
@@ -52,7 +52,7 @@ class PhpExecutableFinder
}
if ($php = getenv('PHP_PATH')) {
- if (!is_executable($php)) {
+ if (!@is_executable($php)) {
return false;
}
@@ -60,12 +60,12 @@ class PhpExecutableFinder
}
if ($php = getenv('PHP_PEAR_PHP_BIN')) {
- if (is_executable($php)) {
+ if (@is_executable($php)) {
return $php;
}
}
- if (is_executable($php = PHP_BINDIR.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
+ if (@is_executable($php = PHP_BINDIR.('\\' === DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
return $php;
}
diff --git a/src/Symfony/Component/Process/Pipes/AbstractPipes.php b/src/Symfony/Component/Process/Pipes/AbstractPipes.php
index 2bd1fe75b7..9a7d88be89 100644
--- a/src/Symfony/Component/Process/Pipes/AbstractPipes.php
+++ b/src/Symfony/Component/Process/Pipes/AbstractPipes.php
@@ -25,6 +25,7 @@ abstract class AbstractPipes implements PipesInterface
private $inputBuffer = '';
private $input;
private $blocked = true;
+ private $lastError;
/**
* @param resource|string|int|float|bool|\Iterator|null $input
@@ -58,10 +59,11 @@ abstract class AbstractPipes implements PipesInterface
*/
protected function hasSystemCallBeenInterrupted()
{
- $lastError = error_get_last();
+ $lastError = $this->lastError;
+ $this->lastError = null;
// stream_select returns false when the `select` system call is interrupted by an incoming signal
- return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
+ return null !== $lastError && false !== stripos($lastError, 'interrupted system call');
}
/**
@@ -165,4 +167,12 @@ abstract class AbstractPipes implements PipesInterface
return array($this->pipes[0]);
}
}
+
+ /**
+ * @internal
+ */
+ public function handleError($type, $msg)
+ {
+ $this->lastError = $msg;
+ }
}
diff --git a/src/Symfony/Component/Process/Pipes/UnixPipes.php b/src/Symfony/Component/Process/Pipes/UnixPipes.php
index badaf34d42..23f873471d 100644
--- a/src/Symfony/Component/Process/Pipes/UnixPipes.php
+++ b/src/Symfony/Component/Process/Pipes/UnixPipes.php
@@ -99,7 +99,9 @@ class UnixPipes extends AbstractPipes
unset($r[0]);
// let's have a look if something changed in streams
- if (($r || $w) && false === @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
+ set_error_handler(array($this, 'handleError'));
+ if (($r || $w) && false === stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
+ restore_error_handler();
// if a system call has been interrupted, forget about it, let's try again
// otherwise, an error occurred, let's reset pipes
if (!$this->hasSystemCallBeenInterrupted()) {
@@ -108,6 +110,7 @@ class UnixPipes extends AbstractPipes
return $read;
}
+ restore_error_handler();
foreach ($r as $pipe) {
// prior PHP 5.4 the array passed to stream_select is modified and
diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
index 89c1d4c361..ff6f7cdce1 100644
--- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
+++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php
@@ -162,7 +162,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
if (!$reflectionType = $reflectionParameter->getType()) {
return null;
}
- $type = $this->extractFromReflectionType($reflectionType);
+ $type = $this->extractFromReflectionType($reflectionType, $reflectionMethod);
if (\in_array($prefix, $this->arrayMutatorPrefixes)) {
$type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type);
@@ -184,7 +184,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
}
if ($reflectionType = $reflectionMethod->getReturnType()) {
- return array($this->extractFromReflectionType($reflectionType));
+ return array($this->extractFromReflectionType($reflectionType, $reflectionMethod));
}
if (\in_array($prefix, array('is', 'can', 'has'))) {
@@ -217,8 +217,9 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
if ($property !== $parameter->name) {
continue;
}
+ $reflectionType = $parameter->getType();
- return array($this->extractFromReflectionType($parameter->getType()));
+ return $reflectionType ? array($this->extractFromReflectionType($reflectionType, $constructor)) : null;
}
if ($parentClass = $reflectionClass->getParentClass()) {
@@ -228,7 +229,7 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
return null;
}
- private function extractFromReflectionType(\ReflectionType $reflectionType): Type
+ private function extractFromReflectionType(\ReflectionType $reflectionType, \ReflectionMethod $reflectionMethod): Type
{
$phpTypeOrClass = $reflectionType->getName();
$nullable = $reflectionType->allowsNull();
@@ -240,12 +241,24 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp
} elseif ($reflectionType->isBuiltin()) {
$type = new Type($phpTypeOrClass, $nullable);
} else {
- $type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $phpTypeOrClass);
+ $type = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));
}
return $type;
}
+ private function resolveTypeName(string $name, \ReflectionMethod $reflectionMethod): string
+ {
+ if ('self' === $lcName = strtolower($name)) {
+ return $reflectionMethod->getDeclaringClass()->name;
+ }
+ if ('parent' === $lcName && $parent = $reflectionMethod->getDeclaringClass()->getParentClass()) {
+ return $parent->name;
+ }
+
+ return $name;
+ }
+
private function isPublicProperty(string $class, string $property): bool
{
try {
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php
similarity index 99%
rename from src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php
rename to src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php
index 38a9ff9e63..af22aa9c91 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/PhpDocExtractorTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\PropertyInfo\Tests\PhpDocExtractors;
+namespace Symfony\Component\PropertyInfo\Tests\PhpDocExtractor;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
similarity index 94%
rename from src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php
rename to src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
index 09a2d3580c..f5b47196ee 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
@@ -52,6 +52,8 @@ class ReflectionExtractorTest extends TestCase
'DOB',
'Id',
'123',
+ 'self',
+ 'realParent',
'c',
'd',
'e',
@@ -154,6 +156,8 @@ class ReflectionExtractorTest extends TestCase
array('donotexist', null),
array('staticGetter', null),
array('staticSetter', null),
+ array('self', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy'))),
+ array('realParent', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy'))),
);
}
@@ -171,6 +175,8 @@ class ReflectionExtractorTest extends TestCase
array('foo', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true))),
array('bar', array(new Type(Type::BUILTIN_TYPE_INT))),
array('baz', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_STRING)))),
+ array('buz', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\Php7Dummy'))),
+ array('biz', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'stdClass'))),
array('donotexist', null),
);
}
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/SerializerExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php
similarity index 95%
rename from src/Symfony/Component/PropertyInfo/Tests/Extractors/SerializerExtractorTest.php
rename to src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php
index b1be5ee118..91cdf80f8d 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/SerializerExtractorTest.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Extractor/SerializerExtractorTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\PropertyInfo\Tests\Extractors;
+namespace Symfony\Component\PropertyInfo\Tests\Extractor;
use Doctrine\Common\Annotations\AnnotationReader;
use PHPUnit\Framework\TestCase;
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
index 0916217020..afe09ef929 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php
@@ -127,4 +127,18 @@ class Dummy extends ParentDummy
public function get123()
{
}
+
+ /**
+ * @param self $self
+ */
+ public function setSelf(self $self)
+ {
+ }
+
+ /**
+ * @param parent $realParent
+ */
+ public function setRealParent(parent $realParent)
+ {
+ }
}
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php
index dc9109d7d1..b3f6d77907 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/ParentDummy.php
@@ -29,7 +29,7 @@ class ParentDummy
public $foo2;
/**
- * @var callback
+ * @var callable
*/
public $foo3;
diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php
index cd5ba380d9..5dcb4c565e 100644
--- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php
+++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Php7Dummy.php
@@ -14,7 +14,7 @@ namespace Symfony\Component\PropertyInfo\Tests\Fixtures;
/**
* @author Kévin Dunglas
*/
-class Php7Dummy
+class Php7Dummy extends \stdClass
{
public function getFoo(): array
{
@@ -27,4 +27,12 @@ class Php7Dummy
public function addBaz(string $baz)
{
}
+
+ public function getBuz(): self
+ {
+ }
+
+ public function getBiz(): parent
+ {
+ }
}
diff --git a/src/Symfony/Component/PropertyInfo/Type.php b/src/Symfony/Component/PropertyInfo/Type.php
index 71aa162f70..461495ed51 100644
--- a/src/Symfony/Component/PropertyInfo/Type.php
+++ b/src/Symfony/Component/PropertyInfo/Type.php
@@ -59,7 +59,7 @@ class Type
/**
* @throws \InvalidArgumentException
*/
- public function __construct(string $builtinType, bool $nullable = false, string $class = null, bool $collection = false, Type $collectionKeyType = null, Type $collectionValueType = null)
+ public function __construct(string $builtinType, bool $nullable = false, string $class = null, bool $collection = false, self $collectionKeyType = null, self $collectionValueType = null)
{
if (!in_array($builtinType, self::$builtinTypes)) {
throw new \InvalidArgumentException(sprintf('"%s" is not a valid PHP type.', $builtinType));
diff --git a/src/Symfony/Component/Routing/RouteCollectionBuilder.php b/src/Symfony/Component/Routing/RouteCollectionBuilder.php
index d63c6138f7..c98d642a06 100644
--- a/src/Symfony/Component/Routing/RouteCollectionBuilder.php
+++ b/src/Symfony/Component/Routing/RouteCollectionBuilder.php
@@ -118,7 +118,7 @@ class RouteCollectionBuilder
* @param string $prefix
* @param RouteCollectionBuilder $builder
*/
- public function mount($prefix, RouteCollectionBuilder $builder)
+ public function mount($prefix, self $builder)
{
$builder->prefix = trim(trim($prefix), '/');
$this->routes[] = $builder;
@@ -251,11 +251,9 @@ class RouteCollectionBuilder
/**
* Adds a resource for this collection.
*
- * @param ResourceInterface $resource
- *
* @return $this
*/
- private function addResource(ResourceInterface $resource): RouteCollectionBuilder
+ private function addResource(ResourceInterface $resource): self
{
$this->resources[] = $resource;
diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
index 80ae75caa2..b9859452b1 100644
--- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
+++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php
@@ -14,7 +14,6 @@ namespace Symfony\Component\Security\Guard\Firewall;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Guard\AuthenticatorInterface;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
diff --git a/src/Symfony/Component/Security/Http/Firewall.php b/src/Symfony/Component/Security/Http/Firewall.php
index 28b56d5791..9bee596759 100644
--- a/src/Symfony/Component/Security/Http/Firewall.php
+++ b/src/Symfony/Component/Security/Http/Firewall.php
@@ -47,13 +47,22 @@ class Firewall implements EventSubscriberInterface
}
// register listeners for this firewall
- list($listeners, $exceptionListener) = $this->map->getListeners($event->getRequest());
+ $listeners = $this->map->getListeners($event->getRequest());
+
+ $authenticationListeners = $listeners[0];
+ $exceptionListener = $listeners[1];
+ $logoutListener = isset($listeners[2]) ? $listeners[2] : null;
+
if (null !== $exceptionListener) {
$this->exceptionListeners[$event->getRequest()] = $exceptionListener;
$exceptionListener->register($this->dispatcher);
}
- return $this->handleRequest($event, $listeners);
+ $this->handleRequest($event, $authenticationListeners);
+
+ if (null !== $logoutListener) {
+ $logoutListener->handle($event);
+ }
}
public function onKernelFinishRequest(FinishRequestEvent $event)
diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php
index fdc74a6cb6..62b7df0031 100644
--- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php
@@ -45,7 +45,6 @@ class ContextListener implements ListenerInterface
private $trustResolver;
/**
- * @param TokenStorageInterface $tokenStorage
* @param iterable|UserProviderInterface[] $userProviders
*/
public function __construct(TokenStorageInterface $tokenStorage, iterable $userProviders, string $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null)
diff --git a/src/Symfony/Component/Security/Http/FirewallMap.php b/src/Symfony/Component/Security/Http/FirewallMap.php
index e767d123cb..fc97410d4e 100644
--- a/src/Symfony/Component/Security/Http/FirewallMap.php
+++ b/src/Symfony/Component/Security/Http/FirewallMap.php
@@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Http;
use Symfony\Component\HttpFoundation\RequestMatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Firewall\ExceptionListener;
+use Symfony\Component\Security\Http\Firewall\LogoutListener;
/**
* FirewallMap allows configuration of different firewalls for specific parts
@@ -25,9 +26,9 @@ class FirewallMap implements FirewallMapInterface
{
private $map = array();
- public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = array(), ExceptionListener $exceptionListener = null)
+ public function add(RequestMatcherInterface $requestMatcher = null, array $listeners = array(), ExceptionListener $exceptionListener = null, LogoutListener $logoutListener = null)
{
- $this->map[] = array($requestMatcher, $listeners, $exceptionListener);
+ $this->map[] = array($requestMatcher, $listeners, $exceptionListener, $logoutListener);
}
/**
@@ -37,10 +38,10 @@ class FirewallMap implements FirewallMapInterface
{
foreach ($this->map as $elements) {
if (null === $elements[0] || $elements[0]->matches($request)) {
- return array($elements[1], $elements[2]);
+ return array($elements[1], $elements[2], $elements[3]);
}
}
- return array(array(), null);
+ return array(array(), null, null);
}
}
diff --git a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php
index 944a7b3133..d9a15d5ac0 100644
--- a/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php
+++ b/src/Symfony/Component/Serializer/Mapping/AttributeMetadataInterface.php
@@ -60,5 +60,5 @@ interface AttributeMetadataInterface
/**
* Merges an {@see AttributeMetadataInterface} with in the current one.
*/
- public function merge(AttributeMetadataInterface $attributeMetadata);
+ public function merge(self $attributeMetadata);
}
diff --git a/src/Symfony/Component/Serializer/Mapping/ClassMetadataInterface.php b/src/Symfony/Component/Serializer/Mapping/ClassMetadataInterface.php
index ddcffe97c9..45ed03dfa1 100644
--- a/src/Symfony/Component/Serializer/Mapping/ClassMetadataInterface.php
+++ b/src/Symfony/Component/Serializer/Mapping/ClassMetadataInterface.php
@@ -46,7 +46,7 @@ interface ClassMetadataInterface
/**
* Merges a {@link ClassMetadataInterface} in the current one.
*/
- public function merge(ClassMetadataInterface $classMetadata);
+ public function merge(self $classMetadata);
/**
* Returns a {@link \ReflectionClass} instance for this class.
diff --git a/src/Symfony/Component/Translation/MessageCatalogueInterface.php b/src/Symfony/Component/Translation/MessageCatalogueInterface.php
index 4dad27fbf6..e0dbb2bd96 100644
--- a/src/Symfony/Component/Translation/MessageCatalogueInterface.php
+++ b/src/Symfony/Component/Translation/MessageCatalogueInterface.php
@@ -105,7 +105,7 @@ interface MessageCatalogueInterface
*
* The two catalogues must have the same locale.
*/
- public function addCatalogue(MessageCatalogueInterface $catalogue);
+ public function addCatalogue(self $catalogue);
/**
* Merges translations from the given Catalogue into the current one
@@ -113,7 +113,7 @@ interface MessageCatalogueInterface
*
* This is used to provide default translations when they do not exist for the current locale.
*/
- public function addFallbackCatalogue(MessageCatalogueInterface $catalogue);
+ public function addFallbackCatalogue(self $catalogue);
/**
* Gets the fallback catalogue.
diff --git a/src/Symfony/Component/Validator/ConstraintViolationListInterface.php b/src/Symfony/Component/Validator/ConstraintViolationListInterface.php
index 0489ab500a..47e986f51e 100644
--- a/src/Symfony/Component/Validator/ConstraintViolationListInterface.php
+++ b/src/Symfony/Component/Validator/ConstraintViolationListInterface.php
@@ -26,7 +26,7 @@ interface ConstraintViolationListInterface extends \Traversable, \Countable, \Ar
/**
* Merges an existing violation list into this list.
*/
- public function addAll(ConstraintViolationListInterface $otherList);
+ public function addAll(self $otherList);
/**
* Returns the violation at a given offset.
diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php
index dd0dd1fa46..d777386144 100644
--- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php
+++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php
@@ -330,7 +330,7 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface
/**
* Merges the constraints of the given metadata into this object.
*/
- public function mergeConstraints(ClassMetadata $source)
+ public function mergeConstraints(self $source)
{
if ($source->isGroupSequenceProvider()) {
$this->setGroupSequenceProvider(true);