Merge branch '2.8' into 3.4

* 2.8: (29 commits)
  [Console] Fix docblock of DescriptorInterface::describe
  [Config] Handle nullable node name + fix inheritdocs
  [Security] added userChecker to SimpleAuthenticationProvider
  [Debug] fix test
  Fix typo in test method name
  Fixes #26563 (open_basedir restriction in effect)
  [Debug] Reset previous exception handler ealier to prevent infinite loop
  add hint in Github pull request template
  [Validator] Fix docblock of ClassMetadata#members
  [BrowserKit] Fix cookie path handling when $domain is null
  [DoctrineBridge] Don't rely on ClassMetadataInfo->hasField in DoctrineOrmTypeGuesser anymore
  [BrowserKit] Improves CookieJar::get
  [BrowserKit] Fix Cookie's PHPDoc
  [DomCrawler] Change bad wording in ChoiceFormField::untick
  [DomCrawler] Fix the PHPDoc of ChoiceFormField::setValue
  [DomCrawler] Avoid a useless call to strtolower
  [FrameworkBundle] HttpCache is not longer abstract
  Php Inspections (EA Ultimate): address some of one-time used local variables
  [Intl] Load locale aliases to support alias fallbacks
  [CssSelector] Fix CSS identifiers parsing - they can start with dash
  ...
This commit is contained in:
Nicolas Grekas 2018-03-19 23:32:39 +01:00
commit 34d5b5eb99
38 changed files with 333 additions and 160 deletions

View File

@ -4,7 +4,7 @@
| Bug fix? | yes/no | Bug fix? | yes/no
| New feature? | yes/no <!-- don't forget to update src/**/CHANGELOG.md files --> | New feature? | yes/no <!-- don't forget to update src/**/CHANGELOG.md files -->
| BC breaks? | no <!-- see https://symfony.com/bc --> | BC breaks? | no <!-- see https://symfony.com/bc -->
| Deprecations? | yes/no <!-- don't forget to update UPGRADE-*.md files --> | Deprecations? | yes/no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass? | yes <!-- please add some, will be required by reviewers --> | Tests pass? | yes <!-- please add some, will be required by reviewers -->
| Fixed tickets | #... <!-- #-prefixed issue number(s), if any --> | Fixed tickets | #... <!-- #-prefixed issue number(s), if any -->
| License | MIT | License | MIT

View File

