diff --git a/.travis.yml b/.travis.yml index 711fa49c74..618fdeded3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -dist: precise +dist: trusty sudo: false git: @@ -20,10 +20,8 @@ env: matrix: include: - # Use the newer stack for HHVM as HHVM does not support Precise anymore since a long time and so Precise has an outdated version - php: hhvm-3.18 sudo: required - dist: trusty group: edge - php: 5.5 - php: 5.6 @@ -104,7 +102,6 @@ before_install: echo opcache.enable_cli = 1 >> $INI echo hhvm.jit = 0 >> $INI echo apc.enable_cli = 1 >> $INI - echo extension = ldap.so >> $INI echo extension = redis.so >> $INI echo extension = memcached.so >> $INI [[ $PHP = 5.* ]] && echo extension = memcache.so >> $INI diff --git a/src/Symfony/Component/Console/Input/ArrayInput.php b/src/Symfony/Component/Console/Input/ArrayInput.php index 434ec0240d..19921fb3b6 100644 --- a/src/Symfony/Component/Console/Input/ArrayInput.php +++ b/src/Symfony/Component/Console/Input/ArrayInput.php @@ -112,9 +112,15 @@ class ArrayInput extends Input $params = array(); foreach ($this->parameters as $param => $val) { if ($param && '-' === $param[0]) { - $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + if (is_array($val)) { + foreach ($val as $v) { + $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); + } + } else { + $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + } } else { - $params[] = $this->escapeToken($val); + $params[] = is_array($val) ? array_map(array($this, 'escapeToken'), $val) : $this->escapeToken($val); } } diff --git a/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php index a1b5a2030b..3e8584352a 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php @@ -167,5 +167,8 @@ class ArrayInputTest extends TestCase { $input = new ArrayInput(array('-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C")); $this->assertEquals('-f -b=bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input); + + $input = new ArrayInput(array('-b' => array('bval_1', 'bval_2'), '--f' => array('fval_1', 'fval_2'))); + $this->assertSame('-b=bval_1 -b=bval_2 --f=fval_1 --f=fval_2', (string) $input); } } diff --git a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php index c5c99d78ca..2ecba97f7f 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php @@ -82,8 +82,11 @@ class GetAttrNode extends Node if (!is_object($obj)) { throw new \RuntimeException('Unable to get a property on a non-object.'); } + if (!is_callable($toCall = array($obj, $this->nodes['attribute']->attributes['value']))) { + throw new \RuntimeException(sprintf('Unable to call method "%s" of object "%s".', $this->nodes['attribute']->attributes['value'], get_class($obj))); + } - return call_user_func_array(array($obj, $this->nodes['attribute']->attributes['value']), $this->nodes['arguments']->evaluate($functions, $values)); + return call_user_func_array($toCall, $this->nodes['arguments']->evaluate($functions, $values)); case self::ARRAY_CALL: $array = $this->nodes['node']->evaluate($functions, $values); diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index 82f1c439b9..eb4f7d2ef0 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -242,6 +242,16 @@ class ExpressionLanguageTest extends TestCase $registerCallback($el); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessageRegExp /Unable to call method "\w+" of object "\w+"./ + */ + public function testCallBadCallable() + { + $el = new ExpressionLanguage(); + $el->evaluate('foo.myfunction()', array('foo' => new \stdClass())); + } + /** * @dataProvider getRegisterCallbacks * @expectedException \LogicException diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index cf1a11ea2c..ed8f1e9b82 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -146,12 +146,17 @@ class JsonResponse extends Response $data = json_encode($data, $this->encodingOptions); } else { try { - // PHP 5.4 and up wrap exceptions thrown by JsonSerializable - // objects in a new exception that needs to be removed. - // Fortunately, PHP 5.5 and up do not trigger any warning anymore. - $data = json_encode($data, $this->encodingOptions); + if (!interface_exists('JsonSerializable', false)) { + set_error_handler(function () { return false; }); + $data = @json_encode($data, $this->encodingOptions); + restore_error_handler(); + } else { + $data = json_encode($data, $this->encodingOptions); + } } catch (\Exception $e) { - if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { + if (!interface_exists('JsonSerializable', false)) { + restore_error_handler(); + } elseif ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { throw $e->getPrevious() ?: $e; } throw $e; diff --git a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php index c8b9377895..201839f89c 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php @@ -228,6 +228,10 @@ class JsonResponseTest extends TestCase */ public function testSetContentJsonSerializeError() { + if (!interface_exists('JsonSerializable', false)) { + $this->markTestSkipped('JsonSerializable is required.'); + } + $serializable = new JsonSerializableObject(); JsonResponse::create($serializable); @@ -242,7 +246,7 @@ class JsonResponseTest extends TestCase } } -if (interface_exists('JsonSerializable')) { +if (interface_exists('JsonSerializable', false)) { class JsonSerializableObject implements \JsonSerializable { public function jsonSerialize()