Merge branch '3.3' into 3.4

* 3.3: (22 commits)
  [Routing] Fix resource miss
  [Security] Fixed auth provider authenticate() cannot return void
  declare argument type
  [FrameworkBundle][Serializer] Move normalizer/encoders definitions to xml file & remove unnecessary checks
  streamed response should return $this
  $isClientIpsVali is not used
  content can be a resource
  Adding the Form default theme files to be warmed up in Twig's cache
  Remove BC Break label from `NullDumper` class
  Username and password in basic auth are allowed to contain '.'
  Remove obsolete PHPDoc from UriSigner
  [Serializer] YamlEncoder: throw if the Yaml component isn't installed
  [Serializer] ObjectNormalizer: throw if PropertyAccess isn't installed
  [PropertyInfo] Add support for the iterable type
  pdo session fix
  Fixed pathinfo calculation for requests starting with a question mark.  - fix bad conflict resolving issue  - port symfony/symfony#21968 to 3.3+
  Fixed unsetting from loosely equal keys OrderedHashMap
  add DOMElement as return type in Crawler::getIterator to support foreach support in ide
  Fixed mistake in exception expectation
  [Debug] Fix same vendor detection in class loader
  ...
This commit is contained in:
Fabien Potencier 2017-10-20 11:48:32 -07:00
commit 1376b4becd
39 changed files with 248 additions and 112 deletions

View File

@ -84,7 +84,7 @@ DependencyInjection
* Autowiring services based on the types they implement is deprecated and won't be supported in version 4.0. Rename (or alias) your services to their FQCN id to make them autowirable.
* [BC BREAK] The `NullDumper` class has been made final
* The `NullDumper` class has been made final
* [BC BREAK] `_defaults` and `_instanceof` are now reserved service names in Yaml configurations. Please rename any services with that names.

View File

