From fe586acd92d67be07f269d0b48e0046cfe62efe8 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Tue, 27 Feb 2018 17:11:57 +0100 Subject: [PATCH 01/18] [Config] Backport string|null api for node names --- src/Symfony/Component/Config/Definition/BaseNode.php | 4 ++-- .../Component/Config/Definition/Builder/NodeBuilder.php | 4 ++-- .../Component/Config/Definition/Builder/NodeDefinition.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index 2e346d7907..8568bf182b 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -33,8 +33,8 @@ abstract class BaseNode implements NodeInterface protected $attributes = array(); /** - * @param string $name The name of the node - * @param NodeInterface $parent The parent of this node + * @param string|null $name The name of the node + * @param NodeInterface|null $parent The parent of this node * * @throws \InvalidArgumentException if the name contains a period */ diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php index 152a497b14..1fac66fd37 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php @@ -143,8 +143,8 @@ class NodeBuilder implements NodeParentInterface /** * Creates a child node. * - * @param string $name The name of the node - * @param string $type The type of the node + * @param string|null $name The name of the node + * @param string $type The type of the node * * @return NodeDefinition The child node * diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php index 3c2610b5d1..8546fcd5ef 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php @@ -36,7 +36,7 @@ abstract class NodeDefinition implements NodeParentInterface protected $attributes = array(); /** - * @param string $name The name of the node + * @param string|null $name The name of the node * @param NodeParentInterface|null $parent The parent */ public function __construct($name, NodeParentInterface $parent = null) From 028c9f23667ee02180a49b099bbf74f876cf0114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Tue, 6 Mar 2018 23:27:05 +0100 Subject: [PATCH 02/18] [DomCrawler] extract(): fix a bug when the attribute list is empty --- src/Symfony/Component/DomCrawler/Crawler.php | 2 +- src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index cccea633dd..a49bb3930a 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -605,7 +605,7 @@ class Crawler extends \SplObjectStorage } } - $data[] = $count > 1 ? $elements : $elements[0]; + $data[] = 1 === $count ? $elements[0] : $elements; } return $data; diff --git a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php index 3ba9247618..74acfdf8c6 100644 --- a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php @@ -369,6 +369,7 @@ EOF $this->assertEquals(array('One', 'Two', 'Three'), $crawler->extract('_text'), '->extract() returns an array of extracted data from the node list'); $this->assertEquals(array(array('One', 'first'), array('Two', ''), array('Three', '')), $crawler->extract(array('_text', 'class')), '->extract() returns an array of extracted data from the node list'); + $this->assertEquals(array(array(), array(), array()), $crawler->extract(array()), '->extract() returns empty arrays if the attribute list is empty'); $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->extract('_text'), '->extract() returns an empty array if the node list is empty'); } From 4d075da9347c693045e57130d5c92655996f1180 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 1 Mar 2018 14:58:28 +0100 Subject: [PATCH 03/18] [FrameworkBundle] HttpCache is not longer abstract --- .../Bundle/FrameworkBundle/HttpCache/HttpCache.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php index fa89292804..8455baafc7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php +++ b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\HttpCache; -use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\HttpKernel\HttpCache\HttpCache as BaseHttpCache; use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpKernel\HttpCache\Store; @@ -23,16 +23,16 @@ use Symfony\Component\HttpFoundation\Response; * * @author Fabien Potencier */ -abstract class HttpCache extends BaseHttpCache +class HttpCache extends BaseHttpCache { protected $cacheDir; protected $kernel; /** - * @param HttpKernelInterface $kernel An HttpKernelInterface instance - * @param string $cacheDir The cache directory (default used if null) + * @param KernelInterface $kernel A KernelInterface instance + * @param string $cacheDir The cache directory (default used if null) */ - public function __construct(HttpKernelInterface $kernel, $cacheDir = null) + public function __construct(KernelInterface $kernel, $cacheDir = null) { $this->kernel = $kernel; $this->cacheDir = $cacheDir; From c77d1428e8fb77faf8fbc4c6a71d1cd27063616e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 15 Mar 2018 17:07:34 +0100 Subject: [PATCH 04/18] [DomCrawler] Avoid a useless call to strtolower --- src/Symfony/Component/DomCrawler/Field/InputFormField.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Field/InputFormField.php b/src/Symfony/Component/DomCrawler/Field/InputFormField.php index 090913efa3..1c3c84d721 100644 --- a/src/Symfony/Component/DomCrawler/Field/InputFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/InputFormField.php @@ -32,11 +32,12 @@ class InputFormField extends FormField throw new \LogicException(sprintf('An InputFormField can only be created from an input or button tag (%s given).', $this->node->nodeName)); } - if ('checkbox' === strtolower($this->node->getAttribute('type'))) { + $type = strtolower($this->node->getAttribute('type')); + if ('checkbox' === $type) { throw new \LogicException('Checkboxes should be instances of ChoiceFormField.'); } - if ('file' === strtolower($this->node->getAttribute('type'))) { + if ('file' === $type) { throw new \LogicException('File inputs should be instances of FileFormField.'); } From 0c62f659fb2b3be9d7403505febf4d7952697c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 15 Mar 2018 17:51:38 +0100 Subject: [PATCH 05/18] [DomCrawler] Fix the PHPDoc of ChoiceFormField::setValue --- src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index c479daa75e..0553c54563 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -113,7 +113,7 @@ class ChoiceFormField extends FormField /** * Sets the value of the field. * - * @param string $value The value of the field + * @param string|array $value The value of the field * * @throws \InvalidArgumentException When value type provided is not correct */ From a4ec6d3c9c33ac4472615e049643a5bf882a3338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 15 Mar 2018 18:10:20 +0100 Subject: [PATCH 06/18] [DomCrawler] Change bad wording in ChoiceFormField::untick --- src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php index c479daa75e..ce22edc2db 100644 --- a/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/ChoiceFormField.php @@ -97,14 +97,14 @@ class ChoiceFormField extends FormField } /** - * Ticks a checkbox. + * Unticks a checkbox. * * @throws \LogicException When the type provided is not correct */ public function untick() { if ('checkbox' !== $this->type) { - throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); + throw new \LogicException(sprintf('You cannot untick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); } $this->setValue(false); From 4ac5d3c3159d1762f5715103c40ae4919c51e2e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 16 Mar 2018 16:11:23 +0100 Subject: [PATCH 07/18] [BrowserKit] Fix Cookie's PHPDoc --- src/Symfony/Component/BrowserKit/Cookie.php | 22 ++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php index e6159da74d..1afd8da5f8 100644 --- a/src/Symfony/Component/BrowserKit/Cookie.php +++ b/src/Symfony/Component/BrowserKit/Cookie.php @@ -44,14 +44,14 @@ class Cookie /** * Sets a cookie. * - * @param string $name The cookie name - * @param string $value The value of the cookie - * @param string $expires The time the cookie expires - * @param string $path The path on the server in which the cookie will be available on - * @param string $domain The domain that the cookie is available - * @param bool $secure Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client - * @param bool $httponly The cookie httponly flag - * @param bool $encodedValue Whether the value is encoded or not + * @param string $name The cookie name + * @param string $value The value of the cookie + * @param string|null $expires The time the cookie expires + * @param string|null $path The path on the server in which the cookie will be available on + * @param string $domain The domain that the cookie is available + * @param bool $secure Indicates that the cookie should only be transmitted over a secure HTTPS connection from the client + * @param bool $httponly The cookie httponly flag + * @param bool $encodedValue Whether the value is encoded or not */ public function __construct($name, $value, $expires = null, $path = null, $domain = '', $secure = false, $httponly = true, $encodedValue = false) { @@ -112,8 +112,8 @@ class Cookie /** * Creates a Cookie instance from a Set-Cookie header value. * - * @param string $cookie A Set-Cookie header value - * @param string $url The base URL + * @param string $cookie A Set-Cookie header value + * @param string|null $url The base URL * * @return static * @@ -242,7 +242,7 @@ class Cookie /** * Gets the expires time of the cookie. * - * @return string The cookie expires time + * @return string|null The cookie expires time */ public function getExpiresTime() { From 57993143a9a57ac39d846a2118e891464e971b3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 16 Mar 2018 17:11:50 +0100 Subject: [PATCH 08/18] [BrowserKit] Improves CookieJar::get --- src/Symfony/Component/BrowserKit/CookieJar.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/CookieJar.php b/src/Symfony/Component/BrowserKit/CookieJar.php index 232cefc8b6..faa8f6ec44 100644 --- a/src/Symfony/Component/BrowserKit/CookieJar.php +++ b/src/Symfony/Component/BrowserKit/CookieJar.php @@ -47,13 +47,13 @@ class CookieJar foreach ($this->cookieJar as $cookieDomain => $pathCookies) { if ($cookieDomain) { $cookieDomain = '.'.ltrim($cookieDomain, '.'); - if ($cookieDomain != substr('.'.$domain, -strlen($cookieDomain))) { + if ($cookieDomain !== substr('.'.$domain, -\strlen($cookieDomain))) { continue; } } foreach ($pathCookies as $cookiePath => $namedCookies) { - if ($cookiePath != substr($path, 0, strlen($cookiePath))) { + if (0 !== strpos($path, $cookiePath)) { continue; } if (isset($namedCookies[$name])) { From f656dc2082a12fdcc9033f9b4043b1ff316848a8 Mon Sep 17 00:00:00 2001 From: Thomas Calvet Date: Fri, 16 Mar 2018 17:35:29 +0100 Subject: [PATCH 09/18] [DoctrineBridge] Don't rely on ClassMetadataInfo->hasField in DoctrineOrmTypeGuesser anymore --- .../Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php | 6 +++--- .../Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php | 8 ++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index ebdcb02ca7..26079cd09f 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -95,7 +95,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface $classMetadata = $classMetadatas[0]; // Check whether the field exists and is nullable or not - if ($classMetadata->hasField($property)) { + if (isset($classMetadata->fieldMappings[$property])) { if (!$classMetadata->isNullable($property) && Type::BOOLEAN !== $classMetadata->getTypeOfField($property)) { return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } @@ -124,7 +124,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface public function guessMaxLength($class, $property) { $ret = $this->getMetadata($class); - if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) { + if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { $mapping = $ret[0]->getFieldMapping($property); if (isset($mapping['length'])) { @@ -143,7 +143,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface public function guessPattern($class, $property) { $ret = $this->getMetadata($class); - if ($ret && $ret[0]->hasField($property) && !$ret[0]->hasAssociation($property)) { + if ($ret && isset($ret[0]->fieldMappings[$property]) && !$ret[0]->hasAssociation($property)) { if (in_array($ret[0]->getTypeOfField($property), array(Type::DECIMAL, Type::FLOAT))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php index 12296729e2..0eda4a3ba6 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/DoctrineOrmTypeGuesserTest.php @@ -33,21 +33,20 @@ class DoctrineOrmTypeGuesserTest extends TestCase // Simple field, not nullable $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(true)); + $classMetadata->fieldMappings['field'] = true; $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(false)); $return[] = array($classMetadata, new ValueGuess(true, Guess::HIGH_CONFIDENCE)); // Simple field, nullable $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(true)); + $classMetadata->fieldMappings['field'] = true; $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(true)); $return[] = array($classMetadata, new ValueGuess(false, Guess::MEDIUM_CONFIDENCE)); // One-to-one, nullable (by default) $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true)); $mapping = array('joinColumns' => array(array())); @@ -57,7 +56,6 @@ class DoctrineOrmTypeGuesserTest extends TestCase // One-to-one, nullable (explicit) $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true)); $mapping = array('joinColumns' => array(array('nullable' => true))); @@ -67,7 +65,6 @@ class DoctrineOrmTypeGuesserTest extends TestCase // One-to-one, not nullable $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true)); $mapping = array('joinColumns' => array(array('nullable' => false))); @@ -77,7 +74,6 @@ class DoctrineOrmTypeGuesserTest extends TestCase // One-to-many, no clue $classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $classMetadata->expects($this->once())->method('hasField')->with('field')->will($this->returnValue(false)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(false)); $return[] = array($classMetadata, null); From acc20fc7553a941e03c85407c7f9536197708998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 16 Mar 2018 18:29:18 +0100 Subject: [PATCH 10/18] [BrowserKit] Fix cookie path handling when $domain is null --- .../Component/BrowserKit/CookieJar.php | 35 +++++++------------ .../BrowserKit/Tests/CookieJarTest.php | 2 ++ 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/CookieJar.php b/src/Symfony/Component/BrowserKit/CookieJar.php index faa8f6ec44..7a4d64c10e 100644 --- a/src/Symfony/Component/BrowserKit/CookieJar.php +++ b/src/Symfony/Component/BrowserKit/CookieJar.php @@ -43,32 +43,21 @@ class CookieJar { $this->flushExpiredCookies(); - if (!empty($domain)) { - foreach ($this->cookieJar as $cookieDomain => $pathCookies) { - if ($cookieDomain) { - $cookieDomain = '.'.ltrim($cookieDomain, '.'); - if ($cookieDomain !== substr('.'.$domain, -\strlen($cookieDomain))) { - continue; - } - } - - foreach ($pathCookies as $cookiePath => $namedCookies) { - if (0 !== strpos($path, $cookiePath)) { - continue; - } - if (isset($namedCookies[$name])) { - return $namedCookies[$name]; - } + foreach ($this->cookieJar as $cookieDomain => $pathCookies) { + if ($cookieDomain && $domain) { + $cookieDomain = '.'.ltrim($cookieDomain, '.'); + if ($cookieDomain !== substr('.'.$domain, -\strlen($cookieDomain))) { + continue; } } - return; - } - - // avoid relying on this behavior that is mainly here for BC reasons - foreach ($this->cookieJar as $cookies) { - if (isset($cookies[$path][$name])) { - return $cookies[$path][$name]; + foreach ($pathCookies as $cookiePath => $namedCookies) { + if (0 !== strpos($path, $cookiePath)) { + continue; + } + if (isset($namedCookies[$name])) { + return $namedCookies[$name]; + } } } } diff --git a/src/Symfony/Component/BrowserKit/Tests/CookieJarTest.php b/src/Symfony/Component/BrowserKit/Tests/CookieJarTest.php index 9c9e122e86..3117e5ce47 100644 --- a/src/Symfony/Component/BrowserKit/Tests/CookieJarTest.php +++ b/src/Symfony/Component/BrowserKit/Tests/CookieJarTest.php @@ -237,6 +237,8 @@ class CookieJarTest extends TestCase $this->assertEquals($cookie1, $cookieJar->get('foo', '/test', 'example.com')); $this->assertEquals($cookie2, $cookieJar->get('foo1', '/', 'example.com')); $this->assertEquals($cookie2, $cookieJar->get('foo1', '/bar', 'example.com')); + + $this->assertEquals($cookie2, $cookieJar->get('foo1', '/bar')); } public function testCookieWithWildcardDomain() From 44008c404703b6f0b4d6cd0440fd454a9016780b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Ostroluck=C3=BD?= Date: Sat, 17 Mar 2018 23:42:44 +0100 Subject: [PATCH 11/18] [Validator] Fix docblock of ClassMetadata#members Structure of this array is in reality >, so MemberMetadata is 2 levels deep in this array, instead of one --- src/Symfony/Component/Validator/Mapping/ClassMetadata.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index c79f1259e7..6472066c83 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -48,7 +48,7 @@ class ClassMetadata extends ElementMetadata implements ClassMetadataInterface public $defaultGroup; /** - * @var MemberMetadata[] + * @var MemberMetadata[][] * * @internal This property is public in order to reduce the size of the * class' serialized representation. Do not access it. Use From 986f9151fee81e6022a9203484131ab9755cba38 Mon Sep 17 00:00:00 2001 From: Florent Mata Date: Sat, 17 Mar 2018 16:10:21 +0100 Subject: [PATCH 12/18] add hint in Github pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 2d64894f41..94f0fabcc4 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,7 +4,7 @@ | Bug fix? | yes/no | New feature? | yes/no | BC breaks? | no -| Deprecations? | yes/no +| Deprecations? | yes/no | Tests pass? | yes | Fixed tickets | #... | License | MIT From f7e1bb05e24d4340e7bea42a6f2b0f4caa271f45 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 16 Mar 2018 17:37:42 +0100 Subject: [PATCH 13/18] [Debug] Reset previous exception handler ealier to prevent infinite loop --- src/Symfony/Component/Debug/ErrorHandler.php | 7 ++++--- .../Component/Debug/Tests/ErrorHandlerTest.php | 13 +++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 8875e03e84..e056862b8e 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -544,15 +544,16 @@ class ErrorHandler } } } + $exceptionHandler = $this->exceptionHandler; + $this->exceptionHandler = null; try { - if (null !== $this->exceptionHandler) { - return \call_user_func($this->exceptionHandler, $exception); + if (null !== $exceptionHandler) { + return \call_user_func($exceptionHandler, $exception); } $handlerException = $handlerException ?: $exception; } catch (\Exception $handlerException) { } catch (\Throwable $handlerException) { } - $this->exceptionHandler = null; if ($exception === $handlerException) { self::$reservedMemory = null; // Disable the fatal error handler throw $exception; // Give back $exception to the native handler diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index f2d0fc8b0b..18834badae 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -530,4 +530,17 @@ class ErrorHandlerTest extends TestCase throw $e; } } + + /** + * @expectedException \Exception + */ + public function testCustomExceptionHandler() + { + $handler = new ErrorHandler(); + $handler->setExceptionHandler(function ($e) use ($handler) { + $handler->handleException($e); + }); + + $handler->handleException(new \Exception()); + } } From 7a049769bfd8da96ed3015ea170cfe0499f3a201 Mon Sep 17 00:00:00 2001 From: temperatur <36632383+temperatur@users.noreply.github.com> Date: Mon, 19 Mar 2018 14:47:13 +0100 Subject: [PATCH 14/18] Fixes #26563 (open_basedir restriction in effect) If the open_basedir is set is_file(PHP_BINARY) is false. --- src/Symfony/Component/Process/PhpExecutableFinder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php index 4bc27fe4d4..9b3b0f4f68 100644 --- a/src/Symfony/Component/Process/PhpExecutableFinder.php +++ b/src/Symfony/Component/Process/PhpExecutableFinder.php @@ -44,7 +44,7 @@ class PhpExecutableFinder } // PHP_BINARY return the current sapi executable - if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) { + if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg'))) { return PHP_BINARY.$args; } From cc38c6bb62ad7ea4cf2f7840288f2640953fd321 Mon Sep 17 00:00:00 2001 From: Egor Gorbachev Date: Mon, 19 Mar 2018 20:40:47 +0300 Subject: [PATCH 15/18] Fix typo in test method name --- src/Symfony/Component/Config/Tests/ConfigCacheFactoryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheFactoryTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheFactoryTest.php index c523e5cd5e..24e3224ce5 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheFactoryTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheFactoryTest.php @@ -20,7 +20,7 @@ class ConfigCacheFactoryTest extends TestCase * @expectedException \InvalidArgumentException * @expectedExceptionMessage Invalid type for callback argument. Expected callable, but got "object". */ - public function testCachWithInvalidCallback() + public function testCacheWithInvalidCallback() { $cacheFactory = new ConfigCacheFactory(true); From ee47236a4c08c39ba5fb33ee9ff13bb838f3a4d9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 19 Mar 2018 19:37:04 +0100 Subject: [PATCH 16/18] [Debug] fix test --- src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 18834badae..4eb4aef0c0 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -533,6 +533,7 @@ class ErrorHandlerTest extends TestCase /** * @expectedException \Exception + * @group no-hhvm */ public function testCustomExceptionHandler() { From cb9c92d06553f60a0b7b6b036c4b2a3c1813e738 Mon Sep 17 00:00:00 2001 From: Boris Vujicic Date: Fri, 2 Mar 2018 09:14:52 +0100 Subject: [PATCH 17/18] [Security] added userChecker to SimpleAuthenticationProvider --- .../Security/Factory/SimpleFormFactory.php | 1 + .../Provider/SimpleAuthenticationProvider.php | 16 +++- .../SimpleAuthenticationProviderTest.php | 89 +++++++++++++++++++ 3 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php index 6241cf4f39..69b8b943ab 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/SimpleFormFactory.php @@ -55,6 +55,7 @@ class SimpleFormFactory extends FormLoginFactory ->replaceArgument(0, new Reference($config['authenticator'])) ->replaceArgument(1, new Reference($userProviderId)) ->replaceArgument(2, $id) + ->replaceArgument(3, new Reference('security.user_checker.'.$id)) ; return $provider; diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php index ffbc72c055..a82fb7eea4 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/SimpleAuthenticationProvider.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Security\Core\Authentication\Provider; +use Symfony\Component\Security\Core\User\UserChecker; +use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; @@ -24,23 +26,29 @@ class SimpleAuthenticationProvider implements AuthenticationProviderInterface private $simpleAuthenticator; private $userProvider; private $providerKey; + private $userChecker; - public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey) + public function __construct(SimpleAuthenticatorInterface $simpleAuthenticator, UserProviderInterface $userProvider, $providerKey, UserCheckerInterface $userChecker = null) { $this->simpleAuthenticator = $simpleAuthenticator; $this->userProvider = $userProvider; $this->providerKey = $providerKey; + $this->userChecker = $userChecker ?: new UserChecker(); } public function authenticate(TokenInterface $token) { $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); - if ($authToken instanceof TokenInterface) { - return $authToken; + if (!$authToken instanceof TokenInterface) { + throw new AuthenticationException('Simple authenticator failed to return an authenticated token.'); } - throw new AuthenticationException('Simple authenticator failed to return an authenticated token.'); + $user = $authToken->getUser(); + $this->userChecker->checkPreAuth($user); + $this->userChecker->checkPostAuth($user); + + return $authToken; } public function supports(TokenInterface $token) diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php new file mode 100644 index 0000000000..1e7069c1fa --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/Provider/SimpleAuthenticationProviderTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Tests\Authentication\Provider; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Security\Core\Exception\DisabledException; +use Symfony\Component\Security\Core\Authentication\Provider\SimpleAuthenticationProvider; +use Symfony\Component\Security\Core\Exception\LockedException; + +class SimpleAuthenticationProviderTest extends TestCase +{ + /** + * @expectedException \Symfony\Component\Security\Core\Exception\DisabledException + */ + public function testAuthenticateWhenPreChecksFails() + { + $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); + + $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $token->expects($this->any()) + ->method('getUser') + ->will($this->returnValue($user)); + + $userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock(); + $userChecker->expects($this->once()) + ->method('checkPreAuth') + ->will($this->throwException(new DisabledException())); + + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + $authenticator->expects($this->once()) + ->method('authenticateToken') + ->will($this->returnValue($token)); + + $provider = $this->getProvider($authenticator, null, $userChecker); + + $provider->authenticate($token); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\LockedException + */ + public function testAuthenticateWhenPostChecksFails() + { + $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); + + $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $token->expects($this->any()) + ->method('getUser') + ->will($this->returnValue($user)); + + $userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock(); + $userChecker->expects($this->once()) + ->method('checkPostAuth') + ->will($this->throwException(new LockedException())); + + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + $authenticator->expects($this->once()) + ->method('authenticateToken') + ->will($this->returnValue($token)); + + $provider = $this->getProvider($authenticator, null, $userChecker); + + $provider->authenticate($token); + } + + protected function getProvider($simpleAuthenticator = null, $userProvider = null, $userChecker = null, $key = 'test') + { + if (null === $userChecker) { + $userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock(); + } + if (null === $simpleAuthenticator) { + $simpleAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface')->getMock(); + } + if (null === $userProvider) { + $userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); + } + + return new SimpleAuthenticationProvider($simpleAuthenticator, $userProvider, $key, $userChecker); + } +} From 5c3e6a95b307e5065855daaf05ace19e09c81203 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Tue, 27 Feb 2018 16:54:37 +0100 Subject: [PATCH 18/18] [Config] Handle nullable node name + fix inheritdocs --- .../Component/Config/Definition/ArrayNode.php | 14 ++----- .../Component/Config/Definition/BaseNode.php | 38 ++++--------------- .../Builder/ArrayNodeDefinition.php | 18 ++------- .../Builder/ParentNodeDefinitionInterface.php | 23 +++++++++++ .../Config/Definition/NodeInterface.php | 16 +++++++- .../Config/Definition/PrototypedArrayNode.php | 8 +--- .../Config/Definition/VariableNode.php | 3 -- 7 files changed, 52 insertions(+), 68 deletions(-) diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index 2c2738ac4c..3ec00350a8 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -150,9 +150,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface } /** - * Sets the node Name. - * - * @param string $name The node's name + * {@inheritdoc} */ public function setName($name) { @@ -160,9 +158,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface } /** - * Checks if the node has a default value. - * - * @return bool + * {@inheritdoc} */ public function hasDefaultValue() { @@ -170,11 +166,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface } /** - * Retrieves the default value. - * - * @return array The default value - * - * @throws \RuntimeException if the node has no default value + * {@inheritdoc} */ public function getDefaultValue() { diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index 2e346d7907..63aac0874c 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -40,7 +40,7 @@ abstract class BaseNode implements NodeInterface */ public function __construct($name, NodeInterface $parent = null) { - if (false !== strpos($name, '.')) { + if (false !== strpos($name = (string) $name, '.')) { throw new \InvalidArgumentException('The name must not contain ".".'); } @@ -170,9 +170,7 @@ abstract class BaseNode implements NodeInterface } /** - * Checks if this node is required. - * - * @return bool + * {@inheritdoc} */ public function isRequired() { @@ -180,9 +178,7 @@ abstract class BaseNode implements NodeInterface } /** - * Returns the name of this node. - * - * @return string The Node's name + * {@inheritdoc} */ public function getName() { @@ -190,9 +186,7 @@ abstract class BaseNode implements NodeInterface } /** - * Retrieves the path of this node. - * - * @return string The Node's path + * {@inheritdoc} */ public function getPath() { @@ -206,14 +200,7 @@ abstract class BaseNode implements NodeInterface } /** - * Merges two values together. - * - * @param mixed $leftSide - * @param mixed $rightSide - * - * @return mixed The merged value - * - * @throws ForbiddenOverwriteException + * {@inheritdoc} */ final public function merge($leftSide, $rightSide) { @@ -233,11 +220,7 @@ abstract class BaseNode implements NodeInterface } /** - * Normalizes a value, applying all normalization closures. - * - * @param mixed $value Value to normalize - * - * @return mixed The normalized value + * {@inheritdoc} */ final public function normalize($value) { @@ -285,14 +268,7 @@ abstract class BaseNode implements NodeInterface } /** - * Finalizes a value, applying all finalization closures. - * - * @param mixed $value The value to finalize - * - * @return mixed The finalized value - * - * @throws Exception - * @throws InvalidConfigurationException + * {@inheritdoc} */ final public function finalize($value) { diff --git a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php index a0ad77edd0..bb751c237a 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php @@ -47,7 +47,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition } /** - * Sets a custom children builder. + * {@inheritdoc} */ public function setBuilder(NodeBuilder $builder) { @@ -55,9 +55,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition } /** - * Returns a builder to add children nodes. - * - * @return NodeBuilder + * {@inheritdoc} */ public function children() { @@ -306,17 +304,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition } /** - * Appends a node definition. - * - * $node = new ArrayNodeDefinition() - * ->children() - * ->scalarNode('foo')->end() - * ->scalarNode('baz')->end() - * ->end() - * ->append($this->getBarNodeDefinition()) - * ; - * - * @return $this + * {@inheritdoc} */ public function append(NodeDefinition $node) { diff --git a/src/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php b/src/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php index 575495bb68..1bf2ad4bf6 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php +++ b/src/Symfony/Component/Config/Definition/Builder/ParentNodeDefinitionInterface.php @@ -18,9 +18,32 @@ namespace Symfony\Component\Config\Definition\Builder; */ interface ParentNodeDefinitionInterface { + /** + * Returns a builder to add children nodes. + * + * @return NodeBuilder + */ public function children(); + /** + * Appends a node definition. + * + * Usage: + * + * $node = $parentNode + * ->children() + * ->scalarNode('foo')->end() + * ->scalarNode('baz')->end() + * ->append($this->getBarNodeDefinition()) + * ->end() + * ; + * + * @return $this + */ public function append(NodeDefinition $node); + /** + * Sets a custom children builder. + */ public function setBuilder(NodeBuilder $builder); } diff --git a/src/Symfony/Component/Config/Definition/NodeInterface.php b/src/Symfony/Component/Config/Definition/NodeInterface.php index b9bddc4938..45f1f681c1 100644 --- a/src/Symfony/Component/Config/Definition/NodeInterface.php +++ b/src/Symfony/Component/Config/Definition/NodeInterface.php @@ -11,6 +11,10 @@ namespace Symfony\Component\Config\Definition; +use Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException; +use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; +use Symfony\Component\Config\Definition\Exception\InvalidTypeException; + /** * Common Interface among all nodes. * @@ -59,11 +63,13 @@ interface NodeInterface public function getDefaultValue(); /** - * Normalizes the supplied value. + * Normalizes a value. * * @param mixed $value The value to normalize * * @return mixed The normalized value + * + * @throws InvalidTypeException if the value type is invalid */ public function normalize($value); @@ -73,7 +79,10 @@ interface NodeInterface * @param mixed $leftSide * @param mixed $rightSide * - * @return mixed The merged values + * @return mixed The merged value + * + * @throws ForbiddenOverwriteException if the configuration path cannot be overwritten + * @throws InvalidTypeException if the value type is invalid */ public function merge($leftSide, $rightSide); @@ -83,6 +92,9 @@ interface NodeInterface * @param mixed $value The value to finalize * * @return mixed The finalized value + * + * @throws InvalidTypeException if the value type is invalid + * @throws InvalidConfigurationException if the value is invalid configuration */ public function finalize($value); } diff --git a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php index 08f335a015..d377b73e6c 100644 --- a/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php +++ b/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php @@ -102,9 +102,7 @@ class PrototypedArrayNode extends ArrayNode } /** - * Checks if the node has a default value. - * - * @return bool + * {@inheritdoc} */ public function hasDefaultValue() { @@ -126,12 +124,10 @@ class PrototypedArrayNode extends ArrayNode } /** - * Retrieves the default value. + * {@inheritdoc} * * The default value could be either explicited or derived from the prototype * default value. - * - * @return array The default value */ public function getDefaultValue() { diff --git a/src/Symfony/Component/Config/Definition/VariableNode.php b/src/Symfony/Component/Config/Definition/VariableNode.php index a9c35284cd..0cd84c72bf 100644 --- a/src/Symfony/Component/Config/Definition/VariableNode.php +++ b/src/Symfony/Component/Config/Definition/VariableNode.php @@ -27,9 +27,6 @@ class VariableNode extends BaseNode implements PrototypeNodeInterface protected $defaultValue; protected $allowEmptyValue = true; - /** - * {@inheritdoc} - */ public function setDefaultValue($value) { $this->defaultValueSet = true;