Compare commits

..

3 Commits

Author SHA1 Message Date
Fabien Potencier
8d4977c296 Merge branch '2.8' into 3.2
* 2.8:
  Using FQ name for PHP_VERSION_ID
  [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323
  Harden the debugging of Twig filters and functions
  bumped Symfony version to 2.8.22
  updated VERSION for 2.8.21
  updated CHANGELOG for 2.8.21
  bumped Symfony version to 2.7.29
  updated VERSION for 2.7.28
  update CONTRIBUTORS for 2.7.28
  updated CHANGELOG for 2.7.28
2017-06-01 14:00:24 -07:00
Fabien Potencier
8470d77011 Merge branch '2.7' into 2.8
* 2.7:
  Using FQ name for PHP_VERSION_ID
  [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323
  Harden the debugging of Twig filters and functions
  bumped Symfony version to 2.7.29
  updated VERSION for 2.7.28
  update CONTRIBUTORS for 2.7.28
  updated CHANGELOG for 2.7.28
2017-06-01 13:52:29 -07:00
Fabien Potencier
2662c21dea Using FQ name for PHP_VERSION_ID 2017-06-01 13:44:56 -07:00
15 changed files with 101 additions and 257 deletions

View File

@@ -1,11 +1,6 @@
CHANGELOG
=========
3.3.0
-----
* deprecated the `ContextErrorException` class: use \ErrorException directly now
3.2.0
-----

View File

@@ -27,8 +27,6 @@ class DebugClassLoader
private $classLoader;
private $isFinder;
private static $caseCheck;
private static $final = array();
private static $finalMethods = array();
private static $deprecated = array();
private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
private static $darwinCache = array('/' => array('/', array()));
@@ -162,51 +160,14 @@ class DebugClassLoader
$name = $refl->getName();
if ($name !== $class && 0 === strcasecmp($name, $class)) {
throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
}
$parent = get_parent_class($class);
// Not an interface nor a trait
if (class_exists($name, false)) {
if (preg_match('#\n \* @final(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
self::$final[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
}
if ($parent && isset(self::$final[$parent])) {
@trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED);
}
// Inherit @final annotations
self::$finalMethods[$name] = $parent && isset(self::$finalMethods[$parent]) ? self::$finalMethods[$parent] : array();
foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
if ($method->class !== $name) {
continue;
}
if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
@trigger_error(sprintf('%s It may change without further notice as of its next major version. You should not extend it from "%s".', self::$finalMethods[$parent][$method->name], $name), E_USER_DEPRECATED);
}
$doc = $method->getDocComment();
if (false === $doc || false === strpos($doc, '@final')) {
continue;
}
if (preg_match('#\n\s+\* @final(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
$message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
self::$finalMethods[$name][$method->name] = sprintf('The "%s::%s()" method is considered final%s.', $name, $method->name, $message);
}
}
throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
}
if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
@trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
@trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
} elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
} else {
// Don't trigger deprecations for classes in the same vendor
if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) {
$len = 0;
$ns = '';
@@ -220,10 +181,11 @@ class DebugClassLoader
break;
}
}
$parent = get_parent_class($class);
if (!$parent || strncmp($ns, $parent, $len)) {
if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
@trigger_error(sprintf('The "%s" class extends "%s" that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
@trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
}
$parentInterfaces = array();
@@ -245,7 +207,7 @@ class DebugClassLoader
foreach ($deprecatedInterfaces as $interface) {
if (!isset($parentInterfaces[$interface])) {
@trigger_error(sprintf('The "%s" %s "%s" that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
@trigger_error(sprintf('The %s %s %s that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
}
}
}
@@ -342,7 +304,7 @@ class DebugClassLoader
if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
&& 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
) {
throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)));
throw new \RuntimeException(sprintf('Case mismatch between class and real file names: %s vs %s in %s', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)));
}
}

View File

@@ -534,6 +534,9 @@ class ErrorHandler
}
} elseif ($exception instanceof \ErrorException) {
$message = 'Uncaught '.$exception->getMessage();
if ($exception instanceof ContextErrorException) {
$e['context'] = $exception->getContext();
}
} else {
$message = 'Uncaught Exception: '.$exception->getMessage();
}

View File