@ -69,16 +69,11 @@ use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Serializer\Encoder\CsvEncoder;
use Symfony\Component\Serializer\Encoder\DecoderInterface;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
use Symfony\Component\Serializer\Encoder\YamlEncoder;
use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Stopwatch\Stopwatch;
use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand;
@ -1533,39 +1528,6 @@ class FrameworkExtension extends Extension
*/
private function registerSerializerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
if (class_exists('Symfony\Component\Serializer\Normalizer\DataUriNormalizer')) {
// Run before serializer.normalizer.object
$definition = $container->register('serializer.normalizer.data_uri', DataUriNormalizer::class);
$definition->setPublic(false);
$definition->addTag('serializer.normalizer', array('priority' => -920));
}
if (class_exists('Symfony\Component\Serializer\Normalizer\DateTimeNormalizer')) {
// Run before serializer.normalizer.object
$definition = $container->register('serializer.normalizer.datetime', DateTimeNormalizer::class);
$definition->setPublic(false);
$definition->addTag('serializer.normalizer', array('priority' => -910));
}
if (class_exists('Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer')) {
// Run before serializer.normalizer.object
$definition = $container->register('serializer.normalizer.json_serializable', JsonSerializableNormalizer::class);
$definition->setPublic(false);
$definition->addTag('serializer.normalizer', array('priority' => -900));
}
if (class_exists(YamlEncoder::class) && defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) {
$definition = $container->register('serializer.encoder.yaml', YamlEncoder::class);
$definition->setPublic(false);
$definition->addTag('serializer.encoder');
}
if (class_exists(CsvEncoder::class)) {
$definition = $container->register('serializer.encoder.csv', CsvEncoder::class);
$definition->setPublic(false);
$definition->addTag('serializer.encoder');
}
$loader->load('serializer.xml');
if (!class_exists(DateIntervalNormalizer::class)) {
@ -1630,7 +1592,7 @@ class FrameworkExtension extends Extension
$container->getDefinition('serializer.mapping.class_metadata_factory')->replaceArgument(
1, new Reference($config['cache'])
);
} elseif (!$container->getParameter('kernel.debug') && class_exists(CacheClassMetadataFactory::class)) {
} elseif (!$container->getParameter('kernel.debug')) {
$cacheMetadataFactory = new Definition(
CacheClassMetadataFactory::class,
array(

View File

@ -30,6 +30,21 @@
<tag name="serializer.normalizer" priority="-915" />
</service>
<service id="serializer.normalizer.data_uri" class="Symfony\Component\Serializer\Normalizer\DataUriNormalizer">
<!-- Run before serializer.normalizer.object -->
<tag name="serializer.normalizer" priority="-920" />
</service>
<service id="serializer.normalizer.datetime" class="Symfony\Component\Serializer\Normalizer\DateTimeNormalizer">
<!-- Run before serializer.normalizer.object -->
<tag name="serializer.normalizer" priority="-910" />
</service>
<service id="serializer.normalizer.json_serializable" class="Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer">
<!-- Run before serializer.normalizer.object -->
<tag name="serializer.normalizer" priority="-900" />
</service>
<service id="serializer.normalizer.object" class="Symfony\Component\Serializer\Normalizer\ObjectNormalizer">
<argument type="service" id="serializer.mapping.class_metadata_factory" />
<argument>null</argument> <!-- name converter -->
@ -93,6 +108,14 @@
<tag name="serializer.encoder" />
</service>
<service id="serializer.encoder.yaml" class="Symfony\Component\Serializer\Encoder\YamlEncoder">
<tag name="serializer.encoder" />
</service>
<service id="serializer.encoder.csv" class="Symfony\Component\Serializer\Encoder\CsvEncoder">
<tag name="serializer.encoder" />
</service>
<!-- Name converter -->
<service id="serializer.name_converter.camel_case_to_snake_case" class="Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter" />

View File

@ -166,12 +166,11 @@ class ConfigurationTest extends TestCase
*/
public function testInvalidAssetsConfiguration(array $assetConfig, $expectedMessage)
{
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(
InvalidConfigurationException::class,
$expectedMessage
);
if (method_exists($this, 'expectExceptionMessage')) {
if (method_exists($this, 'expectException')) {
$this->expectException(InvalidConfigurationException::class);
$this->expectExceptionMessage($expectedMessage);
} else {
$this->setExpectedException(InvalidConfigurationException::class, $expectedMessage);
}
$processor = new Processor();

View File

@ -36,7 +36,6 @@ use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory;
use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader;
use Symfony\Component\Serializer\Mapping\Loader\YamlFileLoader;
use Symfony\Component\Serializer\Normalizer\DataUriNormalizer;
@ -764,10 +763,6 @@ abstract class FrameworkExtensionTest extends TestCase
public function testDataUriNormalizerRegistered()
{
if (!class_exists('Symfony\Component\Serializer\Normalizer\DataUriNormalizer')) {
$this->markTestSkipped('The DataUriNormalizer has been introduced in the Serializer Component version 3.1.');
}
$container = $this->createContainerFromFile('full');
$definition = $container->getDefinition('serializer.normalizer.data_uri');
@ -794,10 +789,6 @@ abstract class FrameworkExtensionTest extends TestCase
public function testDateTimeNormalizerRegistered()
{
if (!class_exists('Symfony\Component\Serializer\Normalizer\DateTimeNormalizer')) {
$this->markTestSkipped('The DateTimeNormalizer has been introduced in the Serializer Component version 3.1.');
}
$container = $this->createContainerFromFile('full');
$definition = $container->getDefinition('serializer.normalizer.datetime');
@ -809,10 +800,6 @@ abstract class FrameworkExtensionTest extends TestCase
public function testJsonSerializableNormalizerRegistered()
{
if (!class_exists('Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer')) {
$this->markTestSkipped('The JsonSerializableNormalizer has been introduced in the Serializer Component version 3.1.');
}
$container = $this->createContainerFromFile('full');
$definition = $container->getDefinition('serializer.normalizer.json_serializable');
@ -835,10 +822,6 @@ abstract class FrameworkExtensionTest extends TestCase
public function testSerializerCacheActivated()
{
if (!class_exists(CacheClassMetadataFactory::class) || !method_exists(XmlFileLoader::class, 'getMappedClasses') || !method_exists(YamlFileLoader::class, 'getMappedClasses')) {
$this->markTestSkipped('The Serializer default cache warmer has been introduced in the Serializer Component version 3.2.');
}
$container = $this->createContainerFromFile('serializer_enabled');
$this->assertTrue($container->hasDefinition('serializer.mapping.cache_class_metadata_factory'));

View File

@ -43,7 +43,14 @@ class ExtensionPass implements CompilerPassInterface
if ($container->has('form.extension')) {
$container->getDefinition('twig.extension.form')->addTag('twig.extension');
$reflClass = new \ReflectionClass('Symfony\Bridge\Twig\Extension\FormExtension');
$container->getDefinition('twig.loader.native_filesystem')->addMethodCall('addPath', array(dirname(dirname($reflClass->getFileName())).'/Resources/views/Form'));
$coreThemePath = dirname(dirname($reflClass->getFileName())).'/Resources/views/Form';
$container->getDefinition('twig.loader.native_filesystem')->addMethodCall('addPath', array($coreThemePath));
$paths = $container->getDefinition('twig.cache_warmer')->getArgument(2);
$paths[$coreThemePath] = null;
$container->getDefinition('twig.cache_warmer')->replaceArgument(2, $paths);
$container->getDefinition('twig.template_iterator')->replaceArgument(2, $paths);
}
if ($container->has('router')) {

View File

@ -113,6 +113,7 @@ class TwigExtension extends Extension
}
}
// paths are modified in ExtensionPass if forms are enabled
$container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']);
$container->getDefinition('twig.template_iterator')->replaceArgument(2, $config['paths']);

View File

@ -166,18 +166,11 @@ class DebugClassLoader
}
// Don't trigger deprecations for classes in the same vendor
if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) {
if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
$len = 0;
$ns = '';
} else {
switch ($ns = substr($name, 0, $len)) {
case 'Symfony\Bridge\\':
case 'Symfony\Bundle\\':
case 'Symfony\Component\\':
$ns = 'Symfony\\';
$len = strlen($ns);
break;
}
$ns = substr($name, 0, $len);
}
// Detect annotations on the class

View File

@ -1071,7 +1071,7 @@ class Crawler implements \Countable, \IteratorAggregate
}
/**
* @return \ArrayIterator
* @return \ArrayIterator|\DOMElement[]
*/
public function getIterator()
{

View File

@ -11,8 +11,8 @@
<target>Den uppladdade filen var för stor. Försök ladda upp en mindre fil.</target>
</trans-unit>
<trans-unit id="30">
<source>The CSRF token is invalid.</source>
<target>CSRF-symbolen är inte giltig.</target>
<source>The CSRF token is invalid. Please try to resubmit the form.</source>
<target>CSRF-elementet är inte giltigt. Försök att skicka formuläret igen.</target>
</trans-unit>
</body>
</file>

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Form\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\ButtonBuilder;
use Symfony\Component\Form\Exception\InvalidArgumentException;
/**
* @author Alexander Cheprasov <cheprasov.84@ya.ru>
@ -53,10 +54,12 @@ class ButtonBuilderTest extends TestCase
*/
public function testInvalidNames($name)
{
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(
'\Symfony\Component\Form\Exception\InvalidArgumentException',
'Buttons cannot have empty names.'
);
if (method_exists($this, 'expectException')) {
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Buttons cannot have empty names.');
} else {
$this->setExpectedException(InvalidArgumentException::class, 'Buttons cannot have empty names.');
}
new ButtonBuilder($name);
}
}

View File

@ -181,7 +181,12 @@ class DateIntervalToArrayTransformerTest extends DateIntervalTestCase
'minutes' => '',
'seconds' => '6',
);
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(TransformationFailedException::class, 'This amount of "minutes" is invalid');
if (method_exists($this, 'expectException')) {
$this->expectException(TransformationFailedException::class);
$this->expectExceptionMessage('This amount of "minutes" is invalid');
} else {
$this->setExpectedException(TransformationFailedException::class, 'This amount of "minutes" is invalid');
}
$transformer->reverseTransform($input);
}
@ -191,7 +196,12 @@ class DateIntervalToArrayTransformerTest extends DateIntervalTestCase
$input = array(
'invert' => '1',
);
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(TransformationFailedException::class, 'The value of "invert" must be boolean');
if (method_exists($this, 'expectException')) {
$this->expectException(TransformationFailedException::class);
$this->expectExceptionMessage('The value of "invert" must be boolean');
} else {
$this->setExpectedException(TransformationFailedException::class, 'The value of "invert" must be boolean');
}
$transformer->reverseTransform($input);
}

View File

@ -56,6 +56,15 @@ class OrderedHashMapTest extends TestCase
$this->assertSame(array(0 => 1, 'foo' => 2, 1 => 3), iterator_to_array($map));
}
public function testInsertLooselyEqualKeys()
{
$map = new OrderedHashMap();
$map['1 as a string'] = '1 as a string';
$map[1] = 1;
$this->assertSame(array('1 as a string' => '1 as a string', 1 => 1), iterator_to_array($map));
}
/**
* Updates should not change the position of an element, otherwise we could
* turn foreach loops into endless loops if they change the current
@ -111,6 +120,17 @@ class OrderedHashMapTest extends TestCase
$this->assertSame(array('second' => 2), iterator_to_array($map));
}
public function testUnsetFromLooselyEqualKeysHashMap()
{
$map = new OrderedHashMap();
$map['1 as a string'] = '1 as a string';
$map[1] = 1;
unset($map[1]);
$this->assertSame(array('1 as a string' => '1 as a string'), iterator_to_array($map));
}
public function testUnsetNonExistingSucceeds()
{
$map = new OrderedHashMap();

View File

@ -133,7 +133,7 @@ class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable
: 1 + (int) max($this->orderedKeys);
}
$this->orderedKeys[] = $key;
$this->orderedKeys[] = (string) $key;
}
$this->elements[$key] = $value;
@ -144,7 +144,7 @@ class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable
*/
public function offsetUnset($key)
{
if (false !== ($position = array_search($key, $this->orderedKeys))) {
if (false !== ($position = array_search((string) $key, $this->orderedKeys))) {
array_splice($this->orderedKeys, $position, 1);
unset($this->elements[$key]);

View File

@ -118,7 +118,13 @@ class OrderedHashMapIterator implements \Iterator
*/
public function key()
{
return $this->key;
if (null === $this->key) {
return null;
}
$array = array($this->key => null);
return key($array);
}
/**

View File

@ -153,7 +153,7 @@ class AcceptHeader
private function sort()
{
if (!$this->sorted) {
uasort($this->items, function ($a, $b) {
uasort($this->items, function (AcceptHeaderItem $a, AcceptHeaderItem $b) {
$qA = $a->getQuality();
$qB = $b->getQuality();

View File

@ -144,7 +144,7 @@ class Request
public $headers;
/**
* @var string
* @var string|resource
*/
protected $content;
@ -221,7 +221,6 @@ class Request
protected static $requestFactory;
private $isHostValid = true;
private $isClientIpsValid = true;
private $isForwardedValid = true;
private static $trustedHeaderSet = -1;
@ -1887,6 +1886,9 @@ class Request
// Does the baseUrl have anything in common with the request_uri?
$requestUri = $this->getRequestUri();
if ($requestUri !== '' && $requestUri[0] !== '/') {
$requestUri = '/'.$requestUri;
}
if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
// full $baseUrl matches
@ -1959,9 +1961,12 @@ class Request
}
// Remove the query string from REQUEST_URI
if ($pos = strpos($requestUri, '?')) {
if (false !== $pos = strpos($requestUri, '?')) {
$requestUri = substr($requestUri, 0, $pos);
}
if ($requestUri !== '' && $requestUri[0] !== '/') {
$requestUri = '/'.$requestUri;
}
$pathInfo = substr($requestUri, strlen($baseUrl));
if (null !== $baseUrl && (false === $pathInfo || '' === $pathInfo)) {

View File

@ -413,7 +413,7 @@ class PdoSessionHandler extends AbstractSessionHandler
$this->gcCalled = false;
// delete the session records that have expired
$sql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol < :time";
$sql = "DELETE FROM $this->table WHERE $this->lifetimeCol < :time - $this->timeCol";
$stmt = $this->pdo->prepare($sql);
$stmt->bindValue(':time', time(), \PDO::PARAM_INT);

View File

@ -84,7 +84,7 @@ class StreamedResponse extends Response
public function sendHeaders()
{
if ($this->headersSent) {
return;
return $this;
}
$this->headersSent = true;
@ -102,7 +102,7 @@ class StreamedResponse extends Response
public function sendContent()
{
if ($this->streamed) {
return;
return $this;
}
$this->streamed = true;

View File

@ -1286,6 +1286,12 @@ class RequestTest extends TestCase
$request->initialize(array(), array(), array(), array(), array(), $server);
$this->assertEquals('/path%20test/info', $request->getPathInfo());
$server = array();
$server['REQUEST_URI'] = '?a=b';
$request->initialize(array(), array(), array(), array(), array(), $server);
$this->assertEquals('/', $request->getPathInfo());
}
public function testGetParameterPrecedence()
@ -2218,6 +2224,61 @@ class RequestTest extends TestCase
'trusted with partially-broken via' => array('HTTP/2.0', true, '1.0 fred, foo', 'HTTP/1.0'),
);
}
public function nonstandardRequestsData()
{
return array(
array('', '', '/', 'http://host:8080/', ''),
array('/', '', '/', 'http://host:8080/', ''),
array('hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),
array('/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'),
array('', 'a=b', '/', 'http://host:8080/?a=b'),
array('?a=b', 'a=b', '/', 'http://host:8080/?a=b'),
array('/?a=b', 'a=b', '/', 'http://host:8080/?a=b'),
array('x', 'a=b', '/x', 'http://host:8080/x?a=b'),
array('x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),
array('/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'),
array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'),
array('hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
array('hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
array('/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'),
);
}
/**
* @dataProvider nonstandardRequestsData
*/
public function testNonstandardRequests($requestUri, $queryString, $expectedPathInfo, $expectedUri, $expectedBasePath = '', $expectedBaseUrl = null)
{
if (null === $expectedBaseUrl) {
$expectedBaseUrl = $expectedBasePath;
}
$server = array(
'HTTP_HOST' => 'host:8080',
'SERVER_PORT' => '8080',
'QUERY_STRING' => $queryString,
'PHP_SELF' => '/hello/app.php',
'SCRIPT_FILENAME' => '/some/path/app.php',
'REQUEST_URI' => $requestUri,
);
$request = new Request(array(), array(), array(), array(), array(), $server);
$this->assertEquals($expectedPathInfo, $request->getPathInfo());
$this->assertEquals($expectedUri, $request->getUri());
$this->assertEquals($queryString, $request->getQueryString());
$this->assertEquals(8080, $request->getPort());
$this->assertEquals('host:8080', $request->getHttpHost());
$this->assertEquals($expectedBaseUrl, $request->getBaseUrl());
$this->assertEquals($expectedBasePath, $request->getBasePath());
}
}
class RequestContentProxy extends Request

View File

@ -112,4 +112,15 @@ class StreamedResponseTest extends TestCase
$this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response);
$this->assertEquals(204, $response->getStatusCode());
}
public function testReturnThis()
{
$response = new StreamedResponse(function () {});
$this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response->sendContent());
$this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response->sendContent());
$response = new StreamedResponse(function () {});
$this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response->sendHeaders());
$this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response->sendHeaders());
}
}

