Merge branch '2.7' into 2.8

* 2.7:
  [travis] Disable hirak/prestissimo for deps=low/high tests
  [HttpFoundation] fix phpdoc of UploadedFile
  Lower complexity of Form:isValid()
  skipped dns-sensitive tests when DnsMock is not found
  [FrameworkBundle] Return the invokable service if its name is the class name
  [ci] Skip dns-sensitive tests when DnsMock is not found
  Exclude Bridge\PhpUnit from composer.json by default
  fixed CS
  Optimize ReplaceAliasByActualDefinitionPass
  [Process] use __METHOD__ where applicable
  [Routing] Don't needlessly execute strtr's as they are fairly expensive
This commit is contained in:
Nicolas Grekas 2016-04-02 09:57:47 +02:00
commit e7d7e1ee38
15 changed files with 194 additions and 144 deletions

View File

@ -1,6 +1,5 @@
{ {
"require": { "require": {
"php": ">=5.3.7", "hirak/prestissimo": "^0.1.18"
"hirak/prestissimo": "^0.1.15"
} }
} }

View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "aa7aa2d143fd85800595242996021ada", "hash": "e02685ff7d2409d34fa87e306fc86ec5",
"content-hash": "51e9161b78dda1fe149a9e9c106be90b", "content-hash": "2854c05c76a78113c693dbbdd3f9c518",
"packages": [ "packages": [
{ {
"name": "hirak/prestissimo", "name": "hirak/prestissimo",
@ -65,8 +65,6 @@
"stability-flags": [], "stability-flags": [],
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": [],
"php": ">=5.3.7"
},
"platform-dev": [] "platform-dev": []
} }

View File

@ -35,44 +35,46 @@ cache:
services: mongodb services: mongodb
before_install: before_install:
- PHP=$TRAVIS_PHP_VERSION
# Matrix lines for intermediate PHP versions are skipped for pull requests # Matrix lines for intermediate PHP versions are skipped for pull requests
- if [[ ! $deps && ! $TRAVIS_PHP_VERSION = ${MIN_PHP%.*} && $TRAVIS_PHP_VERSION != hhvm && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip; fi; - if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && $PHP != hhvm && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip; skip=1; fi
# A sigchild-enabled-PHP is used to test the Process component on the lowest PHP matrix line # A sigchild-enabled-PHP is used to test the Process component on the lowest PHP matrix line
- if [[ ! $deps && $TRAVIS_PHP_VERSION = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then wget http://museum.php.net/php5/php-$MIN_PHP.tar.bz2 -O - | tar -xj; (cd php-$MIN_PHP; ./configure --enable-sigchild --enable-pcntl; make -j2); fi; - if [[ ! $deps && $PHP = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then wget http://museum.php.net/php5/php-$MIN_PHP.tar.bz2 -O - | tar -xj; (cd php-$MIN_PHP; ./configure --enable-sigchild --enable-pcntl; make -j2); fi
- if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi; - if [[ $PHP != hhvm ]]; then INI_FILE=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; else INI_FILE=/etc/hhvm/php.ini; fi
- echo memory_limit = -1 >> $INI_FILE - if [[ ! $skip ]]; then echo memory_limit = -1 >> $INI_FILE; fi
- echo session.gc_probability = 0 >> $INI_FILE - if [[ ! $skip ]]; then echo session.gc_probability = 0 >> $INI_FILE; fi
- if [[ $TRAVIS_PHP_VERSION = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi; - if [[ ! $skip && $PHP = 5.* ]]; then echo extension = mongo.so >> $INI_FILE; fi
- if [[ $TRAVIS_PHP_VERSION = 5.* ]]; then echo extension = memcache.so >> $INI_FILE; fi; - if [[ ! $skip && $PHP = 5.* ]]; then echo extension = memcache.so >> $INI_FILE; fi
- if [[ $TRAVIS_PHP_VERSION = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.10 && echo apc.enable_cli = 1 >> $INI_FILE); fi; - if [[ ! $skip && $PHP = 5.* ]]; then (echo yes | pecl install -f apcu-4.0.10 && echo apc.enable_cli = 1 >> $INI_FILE); fi
- if [[ $TRAVIS_PHP_VERSION = 7.* ]]; then (echo yes | pecl install -f apcu-5.1.2 && echo apc.enable_cli = 1 >> $INI_FILE); fi; - if [[ ! $skip && $PHP = 7.* ]]; then (echo yes | pecl install -f apcu-5.1.2 && echo apc.enable_cli = 1 >> $INI_FILE); fi
- if [[ $TRAVIS_PHP_VERSION = 5.* && ! $deps ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> $INI_FILE); fi; - if [[ ! $deps && $PHP = 5.* ]]; then (cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> $INI_FILE); fi
- if [[ $TRAVIS_PHP_VERSION = 5.* ]]; then pecl install -f memcached-2.1.0; fi; - if [[ ! $skip && $PHP = 5.* ]]; then pecl install -f memcached-2.1.0; fi
- if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then echo extension = ldap.so >> $INI_FILE; fi; - if [[ ! $skip && $PHP != hhvm ]]; then echo extension = ldap.so >> $INI_FILE; fi
- if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then phpenv config-rm xdebug.ini; fi; - if [[ ! $skip && $PHP != hhvm ]]; then phpenv config-rm xdebug.ini; fi
- if [[ $deps != skip ]]; then composer self-update; fi; - if [[ ! $skip ]]; then composer self-update; fi
- if [[ $deps != skip && $TRAVIS_REPO_SLUG = symfony/symfony ]]; then cp .composer/* ~/.composer/; composer global install; fi; - if [[ ! $skip ]]; then cp .composer/* ~/.composer/; composer global install; fi
- if [[ $deps != skip ]]; then ./phpunit install; fi; - if [[ ! $skip ]]; then ./phpunit install; fi
- export PHPUNIT=$(readlink -f ./phpunit) - if [[ ! $skip && $deps ]]; then composer global remove hirak/prestissimo; fi
- if [[ ! $skip ]]; then export PHPUNIT=$(readlink -f ./phpunit); fi
install: install:
- if [[ $deps != skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi; - if [[ ! $skip ]]; then COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); fi
# Create local composer packages for each patched components and reference them in composer.json files when cross-testing components # Create local composer packages for each patched components and reference them in composer.json files when cross-testing components
- if [[ $deps != skip && $deps ]]; then php .travis.php $TRAVIS_COMMIT_RANGE $TRAVIS_BRANCH $COMPONENTS; fi; - if [[ ! $skip && $deps ]]; then php .travis.php $TRAVIS_COMMIT_RANGE $TRAVIS_BRANCH $COMPONENTS; fi
# For the master branch when deps=high, the version before master is checked out and tested with the locally patched components # For the master branch when deps=high, the version before master is checked out and tested with the locally patched components
- if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then SYMFONY_VERSION=$(git ls-remote --heads | grep -o '/[1-9].*' | tail -n 1 | sed s/.//); else SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*'); fi; - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then SYMFONY_VERSION=$(git ls-remote --heads | grep -o '/[1-9].*' | tail -n 1 | sed s/.//); else SYMFONY_VERSION=$(cat composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9.]*'); fi
- if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then git fetch origin $SYMFONY_VERSION; git checkout -m FETCH_HEAD; COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); ./phpunit install; fi; - if [[ $deps = high && $TRAVIS_BRANCH = master ]]; then git fetch origin $SYMFONY_VERSION; git checkout -m FETCH_HEAD; COMPONENTS=$(find src/Symfony -mindepth 3 -type f -name phpunit.xml.dist -printf '%h\n'); ./phpunit install; fi
# Legacy tests are skipped when deps=high and when the current branch version has not the same major version number than the next one # Legacy tests are skipped when deps=high and when the current branch version has not the same major version number than the next one
- if [[ $deps = high && ${SYMFONY_VERSION%.*} != $(git show $(git ls-remote --heads | grep -FA1 /$SYMFONY_VERSION | tail -n 1):composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9]*' | head -n 1) ]]; then LEGACY=,legacy; fi; - if [[ $deps = high && ${SYMFONY_VERSION%.*} != $(git show $(git ls-remote --heads | grep -FA1 /$SYMFONY_VERSION | tail -n 1):composer.json | grep '^ *"dev-master". *"[1-9]' | grep -o '[0-9]*' | head -n 1) ]]; then LEGACY=,legacy; fi
- export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev; - export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev
- if [[ ! $deps ]]; then composer update; else export SYMFONY_DEPRECATIONS_HELPER=weak; fi; - if [[ ! $deps ]]; then composer update; else export SYMFONY_DEPRECATIONS_HELPER=weak; fi
- if [[ $TRAVIS_BRANCH = master ]]; then export SYMFONY_PHPUNIT_OVERLOAD=1; fi; - if [[ $TRAVIS_BRANCH = master ]]; then export SYMFONY_PHPUNIT_OVERLOAD=1; fi
- if [[ $TRAVIS_PHP_VERSION != hhvm ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi; - if [[ $PHP != hhvm ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi
script: script:
- if [[ ! $deps ]]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'; fi; - if [[ $skip ]]; then echo -e "\\n\\e[1;34mIntermediate PHP version $PHP is skipped for pull requests.\\e[0m"; fi
- if [[ ! $deps ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi; - if [[ ! $deps ]]; then echo "$COMPONENTS" | parallel --gnu '$PHPUNIT --exclude-group tty,benchmark,intl-data {}'; fi
- if [[ ! $deps && $TRAVIS_PHP_VERSION = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi; - if [[ ! $deps ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi
- if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY; fi; - if [[ ! $deps && $PHP = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi
- if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'; fi; - if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY; fi
- if [[ $deps = skip ]]; then echo This matrix line is skipped for pull requests.; fi; - if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'; fi

View File

@ -54,8 +54,8 @@ install:
- copy /Y php.ini-max php.ini - copy /Y php.ini-max php.ini
- cd c:\projects\symfony - cd c:\projects\symfony
- mkdir %APPDATA%\Composer - mkdir %APPDATA%\Composer
- IF %APPVEYOR_REPO_NAME%==symfony/symfony copy /Y .composer\* %APPDATA%\Composer\ - copy /Y .composer\* %APPDATA%\Composer\
- IF %APPVEYOR_REPO_NAME%==symfony/symfony composer global install --no-progress --ansi || echo curl.cainfo needs PHP 5.3.7 - composer global install --no-progress --ansi
- php phpunit install - php phpunit install
- IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev) - IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev)
- composer update --no-progress --ansi - composer update --no-progress --ansi

View File

@ -93,7 +93,11 @@
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Symfony\\Bridge\\": "src/Symfony/Bridge/", "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/",
"Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/",
"Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/",
"Symfony\\Bridge\\Swiftmailer\\": "src/Symfony/Bridge/Swiftmailer/",
"Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/",
"Symfony\\Bundle\\": "src/Symfony/Bundle/", "Symfony\\Bundle\\": "src/Symfony/Bundle/",
"Symfony\\Component\\": "src/Symfony/Component/" "Symfony\\Component\\": "src/Symfony/Component/"
}, },
@ -104,6 +108,11 @@
"**/Tests/" "**/Tests/"
] ]
}, },
"autoload-dev": {
"psr-4": {
"Symfony\\Bridge\\PhpUnit\\": "src/Symfony/Bridge/PhpUnit/"
}
},
"minimum-stability": "dev", "minimum-stability": "dev",
"extra": { "extra": {
"branch-alias": { "branch-alias": {

View File

@ -78,6 +78,10 @@ class ControllerResolver extends BaseControllerResolver
*/ */
protected function instantiateController($class) protected function instantiateController($class)
{ {
if ($this->container->has($class)) {
return $this->container->get($class);
}
$controller = parent::instantiateController($class); $controller = parent::instantiateController($class);
if ($controller instanceof ContainerAwareInterface) { if ($controller instanceof ContainerAwareInterface) {

View File

@ -87,6 +87,8 @@ class ControllerResolverTest extends BaseControllerResolverTest
public function testGetControllerInvokableService() public function testGetControllerInvokableService()
{ {
$invokableController = new InvokableController('bar');
$container = $this->createMockContainer(); $container = $this->createMockContainer();
$container->expects($this->once()) $container->expects($this->once())
->method('has') ->method('has')
@ -96,7 +98,7 @@ class ControllerResolverTest extends BaseControllerResolverTest
$container->expects($this->once()) $container->expects($this->once())
->method('get') ->method('get')
->with('foo') ->with('foo')
->will($this->returnValue($this)) ->will($this->returnValue($invokableController))
; ;
$resolver = $this->createControllerResolver(null, null, $container); $resolver = $this->createControllerResolver(null, null, $container);
@ -105,7 +107,33 @@ class ControllerResolverTest extends BaseControllerResolverTest
$controller = $resolver->getController($request); $controller = $resolver->getController($request);
$this->assertInstanceOf(get_class($this), $controller); $this->assertEquals($invokableController, $controller);
}
public function testGetControllerInvokableServiceWithClassNameAsName()
{
$invokableController = new InvokableController('bar');
$className = __NAMESPACE__.'\InvokableController';
$container = $this->createMockContainer();
$container->expects($this->once())
->method('has')
->with($className)
->will($this->returnValue(true))
;
$container->expects($this->once())
->method('get')
->with($className)
->will($this->returnValue($invokableController))
;
$resolver = $this->createControllerResolver(null, null, $container);
$request = Request::create('/');
$request->attributes->set('_controller', $className);
$controller = $resolver->getController($request);
$this->assertEquals($invokableController, $controller);
} }
/** /**
@ -178,3 +206,14 @@ class ContainerAwareController implements ContainerAwareInterface
{ {
} }
} }
class InvokableController
{
public function __construct($bar) // mandatory argument to prevent automatic instantiation
{
}
public function __invoke()
{
}
}

View File

@ -25,7 +25,6 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
{ {
private $compiler; private $compiler;
private $formatter; private $formatter;
private $sourceId;
/** /**
* Process the Container to replace aliases with service definitions. * Process the Container to replace aliases with service definitions.
@ -36,118 +35,110 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
*/ */
public function process(ContainerBuilder $container) public function process(ContainerBuilder $container)
{ {
// Setup
$this->compiler = $container->getCompiler(); $this->compiler = $container->getCompiler();
$this->formatter = $this->compiler->getLoggingFormatter(); $this->formatter = $this->compiler->getLoggingFormatter();
// First collect all alias targets that need to be replaced
foreach ($container->getAliases() as $id => $alias) { $seenAliasTargets = array();
$aliasId = (string) $alias; $replacements = array();
foreach ($container->getAliases() as $definitionId => $target) {
if ('service_container' === $aliasId) { $targetId = (string) $target;
// Special case: leave this target alone
if ('service_container' === $targetId) {
continue; continue;
} }
// Check if target needs to be replaces
try { if (isset($replacements[$targetId])) {
$definition = $container->getDefinition($aliasId); $container->setAlias($definitionId, $replacements[$targetId]);
} catch (InvalidArgumentException $e) { }
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $id, $alias), null, $e); // No neeed to process the same target twice
if (isset($seenAliasTargets[$targetId])) {
continue;
}
// Process new target
$seenAliasTargets[$targetId] = true;
try {
$definition = $container->getDefinition($targetId);
} catch (InvalidArgumentException $e) {
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e);
} }
if ($definition->isPublic()) { if ($definition->isPublic()) {
continue; continue;
} }
// Remove private definition and schedule for replacement
$definition->setPublic(true); $definition->setPublic(true);
$container->setDefinition($id, $definition); $container->setDefinition($definitionId, $definition);
$container->removeDefinition($aliasId); $container->removeDefinition($targetId);
$replacements[$targetId] = $definitionId;
}
$this->updateReferences($container, $aliasId, $id); // Now replace target instances in all definitions
foreach ($container->getDefinitions() as $definitionId => $definition) {
// we have to restart the process due to concurrent modification of $definition->setArguments($this->updateArgumentReferences($replacements, $definitionId, $definition->getArguments()));
// the container $definition->setMethodCalls($this->updateArgumentReferences($replacements, $definitionId, $definition->getMethodCalls()));
$this->process($container); $definition->setProperties($this->updateArgumentReferences($replacements, $definitionId, $definition->getProperties()));
$definition->setFactoryService($this->updateFactoryReferenceId($replacements, $definition->getFactoryService(false)), false);
break; $definition->setFactory($this->updateFactoryReference($replacements, $definition->getFactory()));
} }
} }
/** /**
* Updates references to remove aliases. * Recursively updates references in an array.
* *
* @param ContainerBuilder $container The container * @param array $replacements Table of aliases to replace
* @param string $currentId The alias identifier being replaced * @param string $definitionId Identifier of this definition
* @param string $newId The id of the service the alias points to * @param array $arguments Where to replace the aliases
*/
private function updateReferences($container, $currentId, $newId)
{
foreach ($container->getAliases() as $id => $alias) {
if ($currentId === (string) $alias) {
$container->setAlias($id, $newId);
}
}
foreach ($container->getDefinitions() as $id => $definition) {
$this->sourceId = $id;
$definition->setArguments(
$this->updateArgumentReferences($definition->getArguments(), $currentId, $newId)
);
$definition->setMethodCalls(
$this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId)
);
$definition->setProperties(
$this->updateArgumentReferences($definition->getProperties(), $currentId, $newId)
);
$definition->setFactoryService($this->updateFactoryServiceReference($definition->getFactoryService(false), $currentId, $newId), false);
$definition->setFactory($this->updateFactoryReference($definition->getFactory(), $currentId, $newId));
}
}
/**
* Updates argument references.
*
* @param array $arguments An array of Arguments
* @param string $currentId The alias identifier
* @param string $newId The identifier the alias points to
* *
* @return array * @return array
*/ */
private function updateArgumentReferences(array $arguments, $currentId, $newId) private function updateArgumentReferences(array $replacements, $definitionId, array $arguments)
{ {
foreach ($arguments as $k => $argument) { foreach ($arguments as $k => $argument) {
// Handle recursion step
if (is_array($argument)) { if (is_array($argument)) {
$arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId); $arguments[$k] = $this->updateArgumentReferences($replacements, $definitionId, $argument);
} elseif ($argument instanceof Reference) { continue;
if ($currentId === (string) $argument) { }
// Skip arguments that don't need replacement
if (!$argument instanceof Reference) {
continue;
}
$referenceId = (string) $argument;
if (!isset($replacements[$referenceId])) {
continue;
}
// Perform the replacement
$newId = $replacements[$referenceId];
$arguments[$k] = new Reference($newId, $argument->getInvalidBehavior()); $arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
$this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId)); $this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $definitionId, $referenceId, $newId));
}
}
} }
return $arguments; return $arguments;
} }
private function updateFactoryServiceReference($factoryService, $currentId, $newId) /**
* Returns the updated reference for the factory service.
*
* @param array $replacements Table of aliases to replace
* @param string|null $referenceId Factory service reference identifier
*
* @return string|null
*/
private function updateFactoryReferenceId(array $replacements, $referenceId)
{ {
if (null === $factoryService) { if (null === $referenceId) {
return; return;
} }
return $currentId === $factoryService ? $newId : $factoryService; return isset($replacements[$referenceId]) ? $replacements[$referenceId] : $referenceId;
} }
private function updateFactoryReference($factory, $currentId, $newId) private function updateFactoryReference(array $replacements, $factory)
{ {
if (null === $factory || !is_array($factory) || !$factory[0] instanceof Reference) { if (is_array($factory) && $factory[0] instanceof Reference && isset($replacements[$referenceId = (string) $factory[0]])) {
return $factory; $factory[0] = new Reference($replacements[$referenceId], $factory[0]->getInvalidBehavior());
} }
if ($currentId === (string) $factory[0]) {
$factory[0] = new Reference($newId, $factory[0]->getInvalidBehavior());
}
return $factory; return $factory;
} }

View File

@ -766,11 +766,7 @@ class Form implements \IteratorAggregate, FormInterface
return true; return true;
} }
if (count($this->getErrors(true)) > 0) { return 0 === count($this->getErrors(true));
return false;
}
return true;
} }
/** /**

View File

@ -50,7 +50,7 @@ class UploadedFile extends File
/** /**
* The file size provided by the uploader. * The file size provided by the uploader.
* *
* @var string * @var int|null
*/ */
private $size; private $size;
@ -77,9 +77,9 @@ class UploadedFile extends File
* *
* @param string $path The full temporary path to the file * @param string $path The full temporary path to the file
* @param string $originalName The original file name * @param string $originalName The original file name
* @param string $mimeType The type of the file as provided by PHP * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream
* @param int $size The file size * @param int|null $size The file size
* @param int $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants) * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK
* @param bool $test Whether the test mode is active * @param bool $test Whether the test mode is active
* *
* @throws FileException If file_uploads is disabled * @throws FileException If file_uploads is disabled

