diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index ec7da4c37c..fe59a09640 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -207,7 +207,7 @@ EOF } }); - $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0)); + $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES : 0)); return min($errors, 1); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index 67274fdaf9..e3c750d6d0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -162,7 +162,7 @@ EOF } }); - $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0)); + $output->writeln(json_encode($filesInfo, defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES : 0)); return min($errors, 1); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php index 8d2d6d7fd6..18f8368dc8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/choice_attributes.html.php @@ -1,4 +1,3 @@ -id="escape($id) ?>" name="escape($full_name) ?>" disabled="disabled" $v): ?> diff --git a/src/Symfony/Component/Config/FileLocator.php b/src/Symfony/Component/Config/FileLocator.php index c6600c7783..4816724c81 100644 --- a/src/Symfony/Component/Config/FileLocator.php +++ b/src/Symfony/Component/Config/FileLocator.php @@ -57,7 +57,7 @@ class FileLocator implements FileLocatorInterface $filepaths = array(); foreach ($paths as $path) { - if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { + if (@file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) { if (true === $first) { return $file; } diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 3ce766889d..41991ef76b 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -340,7 +340,7 @@ class Application * Adds an array of command objects. * * If a Command is not enabled it will not be added. - * + * * @param Command[] $commands An array of commands */ public function addCommands(array $commands) @@ -811,6 +811,7 @@ class Application if (true === $input->hasParameterOption(array('--quiet', '-q'))) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + $input->setInteractive(false); } else { if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index e1b2fb6048..cdb246f194 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -640,9 +640,11 @@ class ApplicationTest extends \PHPUnit_Framework_TestCase $tester->run(array('command' => 'list', '--quiet' => true)); $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if --quiet is passed'); $tester->run(array('command' => 'list', '-q' => true)); $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if -q is passed'); $tester->run(array('command' => 'list', '--verbose' => true)); $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed'); diff --git a/src/Symfony/Component/Form/PreloadedExtension.php b/src/Symfony/Component/Form/PreloadedExtension.php index a8fd9d0097..01f44f0d4b 100644 --- a/src/Symfony/Component/Form/PreloadedExtension.php +++ b/src/Symfony/Component/Form/PreloadedExtension.php @@ -14,7 +14,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\InvalidArgumentException; /** - * A form extension with preloaded types, type exceptions and type guessers. + * A form extension with preloaded types, type extensions and type guessers. * * @author Bernhard Schussek */ diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index cab932316e..e999ea06dc 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -657,8 +657,8 @@ abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormInteg [@class="bar&baz"] [not(@required)] [ - ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] - /following-sibling::option[@value="&b"][not(@class)][not(@selected)][.="[trans]Choice&B[/trans]"] + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"][not(@id)][not(@name)] + /following-sibling::option[@value="&b"][not(@class)][not(@selected)][.="[trans]Choice&B[/trans]"][not(@id)][not(@name)] ] [count(./option)=2] ' diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index 1d7c49607d..c76b57bb6a 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -27,6 +27,15 @@ class ControllerResolver implements ControllerResolverInterface { private $logger; + /** + * If the ...$arg functionality is available. + * + * Requires at least PHP 5.6.0 or HHVM 3.9.1 + * + * @var bool + */ + private $supportsVariadic; + /** * Constructor. * @@ -35,6 +44,8 @@ class ControllerResolver implements ControllerResolverInterface public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; + + $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); } /** @@ -99,13 +110,20 @@ class ControllerResolver implements ControllerResolverInterface return $this->doGetArguments($request, $controller, $r->getParameters()); } + /** + * @param Request $request + * @param callable $controller + * @param \ReflectionParameter[] $parameters + * + * @return array The arguments to use when calling the action + */ protected function doGetArguments(Request $request, $controller, array $parameters) { $attributes = $request->attributes->all(); $arguments = array(); foreach ($parameters as $param) { if (array_key_exists($param->name, $attributes)) { - if (PHP_VERSION_ID >= 50600 && $param->isVariadic() && is_array($attributes[$param->name])) { + if ($this->supportsVariadic && $param->isVariadic() && is_array($attributes[$param->name])) { $arguments = array_merge($arguments, array_values($attributes[$param->name])); } else { $arguments[] = $attributes[$param->name]; @@ -114,6 +132,8 @@ class ControllerResolver implements ControllerResolverInterface $arguments[] = $request; } elseif ($param->isDefaultValueAvailable()) { $arguments[] = $param->getDefaultValue(); + } elseif ($param->allowsNull()) { + $arguments[] = null; } else { if (is_array($controller)) { $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 101782e490..9aa7e20a9a 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; use Symfony\Component\HttpFoundation\Request; @@ -222,6 +223,34 @@ class ControllerResolverTest extends \PHPUnit_Framework_TestCase $mock->getController($request); } + /** + * @requires PHP 7.1 + */ + public function testGetNullableArguments() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('foo', 'foo'); + $request->attributes->set('bar', new \stdClass()); + $request->attributes->set('mandatory', 'mandatory'); + $controller = array(new NullableController(), 'action'); + $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + } + + /** + * @requires PHP 7.1 + */ + public function testGetNullableArgumentsWithDefaults() + { + $resolver = new ControllerResolver(); + + $request = Request::create('/'); + $request->attributes->set('mandatory', 'mandatory'); + $controller = array(new NullableController(), 'action'); + $this->assertEquals(array(null, null, 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + } + protected function createControllerResolver(LoggerInterface $logger = null) { return new ControllerResolver($logger); diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php new file mode 100644 index 0000000000..9db4df7b4c --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/Controller/NullableController.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Fixtures\Controller; + +class NullableController +{ + public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory) + { + } +}