View File

@ -58,10 +58,6 @@ class UriSigner
/**
* Checks that a URI contains the correct hash.
*
* The query string parameter must be the last one
* (as it is generated that way by the sign() method, it should
* never be a problem).
*
* @param string $uri A signed URI
*
* @return bool True if the URI is signed correctly, false otherwise

View File

@ -29,10 +29,12 @@ class ProcessFailedExceptionTest extends TestCase
->method('isSuccessful')
->will($this->returnValue(true));
$this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(
'\InvalidArgumentException',
'Expected a failed process, but the given process was successful.'
);
if (method_exists($this, 'expectException')) {
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Expected a failed process, but the given process was successful.');
} else {
$this->setExpectedException(\InvalidArgumentException::class, 'Expected a failed process, but the given process was successful.');
}
new ProcessFailedException($process);
}

View File

@ -37,6 +37,12 @@ class TypeTest extends TestCase
$this->assertEquals(Type::BUILTIN_TYPE_STRING, $collectionValueType->getBuiltinType());
}
public function testIterable()
{
$type = new Type('iterable');
$this->assertSame('iterable', $type->getBuiltinType());
}
/**
* @expectedException \InvalidArgumentException
* @expectedExceptionMessage "foo" is not a valid PHP type.

View File

@ -29,6 +29,7 @@ class Type
const BUILTIN_TYPE_ARRAY = 'array';
const BUILTIN_TYPE_NULL = 'null';
const BUILTIN_TYPE_CALLABLE = 'callable';
const BUILTIN_TYPE_ITERABLE = 'iterable';
/**
* List of PHP builtin types.
@ -45,6 +46,7 @@ class Type
self::BUILTIN_TYPE_ARRAY,
self::BUILTIN_TYPE_CALLABLE,
self::BUILTIN_TYPE_NULL,
self::BUILTIN_TYPE_ITERABLE,
);
/**
@ -104,7 +106,7 @@ class Type
/**
* Gets built-in type.
*
* Can be bool, int, float, string, array, object, resource, null or callback.
* Can be bool, int, float, string, array, object, resource, null, callback or iterable.
*
* @return string
*/