@ -43,11 +43,11 @@ Symfony is the result of the work of many people who made the code better
- Diego Saint Esteben (dosten) - Diego Saint Esteben (dosten)
- Alexandre Salomé (alexandresalome) - Alexandre Salomé (alexandresalome)
- William Durand (couac) - William Durand (couac)
- Hamza Amrouche (simperfit)
- ornicar - ornicar
- Francis Besset (francisbesset) - Francis Besset (francisbesset)
- Iltar van der Berg (kjarli) - Iltar van der Berg (kjarli)
- stealth35 (stealth35) - stealth35 (stealth35)
- Hamza Amrouche (simperfit)
- Alexander Mols (asm89) - Alexander Mols (asm89)
- Yonel Ceruto (yonelceruto) - Yonel Ceruto (yonelceruto)
- Bulat Shakirzyanov (avalanche123) - Bulat Shakirzyanov (avalanche123)
@ -57,8 +57,8 @@ Symfony is the result of the work of many people who made the code better
- Henrik Bjørnskov (henrikbjorn) - Henrik Bjørnskov (henrikbjorn)
- Miha Vrhovnik - Miha Vrhovnik
- Diego Saint Esteben (dii3g0) - Diego Saint Esteben (dii3g0)
- Dany Maillard (maidmaid)
- Pierre du Plessis (pierredup) - Pierre du Plessis (pierredup)
- Dany Maillard (maidmaid)
- Konstantin Kudryashov (everzet) - Konstantin Kudryashov (everzet)
- Kevin Bond (kbond) - Kevin Bond (kbond)
- Bilal Amarni (bamarni) - Bilal Amarni (bamarni)
@ -66,6 +66,7 @@ Symfony is the result of the work of many people who made the code better
- Jérémy DERUSSÉ (jderusse) - Jérémy DERUSSÉ (jderusse)
- Florin Patan (florinpatan) - Florin Patan (florinpatan)
- Samuel ROZE (sroze) - Samuel ROZE (sroze)
- Tobias Nyholm (tobias)
- Gábor Egyed (1ed) - Gábor Egyed (1ed)
- Michel Weimerskirch (mweimerskirch) - Michel Weimerskirch (mweimerskirch)
- Andrej Hudec (pulzarraider) - Andrej Hudec (pulzarraider)
@ -75,7 +76,6 @@ Symfony is the result of the work of many people who made the code better
- Titouan Galopin (tgalopin) - Titouan Galopin (tgalopin)
- Konstantin Myakshin (koc) - Konstantin Myakshin (koc)
- Christian Raue - Christian Raue
- Tobias Nyholm (tobias)
- Arnout Boks (aboks) - Arnout Boks (aboks)
- Deni - Deni
- Henrik Westphal (snc) - Henrik Westphal (snc)
@ -200,6 +200,7 @@ Symfony is the result of the work of many people who made the code better
- Matthieu Bontemps (mbontemps) - Matthieu Bontemps (mbontemps)
- apetitpa - apetitpa
- Pierre Minnieur (pminnieur) - Pierre Minnieur (pminnieur)
- Jannik Zschiesche (apfelbox)
- fivestar - fivestar
- Dominique Bongiraud - Dominique Bongiraud
- Jeremy Livingston (jeremylivingston) - Jeremy Livingston (jeremylivingston)
@ -224,7 +225,6 @@ Symfony is the result of the work of many people who made the code better
- Marcel Beerta (mazen) - Marcel Beerta (mazen)
- gadelat (gadelat) - gadelat (gadelat)
- Loïc Faugeron - Loïc Faugeron
- Jannik Zschiesche (apfelbox)
- Hidde Wieringa (hiddewie) - Hidde Wieringa (hiddewie)
- Marco Pivetta (ocramius) - Marco Pivetta (ocramius)
- Rob Frawley 2nd (robfrawley) - Rob Frawley 2nd (robfrawley)
@ -697,6 +697,7 @@ Symfony is the result of the work of many people who made the code better
- Nykopol (nykopol) - Nykopol (nykopol)
- Jordan Deitch - Jordan Deitch
- Casper Valdemar Poulsen - Casper Valdemar Poulsen
- Remon van de Kamp
- Josiah (josiah) - Josiah (josiah)
- Joschi Kuphal - Joschi Kuphal
- John Bohn (jbohn) - John Bohn (jbohn)
@ -736,6 +737,7 @@ Symfony is the result of the work of many people who made the code better
- Adrien Lucas (adrienlucas) - Adrien Lucas (adrienlucas)
- Zhuravlev Alexander (scif) - Zhuravlev Alexander (scif)
- James Michael DuPont - James Michael DuPont
- Xavier HAUSHERR
- Tom Klingenberg - Tom Klingenberg
- Christopher Hall (mythmakr) - Christopher Hall (mythmakr)
- Patrick Dawkins (pjcdawkins) - Patrick Dawkins (pjcdawkins)
@ -1102,7 +1104,6 @@ Symfony is the result of the work of many people who made the code better
- Pierre Tachoire (krichprollsch) - Pierre Tachoire (krichprollsch)
- Marc J. Schmidt (marcjs) - Marc J. Schmidt (marcjs)
- Marco Jantke - Marco Jantke
- Remon van de Kamp
- Saem Ghani - Saem Ghani
- Clément LEFEBVRE - Clément LEFEBVRE
- Conrad Kleinespel - Conrad Kleinespel
@ -1225,7 +1226,6 @@ Symfony is the result of the work of many people who made the code better
- Sebastian Ionescu - Sebastian Ionescu
- Thomas Ploch - Thomas Ploch
- Simon Neidhold - Simon Neidhold
- Xavier HAUSHERR
- Valentin VALCIU - Valentin VALCIU
- Jeremiah VALERIE - Jeremiah VALERIE
- Kevin Dew - Kevin Dew
@ -1573,6 +1573,7 @@ Symfony is the result of the work of many people who made the code better
- Vladimir Chernyshev (volch) - Vladimir Chernyshev (volch)
- Yorkie Chadwick (yorkie76) - Yorkie Chadwick (yorkie76)
- GuillaumeVerdon - GuillaumeVerdon
- Philipp Keck
- Ondrej Mirtes - Ondrej Mirtes
- akimsko - akimsko
- Youpie - Youpie
@ -1630,6 +1631,7 @@ Symfony is the result of the work of many people who made the code better
- Jordan Hoff - Jordan Hoff
- znerol - znerol
- Christian Eikermann - Christian Eikermann
- Kai Eichinger
- Antonio Angelino - Antonio Angelino
- Matt Fields - Matt Fields
- Niklas Keller - Niklas Keller

View File