@@ -15,8 +15,6 @@ namespace Symfony\Component\Debug\Exception;
* Error Exception with Variable Context.
*
* @author Christian Sciberras <uuf6429@gmail.com>
*
* @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0.
*/
class ContextErrorException extends \ErrorException
{
@@ -33,8 +31,6 @@ class ContextErrorException extends \ErrorException
*/
public function getContext()
{
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
return $this->context;
}
}

View File

@@ -11,7 +11,6 @@
namespace Symfony\Component\Debug\Exception;
use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
/**
@@ -42,8 +41,6 @@ class FlattenException
if ($exception instanceof HttpExceptionInterface) {
$statusCode = $exception->getStatusCode();
$headers = array_merge($headers, $exception->getHeaders());
} elseif ($exception instanceof RequestExceptionInterface) {
$statusCode = 400;
}
if (null === $statusCode) {

File diff suppressed because one or more lines are too long

View File

@@ -61,7 +61,7 @@ class DebugClassLoaderTest extends TestCase
public function testUnsilencing()
{
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
$this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.');
}
if (defined('HHVM_VERSION')) {
@@ -109,7 +109,7 @@ class DebugClassLoaderTest extends TestCase
} catch (\ErrorException $exception) {
// if an exception is thrown, the test passed
$this->assertStringStartsWith(__FILE__, $exception->getFile());
if (PHP_VERSION_ID < 70000) {
if (\PHP_VERSION_ID < 70000) {
$this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage());
$this->assertEquals(E_STRICT, $exception->getSeverity());
} else {
@@ -185,7 +185,7 @@ class DebugClassLoaderTest extends TestCase
$xError = array(
'type' => E_USER_DEPRECATED,
'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.',
'message' => 'The Test\Symfony\Component\Debug\Tests\\'.$class.' class '.$type.' Symfony\Component\Debug\Tests\Fixtures\\'.$super.' that is deprecated but this is a test deprecation notice.',
);
$this->assertSame($xError, $lastError);
@@ -245,7 +245,7 @@ class DebugClassLoaderTest extends TestCase
public function testReservedForPhp7()
{
if (PHP_VERSION_ID >= 70000) {
if (\PHP_VERSION_ID >= 70000) {
$this->markTestSkipped('PHP7 already prevents using reserved names.');
}
@@ -263,51 +263,7 @@ class DebugClassLoaderTest extends TestCase
$xError = array(
'type' => E_USER_DEPRECATED,
'message' => 'The "Test\Symfony\Component\Debug\Tests\Float" class uses the reserved name "Float", it will break on PHP 7 and higher',
);
$this->assertSame($xError, $lastError);
}
public function testExtendedFinalClass()
{
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true);
error_reporting($e);
restore_error_handler();
$lastError = error_get_last();
unset($lastError['file'], $lastError['line']);
$xError = array(
'type' => E_USER_DEPRECATED,
'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".',
);
$this->assertSame($xError, $lastError);
}
public function testExtendedFinalMethod()
{
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true);
error_reporting($e);
restore_error_handler();
$lastError = error_get_last();
unset($lastError['file'], $lastError['line']);
$xError = array(
'type' => E_USER_DEPRECATED,
'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".',
'message' => 'Test\Symfony\Component\Debug\Tests\Float uses a reserved class name (Float) that will break on PHP 7 and higher',
);
$this->assertSame($xError, $lastError);
@@ -345,12 +301,6 @@ class ClassLoader
return $fixtureDir.'notPsr0Bis.php';
} elseif (__NAMESPACE__.'\Fixtures\DeprecatedInterface' === $class) {
return $fixtureDir.'DeprecatedInterface.php';
} elseif (__NAMESPACE__.'\Fixtures\FinalClass' === $class) {
return $fixtureDir.'FinalClass.php';
} elseif (__NAMESPACE__.'\Fixtures\FinalMethod' === $class) {
return $fixtureDir.'FinalMethod.php';
} elseif (__NAMESPACE__.'\Fixtures\ExtendedFinalMethod' === $class) {
return $fixtureDir.'ExtendedFinalMethod.php';
} elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) {
eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}');
} elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) {
@@ -361,8 +311,6 @@ class ClassLoader
eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}');
} elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}');
}
}
}

View File

@@ -15,6 +15,7 @@ use PHPUnit\Framework\TestCase;
use Psr\Log\LogLevel;
use Symfony\Component\Debug\BufferingLogger;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\Exception\ContextErrorException;
use Symfony\Component\Debug\Exception\SilencedErrorContext;
/**
@@ -71,12 +72,13 @@ class ErrorHandlerTest extends TestCase
try {
self::triggerNotice($this);
$this->fail('ErrorException expected');
} catch (\ErrorException $exception) {
$this->fail('ContextErrorException expected');
} catch (ContextErrorException $exception) {
// if an exception is thrown, the test passed
$this->assertEquals(E_NOTICE, $exception->getSeverity());
$this->assertEquals(__FILE__, $exception->getFile());
$this->assertRegExp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
$this->assertArrayHasKey('foobar', $exception->getContext());
$trace = $exception->getTrace();

View File

@@ -13,7 +13,6 @@ namespace Symfony\Component\Debug\Tests\Exception;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
@@ -80,11 +79,6 @@ class FlattenExceptionTest extends TestCase
$flattened = FlattenException::create(new UnsupportedMediaTypeHttpException());
$this->assertEquals('415', $flattened->getStatusCode());
if (class_exists(SuspiciousOperationException::class)) {
$flattened = FlattenException::create(new SuspiciousOperationException());
$this->assertEquals('400', $flattened->getStatusCode());
}
}
public function testHeadersForHttpException()

View File

@@ -39,8 +39,8 @@ class ExceptionHandlerTest extends TestCase
$handler->sendPhpResponse(new \RuntimeException('Foo'));
$response = ob_get_clean();
$this->assertContains('Whoops, looks like something went wrong.', $response);
$this->assertNotContains('<div class="trace trace-as-html">', $response);
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response);
$this->assertNotContains('<h2 class="block_exception clear_fix">', $response);
$handler = new ExceptionHandler(true);
@@ -48,8 +48,8 @@ class ExceptionHandlerTest extends TestCase
$handler->sendPhpResponse(new \RuntimeException('Foo'));
$response = ob_get_clean();
$this->assertContains('Whoops, looks like something went wrong.', $response);
$this->assertContains('<div class="trace trace-as-html">', $response);
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response);
$this->assertContains('<h2 class="block_exception clear_fix">', $response);
}
public function testStatusCode()
@@ -94,7 +94,7 @@ class ExceptionHandlerTest extends TestCase
$handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
$response = ob_get_clean();
$this->assertStringMatchesFormat('%A<p class="break-long-words trace-message">Foo</p>%A<p class="break-long-words trace-message">Bar</p>%A', $response);
$this->assertStringMatchesFormat('%A<span class="exception_message">Foo</span>%A<span class="exception_message">Bar</span>%A', $response);
}
public function testHandle()

View File

@@ -13,6 +13,7 @@ namespace Symfony\Component\Debug\Tests\FatalErrorHandler;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
use Symfony\Component\Debug\DebugClassLoader;
use Composer\Autoload\ClassLoader as ComposerClassLoader;
@@ -69,10 +70,12 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
public function provideClassNotFoundData()
{
$autoloader = new ComposerClassLoader();
$autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception'));
$prefixes = array('Symfony\Component\Debug\Exception\\' => realpath(__DIR__.'/../../Exception'));
$debugClassLoader = new DebugClassLoader(array($autoloader, 'loadClass'));
$symfonyAutoloader = new SymfonyClassLoader();
$symfonyAutoloader->addPrefixes($prefixes);
$debugClassLoader = new DebugClassLoader(array($symfonyAutoloader, 'loadClass'));
return array(
array(
@@ -128,7 +131,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
),
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
array($autoloader, 'loadClass'),
array($symfonyAutoloader, 'loadClass'),
),
array(
array(

View File

@@ -1,17 +0,0 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
class ExtendedFinalMethod extends FinalMethod
{
/**
* {@inheritdoc}
*/
public function finalMethod()
{
}
public function anotherMethod()
{
}
}

View File

@@ -1,10 +0,0 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @final since version 3.3.
*/
class FinalClass
{
}

View File

@@ -1,17 +0,0 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
class FinalMethod
{
/**
* @final since version 3.3.
*/
public function finalMethod()
{
}
public function anotherMethod()
{
}
}

View File

@@ -23,6 +23,7 @@
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
"symfony/class-loader": "~2.8|~3.0",
"symfony/http-kernel": "~2.8|~3.0"
},
"autoload": {
@@ -34,7 +35,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "3.3-dev"
"dev-master": "3.2-dev"
}
}
}