View File

@ -318,10 +318,10 @@ class RouteCollectionBuilder
$routeCollection->addCollection($subCollection);
}
}
foreach ($this->resources as $resource) {
$routeCollection->addResource($resource);
}
foreach ($this->resources as $resource) {
$routeCollection->addResource($resource);
}
return $routeCollection;

View File

@ -12,7 +12,9 @@
namespace Symfony\Component\Routing\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\Routing\Loader\YamlFileLoader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\RouteCollectionBuilder;
@ -59,7 +61,18 @@ class RouteCollectionBuilderTest extends TestCase
$this->assertCount(1, $addedCollection->getResources());
// make sure the routes were imported into the top-level builder
$routeCollection = $routes->build();
$this->assertCount(1, $routes->build());
$this->assertCount(1, $routeCollection->getResources());
}
public function testImportAddResources()
{
$routeCollectionBuilder = new RouteCollectionBuilder(new YamlFileLoader(new FileLocator(array(__DIR__.'/Fixtures/'))));
$routeCollectionBuilder->import('file_resource.yml');
$routeCollection = $routeCollectionBuilder->build();
$this->assertCount(1, $routeCollection->getResources());
}
/**

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\Security\Core\Authentication\Provider;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
@ -44,7 +45,7 @@ class AnonymousAuthenticationProvider implements AuthenticationProviderInterface
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
if ($this->secret !== $token->getSecret()) {

View File

@ -13,6 +13,7 @@ namespace Symfony\Component\Security\Core\Authentication\Provider;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
@ -51,7 +52,7 @@ class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderIn
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
if (!$user = $token->getUser()) {

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\Security\Core\Authentication\Provider;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
class RememberMeAuthenticationProvider implements AuthenticationProviderInterface
@ -40,7 +41,7 @@ class RememberMeAuthenticationProvider implements AuthenticationProviderInterfac
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
if ($this->secret !== $token->getSecret()) {
@ -49,6 +50,7 @@ class RememberMeAuthenticationProvider implements AuthenticationProviderInterfac
$user = $token->getUser();
$this->userChecker->checkPreAuth($user);
$this->userChecker->checkPostAuth($user);
$authenticatedToken = new RememberMeToken($user, $this->providerKey, $this->secret);
$authenticatedToken->setAttributes($token->getAttributes());

View File

@ -56,7 +56,7 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
throw new AuthenticationException('The token is not supported by this authentication provider.');
}
$username = $token->getUsername();

View File

@ -24,11 +24,15 @@ class AnonymousAuthenticationProviderTest extends TestCase
$this->assertFalse($provider->supports($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()));
}
/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
* @expectedExceptionMessage The token is not supported by this authentication provider.
*/
public function testAuthenticateWhenTokenIsNotSupported()
{
$provider = $this->getProvider('foo');
$this->assertNull($provider->authenticate($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()));
$provider->authenticate($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock());
}
/**

View File

@ -36,11 +36,15 @@ class PreAuthenticatedAuthenticationProviderTest extends TestCase
$this->assertFalse($provider->supports($token));
}
/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
* @expectedExceptionMessage The token is not supported by this authentication provider.
*/
public function testAuthenticateWhenTokenIsNotSupported()
{
$provider = $this->getProvider();
$this->assertNull($provider->authenticate($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()));
$provider->authenticate($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock());
}
/**

View File

@ -26,12 +26,16 @@ class RememberMeAuthenticationProviderTest extends TestCase
$this->assertFalse($provider->supports($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()));
}
/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
* @expectedExceptionMessage The token is not supported by this authentication provider.
*/
public function testAuthenticateWhenTokenIsNotSupported()
{
$provider = $this->getProvider();
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$this->assertNull($provider->authenticate($token));
$provider->authenticate($token);
}
/**

View File

@ -29,11 +29,15 @@ class UserAuthenticationProviderTest extends TestCase
$this->assertFalse($provider->supports($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()));
}
/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationException
* @expectedExceptionMessage The token is not supported by this authentication provider.
*/
public function testAuthenticateWhenTokenIsNotSupported()
{
$provider = $this->getProvider();
$this->assertNull($provider->authenticate($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock()));
$provider->authenticate($this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock());
}
/**

View File

@ -11,6 +11,7 @@
namespace Symfony\Component\Serializer\Encoder;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Yaml\Dumper;
use Symfony\Component\Yaml\Parser;
@ -29,6 +30,10 @@ class YamlEncoder implements EncoderInterface, DecoderInterface
public function __construct(Dumper $dumper = null, Parser $parser = null, array $defaultContext = array())
{
if (!class_exists(Dumper::class)) {
throw new RuntimeException('The YamlEncoder class requires the "Yaml" component. Install "symfony/yaml" to use it.');
}
$this->dumper = $dumper ?: new Dumper();
$this->parser = $parser ?: new Parser();
$this->defaultContext = array_merge($this->defaultContext, $defaultContext);

View File

@ -15,6 +15,7 @@ use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\Serializer\Exception\RuntimeException;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@ -32,6 +33,10 @@ class ObjectNormalizer extends AbstractObjectNormalizer
public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyAccessorInterface $propertyAccessor = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null)
{
if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) {
throw new RuntimeException('The ObjectNormalizer class requires the "PropertyAccess" component. Install "symfony/property-access" to use it.');
}
parent::__construct($classMetadataFactory, $nameConverter, $propertyTypeExtractor);
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor();

View File

@ -23,7 +23,7 @@ class UrlValidator extends ConstraintValidator
{
const PATTERN = '~^
(%s):// # protocol
(([\pL\pN-]+:)?([\pL\pN-]+)@)? # basic auth
(([\.\pL\pN-]+:)?([\.\pL\pN-]+)@)? # basic auth
(
([\pL\pN\pS-\.])+(\.?([\pL\pN]|xn\-\-[\pL\pN-]+)+\.?) # a domain name
| # or

View File

@ -116,6 +116,9 @@ class UrlValidatorTest extends ConstraintValidatorTestCase
array('http://xn--d1abbgf6aiiy.xn--p1ai/'),
array('http://☎.com/'),
array('http://username:password@symfony.com'),
array('http://user.name:password@symfony.com'),
array('http://username:pass.word@symfony.com'),
array('http://user.name:pass.word@symfony.com'),
array('http://user-name@symfony.com'),
array('http://symfony.com?'),
array('http://symfony.com?query=1'),