@ -97,7 +97,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
$classMetadata = $classMetadatas[0]; $classMetadata = $classMetadatas[0];
// Check whether the field exists and is nullable or not // 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)) { if (!$classMetadata->isNullable($property) && Type::BOOLEAN !== $classMetadata->getTypeOfField($property)) {
return new ValueGuess(true, Guess::HIGH_CONFIDENCE); return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
} }
@ -126,7 +126,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
public function guessMaxLength($class, $property) public function guessMaxLength($class, $property)
{ {
$ret = $this->getMetadata($class); $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); $mapping = $ret[0]->getFieldMapping($property);
if (isset($mapping['length'])) { if (isset($mapping['length'])) {
@ -145,7 +145,7 @@ class DoctrineOrmTypeGuesser implements FormTypeGuesserInterface
public function guessPattern($class, $property) public function guessPattern($class, $property)
{ {
$ret = $this->getMetadata($class); $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))) { if (in_array($ret[0]->getTypeOfField($property), array(Type::DECIMAL, Type::FLOAT))) {
return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE);
} }

View File

@ -33,21 +33,20 @@ class DoctrineOrmTypeGuesserTest extends TestCase
// Simple field, not nullable // Simple field, not nullable
$classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $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)); $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(false));
$return[] = array($classMetadata, new ValueGuess(true, Guess::HIGH_CONFIDENCE)); $return[] = array($classMetadata, new ValueGuess(true, Guess::HIGH_CONFIDENCE));
// Simple field, nullable // Simple field, nullable
$classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $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)); $classMetadata->expects($this->once())->method('isNullable')->with('field')->will($this->returnValue(true));
$return[] = array($classMetadata, new ValueGuess(false, Guess::MEDIUM_CONFIDENCE)); $return[] = array($classMetadata, new ValueGuess(false, Guess::MEDIUM_CONFIDENCE));
// One-to-one, nullable (by default) // One-to-one, nullable (by default)
$classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $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)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true));
$mapping = array('joinColumns' => array(array())); $mapping = array('joinColumns' => array(array()));
@ -57,7 +56,6 @@ class DoctrineOrmTypeGuesserTest extends TestCase
// One-to-one, nullable (explicit) // One-to-one, nullable (explicit)
$classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $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)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true));
$mapping = array('joinColumns' => array(array('nullable' => true))); $mapping = array('joinColumns' => array(array('nullable' => true)));
@ -67,7 +65,6 @@ class DoctrineOrmTypeGuesserTest extends TestCase
// One-to-one, not nullable // One-to-one, not nullable
$classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $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)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(true));
$mapping = array('joinColumns' => array(array('nullable' => false))); $mapping = array('joinColumns' => array(array('nullable' => false)));
@ -77,7 +74,6 @@ class DoctrineOrmTypeGuesserTest extends TestCase
// One-to-many, no clue // One-to-many, no clue
$classMetadata = $this->getMockBuilder('Doctrine\ORM\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); $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)); $classMetadata->expects($this->once())->method('isAssociationWithSingleJoinColumn')->with('field')->will($this->returnValue(false));
$return[] = array($classMetadata, null); $return[] = array($classMetadata, null);

View File

@ -54,8 +54,7 @@ class TwigExtractor extends AbstractFileExtractor implements ExtractorInterface
*/ */
public function extract($resource, MessageCatalogue $catalogue) public function extract($resource, MessageCatalogue $catalogue)
{ {
$files = $this->extractFiles($resource); foreach ($this->extractFiles($resource) as $file) {
foreach ($files as $file) {
try { try {
$this->extractTemplate(file_get_contents($file->getPathname()), $catalogue); $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue);
} catch (Error $e) { } catch (Error $e) {

View File

@ -11,7 +11,7 @@
namespace Symfony\Bundle\FrameworkBundle\HttpCache; 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\HttpCache as BaseHttpCache;
use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\HttpKernel\HttpCache\Store; use Symfony\Component\HttpKernel\HttpCache\Store;
@ -23,16 +23,16 @@ use Symfony\Component\HttpFoundation\Response;
* *
* @author Fabien Potencier <fabien@symfony.com> * @author Fabien Potencier <fabien@symfony.com>
*/ */
abstract class HttpCache extends BaseHttpCache class HttpCache extends BaseHttpCache
{ {
protected $cacheDir; protected $cacheDir;
protected $kernel; protected $kernel;
/** /**
* @param HttpKernelInterface $kernel An HttpKernelInterface instance * @param KernelInterface $kernel A KernelInterface instance
* @param string $cacheDir The cache directory (default used if null) * @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->kernel = $kernel;
$this->cacheDir = $cacheDir; $this->cacheDir = $cacheDir;

View File

@ -55,6 +55,7 @@ class SimpleFormFactory extends FormLoginFactory
->replaceArgument(0, new Reference($config['authenticator'])) ->replaceArgument(0, new Reference($config['authenticator']))
->replaceArgument(1, new Reference($userProviderId)) ->replaceArgument(1, new Reference($userProviderId))
->replaceArgument(2, $id) ->replaceArgument(2, $id)
->replaceArgument(3, new Reference('security.user_checker.'.$id))
; ;
return $provider; return $provider;

View File

@ -44,14 +44,14 @@ class Cookie
/** /**
* Sets a cookie. * Sets a cookie.
* *
* @param string $name The cookie name * @param string $name The cookie name
* @param string $value The value of the cookie * @param string $value The value of the cookie
* @param string $expires The time the cookie expires * @param string|null $expires The time the cookie expires
* @param string $path The path on the server in which the cookie will be available on * @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 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 $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 $httponly The cookie httponly flag
* @param bool $encodedValue Whether the value is encoded or not * @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) 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. * Creates a Cookie instance from a Set-Cookie header value.
* *
* @param string $cookie A Set-Cookie header value * @param string $cookie A Set-Cookie header value
* @param string $url The base URL * @param string|null $url The base URL
* *
* @return static * @return static
* *
@ -242,7 +242,7 @@ class Cookie
/** /**
* Gets the expires time of the cookie. * Gets the expires time of the cookie.
* *
* @return string The cookie expires time * @return string|null The cookie expires time
*/ */
public function getExpiresTime() public function getExpiresTime()
{ {

View File

@ -43,32 +43,21 @@ class CookieJar
{ {
$this->flushExpiredCookies(); $this->flushExpiredCookies();
if (!empty($domain)) { foreach ($this->cookieJar as $cookieDomain => $pathCookies) {
foreach ($this->cookieJar as $cookieDomain => $pathCookies) { if ($cookieDomain && $domain) {
if ($cookieDomain) { $cookieDomain = '.'.ltrim($cookieDomain, '.');
$cookieDomain = '.'.ltrim($cookieDomain, '.'); if ($cookieDomain !== substr('.'.$domain, -\strlen($cookieDomain))) {
if ($cookieDomain != substr('.'.$domain, -strlen($cookieDomain))) { continue;
continue;
}
}
foreach ($pathCookies as $cookiePath => $namedCookies) {
if ($cookiePath != substr($path, 0, strlen($cookiePath))) {
continue;
}
if (isset($namedCookies[$name])) {
return $namedCookies[$name];
}
} }
} }
return; foreach ($pathCookies as $cookiePath => $namedCookies) {
} if (0 !== strpos($path, $cookiePath)) {
continue;
// avoid relying on this behavior that is mainly here for BC reasons }
foreach ($this->cookieJar as $cookies) { if (isset($namedCookies[$name])) {
if (isset($cookies[$path][$name])) { return $namedCookies[$name];
return $cookies[$path][$name]; }
} }
} }
} }

View File

@ -237,6 +237,8 @@ class CookieJarTest extends TestCase
$this->assertEquals($cookie1, $cookieJar->get('foo', '/test', 'example.com')); $this->assertEquals($cookie1, $cookieJar->get('foo', '/test', 'example.com'));
$this->assertEquals($cookie2, $cookieJar->get('foo1', '/', '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', 'example.com'));
$this->assertEquals($cookie2, $cookieJar->get('foo1', '/bar'));
} }
public function testCookieWithWildcardDomain() public function testCookieWithWildcardDomain()

View File

@ -153,9 +153,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
} }
/** /**
* Sets the node Name. * {@inheritdoc}
*
* @param string $name The node's name
*/ */
public function setName($name) public function setName($name)
{ {
@ -163,9 +161,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
} }
/** /**
* Checks if the node has a default value. * {@inheritdoc}
*
* @return bool
*/ */
public function hasDefaultValue() public function hasDefaultValue()
{ {
@ -173,11 +169,7 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
} }
/** /**
* Retrieves the default value. * {@inheritdoc}
*
* @return array The default value
*
* @throws \RuntimeException if the node has no default value
*/ */
public function getDefaultValue() public function getDefaultValue()
{ {

View File

@ -34,14 +34,14 @@ abstract class BaseNode implements NodeInterface
protected $attributes = array(); protected $attributes = array();
/** /**
* @param string $name The name of the node * @param string|null $name The name of the node
* @param NodeInterface $parent The parent of this node * @param NodeInterface|null $parent The parent of this node
* *
* @throws \InvalidArgumentException if the name contains a period * @throws \InvalidArgumentException if the name contains a period
*/ */
public function __construct($name, NodeInterface $parent = null) 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 ".".'); throw new \InvalidArgumentException('The name must not contain ".".');
} }
@ -184,9 +184,7 @@ abstract class BaseNode implements NodeInterface
} }
/** /**
* Checks if this node is required. * {@inheritdoc}
*
* @return bool
*/ */
public function isRequired() public function isRequired()
{ {
@ -217,9 +215,7 @@ abstract class BaseNode implements NodeInterface
} }
/** /**
* Returns the name of this node. * {@inheritdoc}
*
* @return string The Node's name
*/ */
public function getName() public function getName()
{ {
@ -227,9 +223,7 @@ abstract class BaseNode implements NodeInterface
} }
/** /**
* Retrieves the path of this node. * {@inheritdoc}
*
* @return string The Node's path
*/ */
public function getPath() public function getPath()
{ {
@ -243,14 +237,7 @@ abstract class BaseNode implements NodeInterface
} }
/** /**
* Merges two values together. * {@inheritdoc}
*
* @param mixed $leftSide
* @param mixed $rightSide
*
* @return mixed The merged value
*
* @throws ForbiddenOverwriteException
*/ */
final public function merge($leftSide, $rightSide) final public function merge($leftSide, $rightSide)
{ {
@ -270,11 +257,7 @@ abstract class BaseNode implements NodeInterface
} }
/** /**
* Normalizes a value, applying all normalization closures. * {@inheritdoc}
*
* @param mixed $value Value to normalize
*
* @return mixed The normalized value
*/ */
final public function normalize($value) final public function normalize($value)
{ {
@ -322,14 +305,7 @@ abstract class BaseNode implements NodeInterface
} }
/** /**
* Finalizes a value, applying all finalization closures. * {@inheritdoc}
*
* @param mixed $value The value to finalize
*
* @return mixed The finalized value
*
* @throws Exception
* @throws InvalidConfigurationException
*/ */
final public function finalize($value) final public function finalize($value)
{ {

View File

@ -48,7 +48,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
} }
/** /**
* Sets a custom children builder. * {@inheritdoc}
*/ */
public function setBuilder(NodeBuilder $builder) public function setBuilder(NodeBuilder $builder)
{ {
@ -56,9 +56,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
} }
/** /**
* Returns a builder to add children nodes. * {@inheritdoc}
*
* @return NodeBuilder
*/ */
public function children() public function children()
{ {
@ -366,17 +364,7 @@ class ArrayNodeDefinition extends NodeDefinition implements ParentNodeDefinition
} }
/** /**
* Appends a node definition. * {@inheritdoc}
*
* $node = new ArrayNodeDefinition()
* ->children()
* ->scalarNode('foo')->end()
* ->scalarNode('baz')->end()
* ->end()
* ->append($this->getBarNodeDefinition())
* ;
*
* @return $this
*/ */
public function append(NodeDefinition $node) public function append(NodeDefinition $node)
{ {

View File

@ -143,8 +143,8 @@ class NodeBuilder implements NodeParentInterface
/** /**
* Creates a child node. * Creates a child node.
* *
* @param string $name The name of the node * @param string|null $name The name of the node
* @param string $type The type of the node * @param string $type The type of the node
* *
* @return NodeDefinition The child node * @return NodeDefinition The child node
* *

View File

@ -37,7 +37,7 @@ abstract class NodeDefinition implements NodeParentInterface
protected $attributes = array(); 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 * @param NodeParentInterface|null $parent The parent
*/ */
public function __construct($name, NodeParentInterface $parent = null) public function __construct($name, NodeParentInterface $parent = null)

View File

@ -18,9 +18,32 @@ namespace Symfony\Component\Config\Definition\Builder;
*/ */
interface ParentNodeDefinitionInterface interface ParentNodeDefinitionInterface
{ {
/**
* Returns a builder to add children nodes.
*
* @return NodeBuilder
*/
public function children(); 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); public function append(NodeDefinition $node);
/**
* Sets a custom children builder.
*/
public function setBuilder(NodeBuilder $builder); public function setBuilder(NodeBuilder $builder);
} }

View File

@ -11,6 +11,10 @@
namespace Symfony\Component\Config\Definition; 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. * Common Interface among all nodes.
* *
@ -59,11 +63,13 @@ interface NodeInterface
public function getDefaultValue(); public function getDefaultValue();
/** /**
* Normalizes the supplied value. * Normalizes a value.
* *
* @param mixed $value The value to normalize * @param mixed $value The value to normalize
* *
* @return mixed The normalized value * @return mixed The normalized value
*
* @throws InvalidTypeException if the value type is invalid
*/ */
public function normalize($value); public function normalize($value);
@ -73,7 +79,10 @@ interface NodeInterface
* @param mixed $leftSide * @param mixed $leftSide
* @param mixed $rightSide * @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); public function merge($leftSide, $rightSide);
@ -83,6 +92,9 @@ interface NodeInterface
* @param mixed $value The value to finalize * @param mixed $value The value to finalize
* *
* @return mixed The finalized value * @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); public function finalize($value);
} }

View File

@ -102,9 +102,7 @@ class PrototypedArrayNode extends ArrayNode
} }
/** /**
* Checks if the node has a default value. * {@inheritdoc}
*
* @return bool
*/ */
public function hasDefaultValue() 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 * The default value could be either explicited or derived from the prototype
* default value. * default value.
*
* @return array The default value
*/ */
public function getDefaultValue() public function getDefaultValue()
{ {

View File

@ -27,9 +27,6 @@ class VariableNode extends BaseNode implements PrototypeNodeInterface
protected $defaultValue; protected $defaultValue;
protected $allowEmptyValue = true; protected $allowEmptyValue = true;
/**
* {@inheritdoc}
*/
public function setDefaultValue($value) public function setDefaultValue($value)
{ {
$this->defaultValueSet = true; $this->defaultValueSet = true;

View File

@ -20,7 +20,7 @@ class ConfigCacheFactoryTest extends TestCase
* @expectedException \InvalidArgumentException * @expectedException \InvalidArgumentException
* @expectedExceptionMessage Invalid type for callback argument. Expected callable, but got "object". * @expectedExceptionMessage Invalid type for callback argument. Expected callable, but got "object".
*/ */
public function testCachWithInvalidCallback() public function testCacheWithInvalidCallback()
{ {
$cacheFactory = new ConfigCacheFactory(true); $cacheFactory = new ConfigCacheFactory(true);

View File

@ -21,7 +21,7 @@ use Symfony\Component\Console\Output\OutputInterface;
interface DescriptorInterface interface DescriptorInterface
{ {
/** /**
* Describes an InputArgument instance. * Describes an object if supported.
* *
* @param OutputInterface $output * @param OutputInterface $output
* @param object $object * @param object $object

View File

@ -46,7 +46,7 @@ class TokenizerPatterns
$this->nonAsciiPattern = '[^\x00-\x7F]'; $this->nonAsciiPattern = '[^\x00-\x7F]';
$this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->nmCharPattern = '[_a-z0-9-]|'.$this->escapePattern.'|'.$this->nonAsciiPattern;
$this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern; $this->nmStartPattern = '[_a-z]|'.$this->escapePattern.'|'.$this->nonAsciiPattern;
$this->identifierPattern = '(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*'; $this->identifierPattern = '-?(?:'.$this->nmStartPattern.')(?:'.$this->nmCharPattern.')*';
$this->hashPattern = '#((?:'.$this->nmCharPattern.')+)'; $this->hashPattern = '#((?:'.$this->nmCharPattern.')+)';
$this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)'; $this->numberPattern = '[+-]?(?:[0-9]*\.[0-9]+|[0-9]+)';
$this->quotedStringPattern = '([^\n\r\f%s]|'.$this->stringEscapePattern.')*'; $this->quotedStringPattern = '([^\n\r\f%s]|'.$this->stringEscapePattern.')*';

View File

@ -186,6 +186,7 @@ class ParserTest extends TestCase
array('foo:after', 'Element[foo]', 'after'), array('foo:after', 'Element[foo]', 'after'),
array('foo::selection', 'Element[foo]', 'selection'), array('foo::selection', 'Element[foo]', 'selection'),
array('lorem#ipsum ~ a#b.c[href]:empty::selection', 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ Pseudo[Attribute[Class[Hash[Element[a]#b].c][href]]:empty]]', 'selection'), array('lorem#ipsum ~ a#b.c[href]:empty::selection', 'CombinedSelector[Hash[Element[lorem]#ipsum] ~ Pseudo[Attribute[Class[Hash[Element[a]#b].c][href]]:empty]]', 'selection'),
array('video::-webkit-media-controls', 'Element[video]', '-webkit-media-controls'),
); );
} }

View File

@ -579,15 +579,16 @@ class ErrorHandler
} }
} }
} }
$exceptionHandler = $this->exceptionHandler;
$this->exceptionHandler = null;
try { try {
if (null !== $this->exceptionHandler) { if (null !== $exceptionHandler) {
return \call_user_func($this->exceptionHandler, $exception); return \call_user_func($exceptionHandler, $exception);
} }
$handlerException = $handlerException ?: $exception; $handlerException = $handlerException ?: $exception;
} catch (\Exception $handlerException) { } catch (\Exception $handlerException) {
} catch (\Throwable $handlerException) { } catch (\Throwable $handlerException) {
} }
$this->exceptionHandler = null;
if ($exception === $handlerException) { if ($exception === $handlerException) {
self::$reservedMemory = null; // Disable the fatal error handler self::$reservedMemory = null; // Disable the fatal error handler
throw $exception; // Give back $exception to the native handler throw $exception; // Give back $exception to the native handler

View File

@ -545,4 +545,18 @@ class ErrorHandlerTest extends TestCase
restore_exception_handler(); restore_exception_handler();
} }
} }
/**
* @expectedException \Exception
* @group no-hhvm
*/
public function testCustomExceptionHandler()
{
$handler = new ErrorHandler();
$handler->setExceptionHandler(function ($e) use ($handler) {
$handler->handleException($e);
});
$handler->handleException(new \Exception());
}
} }

View File

@ -648,7 +648,7 @@ class Crawler implements \Countable, \IteratorAggregate
} }
} }
$data[] = $count > 1 ? $elements : $elements[0]; $data[] = 1 === $count ? $elements[0] : $elements;
} }
return $data; return $data;

