Merge branch '3.3' into 3.4
* 3.3: Add application/ld+json format associated to json [HttpFoundation] Fix false-positive ConflictingHeadersException [WebServerBundle] Fix escaping of php binary with arguments Error handlers' $context should be optional as it's deprecated [Serializer] Correct typing mistake in DocBlock [Config] Fix closure CS PHP CS Fixer: use PHPUnit Migration ruleset Update MemcachedTrait.php [Bridge/PhpUnit] thank phpunit/phpunit [Process] Fix setting empty env vars [Process] Dont use getenv(), it returns arrays and can introduce subtle breaks accros PHP versions [WebServerBundle] fix a bug where require would not require the good file because of env [Console] Commands with an alias should not be recognized as ambiguous
This commit is contained in:
commit
cc027a261f
@ -8,9 +8,10 @@ return PhpCsFixer\Config::create()
|
|||||||
->setRules(array(
|
->setRules(array(
|
||||||
'@Symfony' => true,
|
'@Symfony' => true,
|
||||||
'@Symfony:risky' => true,
|
'@Symfony:risky' => true,
|
||||||
|
'@PHPUnit48Migration:risky' => true,
|
||||||
|
'php_unit_no_expectation_annotation' => false, // part of `PHPUnitXYMigration:risky` ruleset, to be enabled when PHPUnit 4.x support will be dropped, as we don't want to rewrite exceptions handling twice
|
||||||
'array_syntax' => array('syntax' => 'long'),
|
'array_syntax' => array('syntax' => 'long'),
|
||||||
'protected_to_private' => false,
|
'protected_to_private' => false,
|
||||||
'php_unit_dedicate_assert' => array('target' => '3.5'),
|
|
||||||
))
|
))
|
||||||
->setRiskyAllowed(true)
|
->setRiskyAllowed(true)
|
||||||
->setFinder(
|
->setFinder(
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
"dev-master": "3.4-dev"
|
"dev-master": "3.4-dev"
|
||||||
|
},
|
||||||
|
"thanks": {
|
||||||
|
"name": "phpunit/phpunit",
|
||||||
|
"url": "https://github.com/sebastianbergmann/phpunit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ if (is_file($_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$_SERVER['SCRIPT_NAME'
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$script = getenv('APP_FRONT_CONTROLLER') ?: 'index.php';
|
$script = isset($_ENV['APP_FRONT_CONTROLLER']) ? $_ENV['APP_FRONT_CONTROLLER'] : 'index.php';
|
||||||
|
|
||||||
$_SERVER = array_merge($_SERVER, $_ENV);
|
$_SERVER = array_merge($_SERVER, $_ENV);
|
||||||
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$script;
|
$_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$script;
|
||||||
|
@ -146,11 +146,11 @@ class WebServer
|
|||||||
private function createServerProcess(WebServerConfig $config)
|
private function createServerProcess(WebServerConfig $config)
|
||||||
{
|
{
|
||||||
$finder = new PhpExecutableFinder();
|
$finder = new PhpExecutableFinder();
|
||||||
if (false === $binary = $finder->find()) {
|
if (false === $binary = $finder->find(false)) {
|
||||||
throw new \RuntimeException('Unable to find the PHP binary.');
|
throw new \RuntimeException('Unable to find the PHP binary.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$process = new Process(array($binary, '-S', $config->getAddress(), $config->getRouter()));
|
$process = new Process(array_merge(array($binary), $finder->findArguments(), array('-dvariables_order=EGPCS', '-S', $config->getAddress(), $config->getRouter())));
|
||||||
$process->setWorkingDirectory($config->getDocumentRoot());
|
$process->setWorkingDirectory($config->getDocumentRoot());
|
||||||
$process->setTimeout(null);
|
$process->setTimeout(null);
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class WebServerConfig
|
|||||||
throw new \InvalidArgumentException(sprintf('Unable to find the front controller under "%s" (none of these files exist: %s).', $documentRoot, implode(', ', $this->getFrontControllerFileNames($env))));
|
throw new \InvalidArgumentException(sprintf('Unable to find the front controller under "%s" (none of these files exist: %s).', $documentRoot, implode(', ', $this->getFrontControllerFileNames($env))));
|
||||||
}
|
}
|
||||||
|
|
||||||
putenv('APP_FRONT_CONTROLLER='.$file);
|
$_ENV['APP_FRONT_CONTROLLER'] = $file;
|
||||||
|
|
||||||
$this->documentRoot = $documentRoot;
|
$this->documentRoot = $documentRoot;
|
||||||
$this->env = $env;
|
$this->env = $env;
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"symfony/console": "~3.4|~4.0",
|
"symfony/console": "~3.4|~4.0",
|
||||||
"symfony/dependency-injection": "~3.4|~4.0",
|
"symfony/dependency-injection": "~3.4|~4.0",
|
||||||
"symfony/http-kernel": "~3.3|~4.0",
|
"symfony/http-kernel": "~3.3|~4.0",
|
||||||
"symfony/process": "~3.3|~4.0"
|
"symfony/process": "~3.3.14|^3.4.2|^4.0.2"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" },
|
"psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" },
|
||||||
|
@ -71,7 +71,7 @@ trait MemcachedTrait
|
|||||||
*
|
*
|
||||||
* @return \Memcached
|
* @return \Memcached
|
||||||
*
|
*
|
||||||
* @throws \ErrorEception When invalid options or servers are provided
|
* @throws \ErrorException When invalid options or servers are provided
|
||||||
*/
|
*/
|
||||||
public static function createConnection($servers, array $options = array())
|
public static function createConnection($servers, array $options = array())
|
||||||
{
|
{
|
||||||
|
@ -158,7 +158,7 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
|
|||||||
$meta = false;
|
$meta = false;
|
||||||
$signalingException = new \UnexpectedValueException();
|
$signalingException = new \UnexpectedValueException();
|
||||||
$prevUnserializeHandler = ini_set('unserialize_callback_func', '');
|
$prevUnserializeHandler = ini_set('unserialize_callback_func', '');
|
||||||
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) use (&$prevErrorHandler, $signalingException) {
|
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$prevErrorHandler, $signalingException) {
|
||||||
if (E_WARNING === $type && 'Class __PHP_Incomplete_Class has no unserializer' === $msg) {
|
if (E_WARNING === $type && 'Class __PHP_Incomplete_Class has no unserializer' === $msg) {
|
||||||
throw $signalingException;
|
throw $signalingException;
|
||||||
}
|
}
|
||||||
|
@ -580,6 +580,7 @@ class Application
|
|||||||
{
|
{
|
||||||
$this->init();
|
$this->init();
|
||||||
|
|
||||||
|
$aliases = array();
|
||||||
$allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
|
$allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands);
|
||||||
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
|
$expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
|
||||||
$commands = preg_grep('{^'.$expr.'}', $allCommands);
|
$commands = preg_grep('{^'.$expr.'}', $allCommands);
|
||||||
@ -612,14 +613,15 @@ class Application
|
|||||||
// filter out aliases for commands which are already on the list
|
// filter out aliases for commands which are already on the list
|
||||||
if (count($commands) > 1) {
|
if (count($commands) > 1) {
|
||||||
$commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
|
$commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
|
||||||
$commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
|
$commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) {
|
||||||
$commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias;
|
$commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias;
|
||||||
|
$aliases[$nameOrAlias] = $commandName;
|
||||||
|
|
||||||
return $commandName === $nameOrAlias || !in_array($commandName, $commands);
|
return $commandName === $nameOrAlias || !in_array($commandName, $commands);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
$exact = in_array($name, $commands, true);
|
$exact = in_array($name, $commands, true) || isset($aliases[$name]);
|
||||||
if (count($commands) > 1 && !$exact) {
|
if (count($commands) > 1 && !$exact) {
|
||||||
$usableWidth = $this->terminal->getWidth() - 10;
|
$usableWidth = $this->terminal->getWidth() - 10;
|
||||||
$abbrevs = array_values($commands);
|
$abbrevs = array_values($commands);
|
||||||
|
@ -57,6 +57,8 @@ class ApplicationTest extends TestCase
|
|||||||
require_once self::$fixturesPath.'/BarBucCommand.php';
|
require_once self::$fixturesPath.'/BarBucCommand.php';
|
||||||
require_once self::$fixturesPath.'/FooSubnamespaced1Command.php';
|
require_once self::$fixturesPath.'/FooSubnamespaced1Command.php';
|
||||||
require_once self::$fixturesPath.'/FooSubnamespaced2Command.php';
|
require_once self::$fixturesPath.'/FooSubnamespaced2Command.php';
|
||||||
|
require_once self::$fixturesPath.'/TestTiti.php';
|
||||||
|
require_once self::$fixturesPath.'/TestToto.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function normalizeLineBreaks($text)
|
protected function normalizeLineBreaks($text)
|
||||||
@ -283,6 +285,14 @@ class ApplicationTest extends TestCase
|
|||||||
$application->findNamespace('f');
|
$application->findNamespace('f');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFindNonAmbiguous()
|
||||||
|
{
|
||||||
|
$application = new Application();
|
||||||
|
$application->add(new \TestTiti());
|
||||||
|
$application->add(new \TestToto());
|
||||||
|
$this->assertEquals('test-toto', $application->find('test')->getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
|
* @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException
|
||||||
* @expectedExceptionMessage There are no commands defined in the "bar" namespace.
|
* @expectedExceptionMessage There are no commands defined in the "bar" namespace.
|
||||||
|
21
src/Symfony/Component/Console/Tests/Fixtures/TestTiti.php
Normal file
21
src/Symfony/Component/Console/Tests/Fixtures/TestTiti.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class TestTiti extends Command
|
||||||
|
{
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('test-titi')
|
||||||
|
->setDescription('The test:titi command')
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$output->write('test-titi');
|
||||||
|
}
|
||||||
|
}
|
22
src/Symfony/Component/Console/Tests/Fixtures/TestToto.php
Normal file
22
src/Symfony/Component/Console/Tests/Fixtures/TestToto.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
class TestToto extends Command
|
||||||
|
{
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('test-toto')
|
||||||
|
->setDescription('The test-toto command')
|
||||||
|
->setAliases(array('test'))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$output->write('test-toto');
|
||||||
|
}
|
||||||
|
}
|
@ -1990,6 +1990,7 @@ class Request
|
|||||||
'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
|
'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'),
|
||||||
'css' => array('text/css'),
|
'css' => array('text/css'),
|
||||||
'json' => array('application/json', 'application/x-json'),
|
'json' => array('application/json', 'application/x-json'),
|
||||||
|
'jsonld' => array('application/ld+json'),
|
||||||
'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
|
'xml' => array('text/xml', 'application/xml', 'application/x-xml'),
|
||||||
'rdf' => array('application/rdf+xml'),
|
'rdf' => array('application/rdf+xml'),
|
||||||
'atom' => array('application/atom+xml'),
|
'atom' => array('application/atom+xml'),
|
||||||
|
@ -372,6 +372,7 @@ class RequestTest extends TestCase
|
|||||||
array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')),
|
array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')),
|
||||||
array('css', array('text/css')),
|
array('css', array('text/css')),
|
||||||
array('json', array('application/json', 'application/x-json')),
|
array('json', array('application/json', 'application/x-json')),
|
||||||
|
array('jsonld', array('application/ld+json')),
|
||||||
array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
|
array('xml', array('text/xml', 'application/xml', 'application/x-xml')),
|
||||||
array('rdf', array('application/rdf+xml')),
|
array('rdf', array('application/rdf+xml')),
|
||||||
array('atom', array('application/atom+xml')),
|
array('atom', array('application/atom+xml')),
|
||||||
@ -968,6 +969,26 @@ class RequestTest extends TestCase
|
|||||||
$request->getClientIps();
|
$request->getClientIps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getClientIpsWithConflictingHeadersProvider
|
||||||
|
*/
|
||||||
|
public function testGetClientIpsOnlyXHttpForwardedForTrusted($httpForwarded, $httpXForwardedFor)
|
||||||
|
{
|
||||||
|
$request = new Request();
|
||||||
|
|
||||||
|
$server = array(
|
||||||
|
'REMOTE_ADDR' => '88.88.88.88',
|
||||||
|
'HTTP_FORWARDED' => $httpForwarded,
|
||||||
|
'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor,
|
||||||
|
);
|
||||||
|
|
||||||
|
Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_FOR);
|
||||||
|
|
||||||
|
$request->initialize(array(), array(), array(), array(), array(), $server);
|
||||||
|
|
||||||
|
$this->assertSame(array_reverse(explode(',', $httpXForwardedFor)), $request->getClientIps());
|
||||||
|
}
|
||||||
|
|
||||||
public function getClientIpsWithConflictingHeadersProvider()
|
public function getClientIpsWithConflictingHeadersProvider()
|
||||||
{
|
{
|
||||||
// $httpForwarded $httpXForwardedFor
|
// $httpForwarded $httpXForwardedFor
|
||||||
|
@ -326,12 +326,20 @@ class Process implements \IteratorAggregate
|
|||||||
// @see : https://bugs.php.net/69442
|
// @see : https://bugs.php.net/69442
|
||||||
$ptsWorkaround = fopen(__FILE__, 'r');
|
$ptsWorkaround = fopen(__FILE__, 'r');
|
||||||
}
|
}
|
||||||
|
if (defined('HHVM_VERSION')) {
|
||||||
|
$envPairs = $env;
|
||||||
|
} else {
|
||||||
|
$envPairs = array();
|
||||||
|
foreach ($env as $k => $v) {
|
||||||
|
$envPairs[] = $k.'='.$v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_dir($this->cwd)) {
|
if (!is_dir($this->cwd)) {
|
||||||
@trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since version 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
|
@trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since version 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $this->options);
|
$this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
|
||||||
|
|
||||||
if (!is_resource($this->process)) {
|
if (!is_resource($this->process)) {
|
||||||
throw new RuntimeException('Unable to launch a new process.');
|
throw new RuntimeException('Unable to launch a new process.');
|
||||||
@ -1722,9 +1730,6 @@ class Process implements \IteratorAggregate
|
|||||||
|
|
||||||
private function getDefaultEnv()
|
private function getDefaultEnv()
|
||||||
{
|
{
|
||||||
if (\PHP_VERSION_ID >= 70100) {
|
|
||||||
$env = getenv();
|
|
||||||
} else {
|
|
||||||
$env = array();
|
$env = array();
|
||||||
|
|
||||||
foreach ($_SERVER as $k => $v) {
|
foreach ($_SERVER as $k => $v) {
|
||||||
@ -1732,7 +1737,6 @@ class Process implements \IteratorAggregate
|
|||||||
$env[$k] = $v;
|
$env[$k] = $v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($_ENV as $k => $v) {
|
foreach ($_ENV as $k => $v) {
|
||||||
if (is_string($v)) {
|
if (is_string($v)) {
|
||||||
|
@ -1441,14 +1441,14 @@ class ProcessTest extends TestCase
|
|||||||
|
|
||||||
public function testEnvIsInherited()
|
public function testEnvIsInherited()
|
||||||
{
|
{
|
||||||
$process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ'));
|
$process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ', 'EMPTY' => ''));
|
||||||
|
|
||||||
putenv('FOO=BAR');
|
putenv('FOO=BAR');
|
||||||
$_ENV['FOO'] = 'BAR';
|
$_ENV['FOO'] = 'BAR';
|
||||||
|
|
||||||
$process->run();
|
$process->run();
|
||||||
|
|
||||||
$expected = array('BAR' => 'BAZ', 'FOO' => 'BAR');
|
$expected = array('BAR' => 'BAZ', 'EMPTY' => '', 'FOO' => 'BAR');
|
||||||
$env = array_intersect_key(unserialize($process->getOutput()), $expected);
|
$env = array_intersect_key(unserialize($process->getOutput()), $expected);
|
||||||
|
|
||||||
$this->assertEquals($expected, $env);
|
$this->assertEquals($expected, $env);
|
||||||
|
@ -245,7 +245,7 @@ class PropertyAccessor implements PropertyAccessorInterface
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public static function handleError($type, $message, $file, $line, $context)
|
public static function handleError($type, $message, $file, $line, $context = array())
|
||||||
{
|
{
|
||||||
if (E_RECOVERABLE_ERROR === $type) {
|
if (E_RECOVERABLE_ERROR === $type) {
|
||||||
self::throwInvalidArgumentException($message, debug_backtrace(false), 1);
|
self::throwInvalidArgumentException($message, debug_backtrace(false), 1);
|
||||||
|
@ -57,7 +57,7 @@ class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, Se
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given class implements the NormalizableInterface.
|
* Checks if the given class implements the DenormalizableInterface.
|
||||||
*
|
*
|
||||||
* @param mixed $data Data to denormalize from
|
* @param mixed $data Data to denormalize from
|
||||||
* @param string $type The class to which the data should be denormalized
|
* @param string $type The class to which the data should be denormalized
|
||||||
|
@ -212,7 +212,7 @@ abstract class AbstractCloner implements ClonerInterface
|
|||||||
*/
|
*/
|
||||||
public function cloneVar($var, $filter = 0)
|
public function cloneVar($var, $filter = 0)
|
||||||
{
|
{
|
||||||
$this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) {
|
$this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) {
|
||||||
if (E_RECOVERABLE_ERROR === $type || E_USER_ERROR === $type) {
|
if (E_RECOVERABLE_ERROR === $type || E_USER_ERROR === $type) {
|
||||||
// Cloner never dies
|
// Cloner never dies
|
||||||
throw new \ErrorException($msg, 0, $type, $file, $line);
|
throw new \ErrorException($msg, 0, $type, $file, $line);
|
||||||
|
Reference in New Issue
Block a user