diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md
index ed61259f28..86a2e43266 100644
--- a/CHANGELOG-2.7.md
+++ b/CHANGELOG-2.7.md
@@ -7,6 +7,27 @@ in 2.7 minor versions.
To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash
To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v2.7.0...v2.7.1
+* 2.7.3 (2015-07-31)
+
+ * bug #15413 Fix the return value on error for intl methods returning arrays (stof)
+ * bug #15392 Fix missing _route parameter notice in RouterListener logging case (Haehnchen)
+ * bug #15390 [php7] Fix for substr() always returning a string (nicolas-grekas)
+ * bug #15386 [php7] Fix for substr() always returning a string (nicolas-grekas)
+ * bug #15355 [Security] Do not save the target path in the session for a stateless firewall (lyrixx)
+ * bug #15306 [HttpKernel] [HttpCache] Fix deprecated error in HttpCache#getSurrogate (m14t)
+ * bug #15369 [TwigBridge] type-dependent path discovery (marcosdsanchez, xabbuh)
+ * bug #15361 [Yaml] throw a ParseException on invalid data type (xabbuh)
+ * bug #15345 [Twig+FrameworkBundle] Fix forward compat with Form 2.8 (nicolas-grekas)
+ * bug #15330 [Console] Fix console output with closed stdout (jakzal)
+ * bug #15339 [Serializer] Fix 2 bugs regarding private setters (dunglas)
+ * bug #15326 [Security] fix check for empty usernames (xabbuh)
+ * bug #15291 [HttpFoundation] Fix Response::closeOutputBuffers() for HHVM 3.3 (nicolas-grekas)
+ * bug #15249 [HttpFoundation] [PSR-7] Allow to use resources as content body and to return resources from string content (dunglas)
+ * bug #15282 [HttpFoundation] Behaviour change in PHP7 for substr (Nicofuma)
+ * bug #15277 [Form] Fix a BC break in the entity (jakzal)
+ * bug #15271 fix broken ChoiceQuestion (sstok)
+ * bug #15250 [PropertyAccess] BC Break since 2.6.5 (Nicolas Macherey)
+
* 2.7.2 (2015-07-13)
* bug #15248 Added 'default' color (jaytaph)
diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php
index c883f15469..027b66c052 100644
--- a/src/Symfony/Component/Debug/ExceptionHandler.php
+++ b/src/Symfony/Component/Debug/ExceptionHandler.php
@@ -38,7 +38,7 @@ class ExceptionHandler
public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
{
- if (false !== strpos($charset, '%') xor false === strpos($fileLinkFormat, '%')) {
+ if (false !== strpos($charset, '%')) {
// Swap $charset and $fileLinkFormat for BC reasons
$pivot = $fileLinkFormat;
$fileLinkFormat = $charset;
@@ -153,19 +153,22 @@ class ExceptionHandler
* it will fallback to plain PHP functions.
*
* @param \Exception $exception An \Exception instance
- *
- * @see sendPhpResponse()
- * @see createResponse()
*/
private function failSafeHandle(\Exception $exception)
{
- if (class_exists('Symfony\Component\HttpFoundation\Response', false)) {
+ if (class_exists('Symfony\Component\HttpFoundation\Response', false)
+ && __CLASS__ !== get_class($this)
+ && ($reflector = new \ReflectionMethod($this, 'createResponse'))
+ && __CLASS__ !== $reflector->class
+ ) {
$response = $this->createResponse($exception);
$response->sendHeaders();
$response->sendContent();
- } else {
- $this->sendPhpResponse($exception);
+
+ return;
}
+
+ $this->sendPhpResponse($exception);
}
/**
diff --git a/src/Symfony/Component/Debug/Tests/ExceptionHandlerTest.php b/src/Symfony/Component/Debug/Tests/ExceptionHandlerTest.php
index 26f889288f..d4b93c0838 100644
--- a/src/Symfony/Component/Debug/Tests/ExceptionHandlerTest.php
+++ b/src/Symfony/Component/Debug/Tests/ExceptionHandlerTest.php
@@ -13,71 +13,97 @@ namespace Symfony\Component\Debug\Tests;
use Symfony\Component\Debug\ExceptionHandler;
use Symfony\Component\Debug\Exception\OutOfMemoryException;
-use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
+require_once __DIR__.'/HeaderMock.php';
+
class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
{
+ protected function setUp()
+ {
+ testHeader();
+ }
+
+ protected function tearDown()
+ {
+ testHeader();
+ }
+
public function testDebug()
{
$handler = new ExceptionHandler(false);
- $response = $handler->createResponse(new \RuntimeException('Foo'));
- $this->assertContains('
Whoops, looks like something went wrong.
', $response->getContent());
- $this->assertNotContains('', $response->getContent());
+ ob_start();
+ $handler->sendPhpResponse(new \RuntimeException('Foo'));
+ $response = ob_get_clean();
+
+ $this->assertContains('Whoops, looks like something went wrong.
', $response);
+ $this->assertNotContains('', $response);
$handler = new ExceptionHandler(true);
- $response = $handler->createResponse(new \RuntimeException('Foo'));
- $this->assertContains('Whoops, looks like something went wrong.
', $response->getContent());
- $this->assertContains('', $response->getContent());
+ ob_start();
+ $handler->sendPhpResponse(new \RuntimeException('Foo'));
+ $response = ob_get_clean();
+
+ $this->assertContains('Whoops, looks like something went wrong.
', $response);
+ $this->assertContains('', $response);
}
public function testStatusCode()
{
- $handler = new ExceptionHandler(false);
+ $handler = new ExceptionHandler(false, 'iso8859-1');
- $response = $handler->createResponse(new \RuntimeException('Foo'));
- $this->assertEquals('500', $response->getStatusCode());
- $this->assertContains('Whoops, looks like something went wrong.', $response->getContent());
+ ob_start();
+ $handler->sendPhpResponse(new NotFoundHttpException('Foo'));
+ $response = ob_get_clean();
- $response = $handler->createResponse(new NotFoundHttpException('Foo'));
- $this->assertEquals('404', $response->getStatusCode());
- $this->assertContains('Sorry, the page you are looking for could not be found.', $response->getContent());
+ $this->assertContains('Sorry, the page you are looking for could not be found.', $response);
+
+ $expectedHeaders = array(
+ array('HTTP/1.0 404', true, null),
+ array('Content-Type: text/html; charset=iso8859-1', true, null),
+ );
+
+ $this->assertSame($expectedHeaders, testHeader());
}
public function testHeaders()
{
- $handler = new ExceptionHandler(false);
+ $handler = new ExceptionHandler(false, 'iso8859-1');
- $response = $handler->createResponse(new MethodNotAllowedHttpException(array('POST')));
- $this->assertEquals('405', $response->getStatusCode());
- $this->assertEquals('POST', $response->headers->get('Allow'));
+ ob_start();
+ $handler->sendPhpResponse(new MethodNotAllowedHttpException(array('POST')));
+ $response = ob_get_clean();
+
+ $expectedHeaders = array(
+ array('HTTP/1.0 405', true, null),
+ array('Allow: POST', false, null),
+ array('Content-Type: text/html; charset=iso8859-1', true, null),
+ );
+
+ $this->assertSame($expectedHeaders, testHeader());
}
public function testNestedExceptions()
{
$handler = new ExceptionHandler(true);
- $response = $handler->createResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
+ ob_start();
+ $handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
+ $response = ob_get_clean();
+
+ $this->assertStringMatchesFormat('%AFoo%ABar%A', $response);
}
public function testHandle()
{
$exception = new \Exception('foo');
- if (class_exists('Symfony\Component\HttpFoundation\Response')) {
- $handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('createResponse'));
- $handler
- ->expects($this->exactly(2))
- ->method('createResponse')
- ->will($this->returnValue(new Response()));
- } else {
- $handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('sendPhpResponse'));
- $handler
- ->expects($this->exactly(2))
- ->method('sendPhpResponse');
- }
+ $handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('sendPhpResponse'));
+ $handler
+ ->expects($this->exactly(2))
+ ->method('sendPhpResponse');
$handler->handle($exception);
@@ -93,18 +119,10 @@ class ExceptionHandlerTest extends \PHPUnit_Framework_TestCase
{
$exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__);
- if (class_exists('Symfony\Component\HttpFoundation\Response')) {
- $handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('createResponse'));
- $handler
- ->expects($this->once())
- ->method('createResponse')
- ->will($this->returnValue(new Response()));
- } else {
- $handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('sendPhpResponse'));
- $handler
- ->expects($this->once())
- ->method('sendPhpResponse');
- }
+ $handler = $this->getMock('Symfony\Component\Debug\ExceptionHandler', array('sendPhpResponse'));
+ $handler
+ ->expects($this->once())
+ ->method('sendPhpResponse');
$that = $this;
$handler->setHandler(function ($e) use ($that) {
diff --git a/src/Symfony/Component/Debug/Tests/HeaderMock.php b/src/Symfony/Component/Debug/Tests/HeaderMock.php
new file mode 100644
index 0000000000..65d0b58855
--- /dev/null
+++ b/src/Symfony/Component/Debug/Tests/HeaderMock.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Debug;
+
+function headers_sent()
+{
+ return false;
+}
+
+function header($str, $replace = true, $status = null)
+{
+ Tests\testHeader($str, $replace, $status);
+}
+
+namespace Symfony\Component\Debug\Tests;
+
+function testHeader()
+{
+ static $headers = array();
+
+ if (!$h = func_get_args()) {
+ $h = $headers;
+ $headers = array();
+
+ return $h;
+ }
+
+ $headers[] = func_get_args();
+}
diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json
index 17c56460cb..6e89d6d48a 100644
--- a/src/Symfony/Component/Debug/composer.json
+++ b/src/Symfony/Component/Debug/composer.json
@@ -25,12 +25,7 @@
"require-dev": {
"symfony/phpunit-bridge": "~2.7|~3.0.0",
"symfony/class-loader": "~2.2|~3.0.0",
- "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2|~3.0.0",
- "symfony/http-foundation": "~2.1|~3.0.0"
- },
- "suggest": {
- "symfony/http-foundation": "",
- "symfony/http-kernel": ""
+ "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2|~3.0.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Debug\\": "" }
diff --git a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
index 00dc60ca3f..297aab6fa1 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
@@ -140,7 +140,7 @@ class RouterListener implements EventSubscriberInterface
}
if (null !== $this->logger) {
- $this->logger->info(sprintf('Matched route "%s".', $parameters['_route']), array(
+ $this->logger->info(sprintf('Matched route "%s".', isset($parameters['_route']) ? $parameters['_route'] : 'n/a'), array(
'route_parameters' => $parameters,
'request_uri' => $request->getUri(),
));
diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php
index d6e5b45ba1..245b53acea 100644
--- a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php
@@ -128,4 +128,34 @@ class RouterListenerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('GET', $context->getMethod());
}
+
+ /**
+ * @dataProvider getLoggingParameterData
+ */
+ public function testLoggingParameter($parameter, $log)
+ {
+ $requestMatcher = $this->getMock('Symfony\Component\Routing\Matcher\RequestMatcherInterface');
+ $requestMatcher->expects($this->once())
+ ->method('matchRequest')
+ ->will($this->returnValue($parameter));
+
+ $logger = $this->getMock('Psr\Log\LoggerInterface');
+ $logger->expects($this->once())
+ ->method('info')
+ ->with($this->equalTo($log));
+
+ $kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
+ $request = Request::create('http://localhost/');
+
+ $listener = new RouterListener($requestMatcher, new RequestContext(), $logger, $this->requestStack);
+ $listener->onKernelRequest(new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST));
+ }
+
+ public function getLoggingParameterData()
+ {
+ return array(
+ array(array('_route' => 'foo'), 'Matched route "foo".'),
+ array(array(), 'Matched route "n/a".'),
+ );
+ }
}
diff --git a/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php b/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php
index 38254fa036..5a4b35519f 100644
--- a/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php
+++ b/src/Symfony/Component/Intl/ResourceBundle/CurrencyBundle.php
@@ -76,7 +76,7 @@ class CurrencyBundle extends CurrencyDataProvider implements CurrencyBundleInter
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
@@ -112,7 +112,7 @@ class CurrencyBundle extends CurrencyDataProvider implements CurrencyBundleInter
try {
return $this->localeProvider->getLocales();
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
}
diff --git a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php
index bb393d2063..cfe82ca3c3 100644
--- a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php
+++ b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php
@@ -80,7 +80,7 @@ class LanguageBundle extends LanguageDataProvider implements LanguageBundleInter
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
@@ -104,7 +104,7 @@ class LanguageBundle extends LanguageDataProvider implements LanguageBundleInter
try {
return $this->scriptProvider->getNames($displayLocale);
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
@@ -116,7 +116,7 @@ class LanguageBundle extends LanguageDataProvider implements LanguageBundleInter
try {
return $this->localeProvider->getLocales();
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
}
diff --git a/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php b/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php
index 22c9aecfb3..b14048a40f 100644
--- a/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php
+++ b/src/Symfony/Component/Intl/ResourceBundle/LocaleBundle.php
@@ -31,7 +31,7 @@ class LocaleBundle extends LocaleDataProvider implements LocaleBundleInterface
try {
return parent::getLocales();
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
@@ -55,7 +55,7 @@ class LocaleBundle extends LocaleDataProvider implements LocaleBundleInterface
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
}
diff --git a/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php b/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php
index 126d62ac04..29697d6883 100644
--- a/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php
+++ b/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php
@@ -64,7 +64,7 @@ class RegionBundle extends RegionDataProvider implements RegionBundleInterface
try {
return $this->getNames($displayLocale);
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
@@ -76,7 +76,7 @@ class RegionBundle extends RegionDataProvider implements RegionBundleInterface
try {
return $this->localeProvider->getLocales();
} catch (MissingResourceException $e) {
- return;
+ return array();
}
}
}
diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf
index 63eecc0e19..a58f5b8d8c 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.ja.xlf
@@ -175,7 +175,7 @@
画像の高さが小さすぎます({{ height }}ピクセル)。{{ min_height }}ピクセル以上にしてください。
-
+
ユーザーの現在のパスワードでなければなりません。
diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf
index 0237a308ac..d5b57031b9 100644
--- a/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf
+++ b/src/Symfony/Component/Validator/Resources/translations/validators.th.xlf
@@ -175,7 +175,7 @@
ความสูงของภาพไม่ได้ขนาด ({{ height }}px) อนุญาตให้สูงอย่างน้อยที่สุด {{ min_height }}px
-
+
ค่านี้ควรจะเป็นรหัสผ่านปัจจุบันของผู้ใช้