View File

@ -97,14 +97,14 @@ class ChoiceFormField extends FormField
} }
/** /**
* Ticks a checkbox. * Unticks a checkbox.
* *
* @throws \LogicException When the type provided is not correct * @throws \LogicException When the type provided is not correct
*/ */
public function untick() public function untick()
{ {
if ('checkbox' !== $this->type) { 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); $this->setValue(false);
@ -113,7 +113,7 @@ class ChoiceFormField extends FormField
/** /**
* Sets the value of the field. * 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 * @throws \InvalidArgumentException When value type provided is not correct
*/ */

View File

@ -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)); 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.'); 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.'); throw new \LogicException('File inputs should be instances of FileFormField.');
} }

View File

@ -413,6 +413,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('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('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'); $this->assertEquals(array(), $this->createTestCrawler()->filterXPath('//ol')->extract('_text'), '->extract() returns an empty array if the node list is empty');
} }

View File

@ -80,6 +80,7 @@ class FormType extends BaseType
} }
} }
$formConfig = $form->getConfig();
$view->vars = array_replace($view->vars, array( $view->vars = array_replace($view->vars, array(
'errors' => $form->getErrors(), 'errors' => $form->getErrors(),
'valid' => $form->isSubmitted() ? $form->isValid() : true, 'valid' => $form->isSubmitted() ? $form->isValid() : true,
@ -88,9 +89,9 @@ class FormType extends BaseType
'required' => $form->isRequired(), 'required' => $form->isRequired(),
'size' => null, 'size' => null,
'label_attr' => $options['label_attr'], 'label_attr' => $options['label_attr'],
'compound' => $form->getConfig()->getCompound(), 'compound' => $formConfig->getCompound(),
'method' => $form->getConfig()->getMethod(), 'method' => $formConfig->getMethod(),
'action' => $form->getConfig()->getAction(), 'action' => $formConfig->getAction(),
'submitted' => $form->isSubmitted(), 'submitted' => $form->isSubmitted(),
)); ));
} }