View File

@ -1087,7 +1087,7 @@ class Process
throw new LogicException('Input can not be set while the process is running.'); throw new LogicException('Input can not be set while the process is running.');
} }
$this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input); $this->input = ProcessUtils::validateInput(__METHOD__, $input);
return $this; return $this;
} }

View File

@ -177,7 +177,7 @@ class ProcessBuilder
*/ */
public function setInput($input) public function setInput($input)
{ {
$this->input = ProcessUtils::validateInput(sprintf('%s::%s', __CLASS__, __FUNCTION__), $input); $this->input = ProcessUtils::validateInput(__METHOD__, $input);
return $this; return $this;
} }

View File

@ -75,6 +75,11 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
'%7C' => '|', '%7C' => '|',
); );
/**
* @var string This regexp matches all characters that are not or should not be encoded by rawurlencode (see list in array above).
*/
private $urlEncodingSkipRegexp = '#[^-.~a-zA-Z0-9_/@:;,=+!*|]#';
/** /**
* Constructor. * Constructor.
* *
@ -196,20 +201,22 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
if ('' === $url) { if ('' === $url) {
$url = '/'; $url = '/';
} } elseif (preg_match($this->urlEncodingSkipRegexp, $url)) {
// the context base URL is already encoded (see Symfony\Component\HttpFoundation\Request)
// the contexts base URL is already encoded (see Symfony\Component\HttpFoundation\Request)
$url = strtr(rawurlencode($url), $this->decodedChars); $url = strtr(rawurlencode($url), $this->decodedChars);
}
// the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3
// so we need to encode them as they are not used for this purpose here // so we need to encode them as they are not used for this purpose here
// otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route
if (false !== strpos($url, '/.')) {
$url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/'));
if ('/..' === substr($url, -3)) { if ('/..' === substr($url, -3)) {
$url = substr($url, 0, -2).'%2E%2E'; $url = substr($url, 0, -2).'%2E%2E';
} elseif ('/.' === substr($url, -2)) { } elseif ('/.' === substr($url, -2)) {
$url = substr($url, 0, -1).'%2E'; $url = substr($url, 0, -1).'%2E';
} }
}
$schemeAuthority = ''; $schemeAuthority = '';
if ($host = $this->context->getHost()) { if ($host = $this->context->getHost()) {
@ -282,7 +289,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt
if ($extra && $query = http_build_query($extra, '', '&')) { if ($extra && $query = http_build_query($extra, '', '&')) {
// "/" and "?" can be left decoded for better user experience, see // "/" and "?" can be left decoded for better user experience, see
// http://tools.ietf.org/html/rfc3986#section-3.4 // http://tools.ietf.org/html/rfc3986#section-3.4
$url .= '?'.strtr($query, array('%2F' => '/')); $url .= '?'.(false === strpos($query, '%2F') ? $query : strtr($query, array('%2F' => '/')));
} }
return $url; return $url;

View File

@ -110,6 +110,7 @@ class EmailValidatorTest extends AbstractConstraintValidatorTest
/** /**
* @dataProvider getDnsChecks * @dataProvider getDnsChecks
* @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
*/ */
public function testDnsChecks($type, $violation) public function testDnsChecks($type, $violation)
{ {
@ -144,6 +145,9 @@ class EmailValidatorTest extends AbstractConstraintValidatorTest
); );
} }
/**
* @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
*/
public function testHostnameIsProperlyParsed() public function testHostnameIsProperlyParsed()
{ {
DnsMock::withMockedHosts(array('baz.com' => array(array('type' => 'MX')))); DnsMock::withMockedHosts(array('baz.com' => array(array('type' => 'MX'))));

View File

@ -195,6 +195,7 @@ class UrlValidatorTest extends AbstractConstraintValidatorTest
/** /**
* @dataProvider getCheckDns * @dataProvider getCheckDns
* @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts
*/ */
public function testCheckDns($violation) public function testCheckDns($violation)
{ {