View File

@ -52,9 +52,7 @@ class ValidationListener implements EventSubscriberInterface
if ($form->isRoot()) { if ($form->isRoot()) {
// Validate the form in group "Default" // Validate the form in group "Default"
$violations = $this->validator->validate($form); foreach ($this->validator->validate($form) as $violation) {
foreach ($violations as $violation) {
// Allow the "invalid" constraint to be put onto // Allow the "invalid" constraint to be put onto
// non-synchronized forms // non-synchronized forms
// ConstraintViolation::getConstraint() must not expect to provide a constraint as long as Symfony\Component\Validator\ExecutionContext exists (before 3.0) // ConstraintViolation::getConstraint() must not expect to provide a constraint as long as Symfony\Component\Validator\ExecutionContext exists (before 3.0)

View File

@ -253,12 +253,8 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
$classMetadata = $this->metadataFactory->getMetadataFor($class); $classMetadata = $this->metadataFactory->getMetadataFor($class);
if ($classMetadata instanceof ClassMetadataInterface && $classMetadata->hasPropertyMetadata($property)) { if ($classMetadata instanceof ClassMetadataInterface && $classMetadata->hasPropertyMetadata($property)) {
$memberMetadatas = $classMetadata->getPropertyMetadata($property); foreach ($classMetadata->getPropertyMetadata($property) as $memberMetadata) {
foreach ($memberMetadata->getConstraints() as $constraint) {
foreach ($memberMetadatas as $memberMetadata) {
$constraints = $memberMetadata->getConstraints();
foreach ($constraints as $constraint) {
if ($guess = $closure($constraint)) { if ($guess = $closure($constraint)) {
$guesses[] = $guess; $guesses[] = $guess;
} }

View File

@ -15,6 +15,7 @@ use Symfony\Component\Intl\Data\Bundle\Reader\JsonBundleReader;
use Symfony\Component\Intl\Data\Bundle\Reader\BufferedBundleReader; use Symfony\Component\Intl\Data\Bundle\Reader\BufferedBundleReader;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReader; use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReader;
use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface; use Symfony\Component\Intl\Data\Bundle\Reader\BundleEntryReaderInterface;
use Symfony\Component\Intl\Data\Provider\LocaleDataProvider;
use Symfony\Component\Intl\Data\Provider\ScriptDataProvider; use Symfony\Component\Intl\Data\Provider\ScriptDataProvider;
use Symfony\Component\Intl\ResourceBundle\CurrencyBundle; use Symfony\Component\Intl\ResourceBundle\CurrencyBundle;
use Symfony\Component\Intl\ResourceBundle\CurrencyBundleInterface; use Symfony\Component\Intl\ResourceBundle\CurrencyBundleInterface;
@ -259,6 +260,11 @@ final class Intl
new JsonBundleReader(), new JsonBundleReader(),
self::BUFFER_SIZE self::BUFFER_SIZE
)); ));
$localeDataProvider = new LocaleDataProvider(
self::getDataDirectory().'/'.self::LOCALE_DIR,
self::$entryReader
);
self::$entryReader->setLocaleAliases($localeDataProvider->getAliases());
} }
return self::$entryReader; return self::$entryReader;

View File

@ -0,0 +1,84 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Intl\Tests;
use Symfony\Component\Intl\Intl;
use PHPUnit\Framework\TestCase;
class IntlTest extends TestCase
{
/**
* @requires extension intl
*/
public function testIsExtensionLoadedChecksIfIntlExtensionIsLoaded()
{
$this->assertTrue(Intl::isExtensionLoaded());
}
public function testGetCurrencyBundleCreatesTheCurrencyBundle()
{
$this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\CurrencyBundleInterface', Intl::getCurrencyBundle());
}
public function testGetLanguageBundleCreatesTheLanguageBundle()
{
$this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\LanguageBundleInterface', Intl::getLanguageBundle());
}
public function testGetLocaleBundleCreatesTheLocaleBundle()
{
$this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\LocaleBundleInterface', Intl::getLocaleBundle());
}
public function testGetRegionBundleCreatesTheRegionBundle()
{
$this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\LocaleBundleInterface', Intl::getLocaleBundle());
}
public function testGetIcuVersionReadsTheVersionOfInstalledIcuLibrary()
{
$this->assertStringMatchesFormat('%d.%d', Intl::getIcuVersion());
}
public function testGetIcuDataVersionReadsTheVersionOfInstalledIcuData()
{
$this->assertStringMatchesFormat('%d.%d', Intl::getIcuDataVersion());
}
public function testGetIcuStubVersionReadsTheVersionOfBundledStubs()
{
$this->assertStringMatchesFormat('%d.%d', Intl::getIcuStubVersion());
}
public function testGetDataDirectoryReturnsThePathToIcuData()
{
$this->assertTrue(is_dir(Intl::getDataDirectory()));
}
/**
* @requires extension intl
*/
public function testLocaleAliasesAreLoaded()
{
\Locale::setDefault('zh_TW');
$countryNameZhTw = Intl::getRegionBundle()->getCountryName('AD');
\Locale::setDefault('zh_Hant_TW');
$countryNameHantZhTw = Intl::getRegionBundle()->getCountryName('AD');
\Locale::setDefault('zh');
$countryNameZh = Intl::getRegionBundle()->getCountryName('AD');
$this->assertSame($countryNameZhTw, $countryNameHantZhTw, 'zh_TW is an alias to zh_Hant_TW');
$this->assertNotSame($countryNameZh, $countryNameZhTw, 'zh_TW does not fall back to zh');
}
}

View File

@ -44,7 +44,7 @@ class PhpExecutableFinder
} }
// PHP_BINARY return the current sapi executable // PHP_BINARY return the current sapi executable
if (PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) { if (PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg'))) {
return PHP_BINARY.$args; return PHP_BINARY.$args;
} }

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Core\Authentication\Provider; 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\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface; use Symfony\Component\Security\Core\Authentication\SimpleAuthenticatorInterface;
@ -24,23 +26,29 @@ class SimpleAuthenticationProvider implements AuthenticationProviderInterface
private $simpleAuthenticator; private $simpleAuthenticator;
private $userProvider; private $userProvider;
private $providerKey; 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->simpleAuthenticator = $simpleAuthenticator;
$this->userProvider = $userProvider; $this->userProvider = $userProvider;
$this->providerKey = $providerKey; $this->providerKey = $providerKey;
$this->userChecker = $userChecker ?: new UserChecker();
} }
public function authenticate(TokenInterface $token) public function authenticate(TokenInterface $token)
{ {
$authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey); $authToken = $this->simpleAuthenticator->authenticateToken($token, $this->userProvider, $this->providerKey);
if ($authToken instanceof TokenInterface) { if (!$authToken instanceof TokenInterface) {
return $authToken; 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) public function supports(TokenInterface $token)

View File

@ -0,0 +1,89 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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);
}
}

View File

@ -47,7 +47,7 @@ class ClassMetadata extends GenericMetadata implements ClassMetadataInterface
public $defaultGroup; public $defaultGroup;
/** /**
* @var MemberMetadata[] * @var MemberMetadata[][]
* *
* @internal This property is public in order to reduce the size of the * @internal This property is public in order to reduce the size of the
* class' serialized representation. Do not access it. Use * class' serialized representation. Do not access it. Use