Compare commits

..

45 Commits

Author SHA1 Message Date
Nicolas Grekas
5aca4aa960 [2.7] Workaround https://bugs.php.net/63206 2016-01-13 08:57:33 +01:00
Fabien Potencier
b5b13b1909 Merge branch '2.3' into 2.7
* 2.3:
  Update copyright year
  [2.3] Static Code Analysis for Components
2016-01-03 16:32:00 +01:00
Diego Saint Esteben
7cca5bb1b1 Update copyright year 2016-01-01 23:53:47 -03:00
Nicolas Grekas
8446878685 Merge branch '2.3' into 2.7
* 2.3:
  [travis] timeout the sigchild tests at 60s
  CS: Single line comments should use double slashes (//) and not hash (#).
  Do not use HttpKernel Extension when not needed
  bumped Symfony version to 2.3.37
  updated VERSION for 2.3.36
  update CONTRIBUTORS for 2.3.36
  updated CHANGELOG for 2.3.36
  use nowdoc instead of heredoc

Conflicts:
	src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php
	src/Symfony/Bundle/FrameworkBundle/Command/RouterApacheDumperCommand.php
	src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php
	src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
	src/Symfony/Bundle/TwigBundle/Command/LintCommand.php
	src/Symfony/Component/Config/Tests/Definition/Dumper/YamlReferenceDumperTest.php
	src/Symfony/Component/Debug/ExceptionHandler.php
	src/Symfony/Component/HttpKernel/Kernel.php
	src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php
2015-12-28 14:11:03 +01:00
Fabien Potencier
08589346bd Revert "Revert "bug #17052 [2.7] Fixed flatten exception recursion with errors (GrahamCampbell)""
This reverts commit e60889ac4d85e6ec1083ab95dc84b2b3c0a95dd6.
2015-12-26 15:05:15 +01:00
Fabien Potencier
2d9eb3ddb3 Merge branch '2.3' into 2.7
* 2.3:
  Revert "bug #17052 [2.7] Fixed flatten exception recursion with errors (GrahamCampbell)"
2015-12-26 15:02:48 +01:00
Fabien Potencier
5f109a38d2 Revert "bug #17052 [2.7] Fixed flatten exception recursion with errors (GrahamCampbell)"
This reverts commit af3f4eaa2b37bca77274b670e96a695f3e46c4e5, reversing
changes made to 021ab8a7b35cac053442124e04cd87e2e1ef43cd.
2015-12-26 15:02:40 +01:00
Fabien Potencier
cfc52f64af Merge branch '2.3' into 2.7
* 2.3:
  [2.7] Fixed flatten exception recursion with errors
  Embedded identifier support
  Change the ExtensionInterface load method definition to bo identical to the documentation.
  add and correct armenian translations
  [Config] Fix array sort on normalization in edge case
  [Yaml] fix indented line handling in folded blocks
  improve BrowserKit test coverage p1
2015-12-26 14:37:43 +01:00
Graham Campbell
efac4e1daf [2.7] Fixed flatten exception recursion with errors 2015-12-26 13:17:22 +01:00
Gregor Harlan
d0ee40c1e2 use nowdoc instead of heredoc 2015-12-21 17:05:00 +01:00
Tobias Schultze
e131370c3c [Debug] fix readme: DebugClassLoader moved to debug itself 2015-11-26 21:02:12 +01:00
Nicolas Grekas
489c11d549 [Debug] Ensure class declarations are loaded only once 2015-11-24 12:55:28 +01:00
Nicolas Grekas
c0f543d3c4 Add missing exclusions from phpunit.xml.dist 2015-11-18 09:19:46 +01:00
Fabien Potencier
0dbc119596 Merge branch '2.3' into 2.7
* 2.3:
  added the new Composer exclude-from-classmap option
  fix expected argument type docblock
  Set back libxml settings after testings.
  fixed Twig deprecation notices
2015-10-30 13:10:21 -07:00
Anne-Sophie Bachelard
89e1a14dfd added the new Composer exclude-from-classmap option 2015-10-30 12:48:51 -07:00
Nicolas Grekas
fb9e6887db Merge branch '2.3' into 2.7
* 2.3:
  [ci] SymfonyTestsListener is now auto-registered
  adds validation messages missing italian translations
2015-10-11 11:39:48 +02:00
Nicolas Grekas
e1aa457a97 [ci] SymfonyTestsListener is now auto-registered 2015-10-11 11:37:49 +02:00
Nicolas Grekas
64e916c356 Merge branch '2.3' into 2.7
* 2.3:
  [tests] Use @requires annotation when possible
  [ci] Enable collecting and replaying skipped tests
  [Process] Workaround buggy PHP warning
  [Console] Add additional ways to detect OS400 platform
  [Yaml] Allow tabs before comments at the end of a line

Conflicts:
	composer.json
	src/Symfony/Bridge/Doctrine/Tests/Logger/DbalLoggerTest.php
	src/Symfony/Bridge/Monolog/composer.json
	src/Symfony/Bridge/Twig/composer.json
	src/Symfony/Bundle/FrameworkBundle/composer.json
	src/Symfony/Bundle/SecurityBundle/composer.json
	src/Symfony/Component/Asset/composer.json
	src/Symfony/Component/ClassLoader/Tests/LegacyApcUniversalClassLoaderTest.php
	src/Symfony/Component/Console/composer.json
	src/Symfony/Component/Debug/composer.json
	src/Symfony/Component/DomCrawler/composer.json
	src/Symfony/Component/EventDispatcher/composer.json
	src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php
	src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php
	src/Symfony/Component/HttpFoundation/composer.json
	src/Symfony/Component/Intl/composer.json
	src/Symfony/Component/Routing/composer.json
	src/Symfony/Component/Security/composer.json
	src/Symfony/Component/Serializer/composer.json
	src/Symfony/Component/Templating/composer.json
	src/Symfony/Component/Translation/composer.json
	src/Symfony/Component/Validator/composer.json
2015-10-10 11:26:25 +02:00
Nicolas Grekas
e9470b1f9e [ci] Enable collecting and replaying skipped tests 2015-10-10 10:46:02 +02:00
Tobias Schultze
fc037263d5 remove api tags that are new in 2.7 2015-09-29 14:08:33 +02:00
Nicolas Grekas
c79c361bca [Debug] Fix case mismatch detection 2015-09-14 10:41:38 +02:00
Nicolas Grekas
726bf9651d [Debug] Ignore silencing for deprecations 2015-08-29 13:12:16 +02:00
Nicolas Grekas
22b295edff [Debug/VarDumper] minor cleanups 2015-08-17 10:58:33 +02:00
Nicolas Grekas
8e122417c0 bug #15443 [Debug] Enhance DebugClassLoader performance on MacOSX (nicolas-grekas)
This PR was merged into the 2.7 branch.

Discussion
----------

[Debug] Enhance DebugClassLoader performance on MacOSX

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #15442
| License       | MIT
| Doc PR        | -

Commits
-------

af0b8eb [Debug] Enhance DebugClassLoader performance on MacOSX
2015-08-07 08:54:57 +02:00
Elan Ruusamäe
9cb55ce279 fix debug-ext 003.phpt
in my environment the filename is filled, not "-"

$ php --version
PHP 5.5.27 (cli) (built: Jul 17 2015 12:32:05)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies
2015-08-07 08:53:47 +02:00
Nicolas Grekas
2651b63b15 [Debug] Enhance DebugClassLoader performance on MacOSX 2015-08-04 12:48:55 +02:00
Nicolas Grekas
aea19edb4a [Debug] cleanup ExceptionHandlerTest 2015-07-31 17:18:52 +02:00
Nicolas Grekas
77d632fd72 [php7] Fix for substr() always returning a string 2015-07-28 14:38:40 +02:00
Fabien Potencier
9daa1bf9f7 Merge branch '2.6' into 2.7
* 2.6:
  Added 'default' color
  [HttpFoundation] Reload the session after regenerating its id
  [HttpFoundation] Add a test case to confirm a bug in session migration
  [2.6] Static Code Analysis for Components and Bundles
  [Finder] Command::addAtIndex() fails with Command instance argument
  [DependencyInjection] Freeze also FrozenParameterBag::remove
  [Twig][Bridge] replaced `extends` with `use` in bootstrap_3_horizontal_layout.html.twig
  fix CS
  fixed CS
  Add a way to reset the singleton
  [Security] allow to use `method` in XML configs
  Remove duplicate example
  Remove var not used due to returning early (introduced in 8982c32)
  Enhance hhvm test skip message
2015-07-09 18:07:40 +02:00
Vladimir Reznichenko
fca5696e0c [2.6] Static Code Analysis for Components and Bundles 2015-07-08 07:59:48 +02:00
Nicolas Grekas
20c5dad1af Enhance hhvm test skip message 2015-07-03 07:54:45 +02:00
Nicolas Grekas
8f1257608f Towards 100% HHVM compat 2015-06-30 15:39:12 +02:00
Nicolas Grekas
3cfb19034c [PhpUnitBridge] Enforce @-silencing of deprecation notices according to new policy 2015-06-18 21:21:56 +02:00
Nicolas Grekas
6136637a77 Merge branch '2.6' into 2.7
* 2.6:
  Add test for HHVM FatalErrors
  [2.6][Debug] Fix fatal-errors handling on HHVM
  [2.3][Debug] Fix fatal-errors handling on HHVM
  Standardize the name of the exception variables
  [2.3] Static Code Analysis for Components
  Remove duplicated paths

Conflicts:
	src/Symfony/Component/Debug/ErrorHandler.php
	src/Symfony/Component/Security/Http/Firewall/BasicAuthenticationListener.php
	src/Symfony/Component/Security/Http/Firewall/ContextListener.php
	src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php
	src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php
2015-06-18 15:03:50 +02:00
Robert Schönthal
ef29e641f1 Add test for HHVM FatalErrors 2015-06-18 11:59:18 +02:00
Nicolas Grekas
92818ecdba [2.6][Debug] Fix fatal-errors handling on HHVM 2015-06-18 11:42:58 +02:00
Nicolas Grekas
c20499a2c8 Merge branch '2.6' into 2.7
* 2.6:
  [Debug] Fix log level of stacked errors
  [VarDumper] Fix uninitialized id in HtmlDumper
  Fixed fluent interface
  [Debug] fix debug class loader case test on windows
  [Debug+VarDumper] Fix handling of PHP7 exception/error model
  [2.6][Security][Translation] #14920 update translations
  [VarDumper] Cherry-pick code style fixes from 2.7
  Bug #14836 [HttpFoundation] Moves default JSON encoding assignment from constructor to property

Conflicts:
	src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php
	src/Symfony/Component/VarDumper/Caster/DOMCaster.php
	src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php
	src/Symfony/Component/VarDumper/Caster/PdoCaster.php
	src/Symfony/Component/VarDumper/Caster/SplCaster.php
2015-06-18 10:00:47 +02:00
Fabien Potencier
636d9b2edf bug #14959 [Debug+VarDumper] Fix handling of PHP7 "Throwable" exceptions (nicolas-grekas)
This PR was merged into the 2.6 branch.

Discussion
----------

[Debug+VarDumper] Fix handling of PHP7 "Throwable" exceptions

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | -
| License       | MIT
| Doc PR        | -

PHP7 may introduce the Throwable interface if the corresponding RFC is accepted (see https://wiki.php.net/rfc/throwable-interface)
This PR adds support for it. We should wait for final approval of the RFC before merging it.

Commits
-------

4dc727f [Debug+VarDumper] Fix handling of PHP7 exception/error model
edf793e [VarDumper] Cherry-pick code style fixes from 2.7
2015-06-17 23:08:37 +02:00
Nicolas Grekas
ce0589b0aa [Debug] Fix log level of stacked errors 2015-06-17 21:16:58 +02:00
Nicolas Grekas
192dd832b3 [2.7] Fix unsilenced deprecation notices 2015-06-16 15:26:24 +02:00
Nicolas Grekas
355f12cf08 [2.3][Debug] Fix fatal-errors handling on HHVM 2015-06-16 14:35:43 +02:00
Tobias Schultze
e4b7fc3e49 [Debug] fix debug class loader case test on windows 2015-06-16 13:27:45 +02:00
Nicolas Grekas
66eb82f37f [Debug+VarDumper] Fix handling of PHP7 exception/error model 2015-06-15 17:25:25 +02:00
Vladimir Reznichenko
ff6a582db5 Php Inspections (EA Extended): - resolved possible PHP Fatal in \Symfony\Component\BrowserKit\Cookie::__toString -resolved implicit magic methods calls -resolved callable name case mismatches 2015-05-29 19:14:48 +02:00
Nicolas Grekas
30d1de52f1 Fix HTML escaping of to-source links 2015-05-19 17:44:44 -07:00
18 changed files with 426 additions and 155 deletions

View File

@@ -21,8 +21,6 @@ namespace Symfony\Component\Debug;
* @author Fabien Potencier <fabien@symfony.com>
* @author Christophe Coevoet <stof@notk.org>
* @author Nicolas Grekas <p@tchwork.com>
*
* @api
*/
class DebugClassLoader
{
@@ -32,13 +30,12 @@ class DebugClassLoader
private static $caseCheck;
private static $deprecated = array();
private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
private static $darwinCache = array('/' => array('/', array()));
/**
* Constructor.
*
* @param callable|object $classLoader Passing an object is @deprecated since version 2.5 and support for it will be removed in 3.0
*
* @api
*/
public function __construct($classLoader)
{
@@ -150,7 +147,7 @@ class DebugClassLoader
try {
if ($this->isFinder) {
if ($file = $this->classLoader[0]->findFile($class)) {
require $file;
require_once $file;
}
} else {
call_user_func($this->classLoader, $class);
@@ -179,7 +176,7 @@ class DebugClassLoader
}
if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
trigger_error(sprintf('%s uses a reserved class name (%s) that 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 {
@@ -220,35 +217,89 @@ class DebugClassLoader
throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file));
}
if (self::$caseCheck && preg_match('#([/\\\\][a-zA-Z_\x7F-\xFF][a-zA-Z0-9_\x7F-\xFF]*)+\.(php|hh)$#D', $file, $tail)) {
$tail = $tail[0];
$real = $refl->getFilename();
if (self::$caseCheck) {
$real = explode('\\', $class.strrchr($file, '.'));
$tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
$i = count($tail) - 1;
$j = count($real) - 1;
while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
--$i;
--$j;
}
array_splice($tail, 0, $i + 1);
}
if (self::$caseCheck && $tail) {
$tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
$tailLen = strlen($tail);
$real = $refl->getFileName();
if (2 === self::$caseCheck) {
// realpath() on MacOSX doesn't normalize the case of characters
$cwd = getcwd();
$basename = strrpos($real, '/');
chdir(substr($real, 0, $basename));
$basename = substr($real, $basename + 1);
// glob() patterns are case-sensitive even if the underlying fs is not
if (!in_array($basename, glob($basename.'*', GLOB_NOSORT), true)) {
$real = getcwd().'/';
$h = opendir('.');
while (false !== $f = readdir($h)) {
if (0 === strcasecmp($f, $basename)) {
$real .= $f;
break;
$i = 1 + strrpos($real, '/');
$file = substr($real, $i);
$real = substr($real, 0, $i);
if (isset(self::$darwinCache[$real])) {
$kDir = $real;
} else {
$kDir = strtolower($real);
if (isset(self::$darwinCache[$kDir])) {
$real = self::$darwinCache[$kDir][0];
} else {
$dir = getcwd();
chdir($real);
$real = getcwd().'/';
chdir($dir);
$dir = $real;
$k = $kDir;
$i = strlen($dir) - 1;
while (!isset(self::$darwinCache[$k])) {
self::$darwinCache[$k] = array($dir, array());
self::$darwinCache[$dir] = &self::$darwinCache[$k];
while ('/' !== $dir[--$i]) {
}
$k = substr($k, 0, ++$i);
$dir = substr($dir, 0, $i--);
}
}
closedir($h);
}
chdir($cwd);
$dirFiles = self::$darwinCache[$kDir][1];
if (isset($dirFiles[$file])) {
$kFile = $file;
} else {
$kFile = strtolower($file);
if (!isset($dirFiles[$kFile])) {
foreach (scandir($real, 2) as $f) {
if ('.' !== $f[0]) {
$dirFiles[$f] = $f;
if ($f === $file) {
$kFile = $k = $file;
} elseif ($f !== $k = strtolower($f)) {
$dirFiles[$k] = $f;
}
}
}
self::$darwinCache[$kDir][1] = $dirFiles;
}
}
$real .= $dirFiles[$kFile];
}
if (0 === substr_compare($real, $tail, -strlen($tail), strlen($tail), true)
&& 0 !== substr_compare($real, $tail, -strlen($tail), strlen($tail), false)
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 source file names: %s vs %s', $class, $real));
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

@@ -14,8 +14,8 @@ namespace Symfony\Component\Debug;
use Psr\Log\LogLevel;
use Psr\Log\LoggerInterface;
use Symfony\Component\Debug\Exception\ContextErrorException;
use Symfony\Component\Debug\Exception\FatalBaseException;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Symfony\Component\Debug\Exception\OutOfMemoryException;
use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
@@ -95,6 +95,7 @@ class ErrorHandler
private $loggedTraces = array();
private $isRecursive = 0;
private $isRoot = false;
private $exceptionHandler;
private static $reservedMemory;
@@ -134,7 +135,12 @@ class ErrorHandler
$handler = new static();
}
$prev = set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
restore_error_handler();
// Specifying the error types earlier would expose us to https://bugs.php.net/63206
set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
$handler->isRoot = true;
}
if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
$handler = $prev[0];
@@ -251,7 +257,7 @@ class ErrorHandler
public function throwAt($levels, $replace = false)
{
$prev = $this->thrownErrors;
$this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
$this->thrownErrors = (E_ALL | E_STRICT) & ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
if (!$replace) {
$this->thrownErrors |= $prev;
}
@@ -326,12 +332,16 @@ class ErrorHandler
private function reRegister($prev)
{
if ($prev !== $this->thrownErrors | $this->loggedErrors) {
$handler = set_error_handler('var_dump', 0);
$handler = set_error_handler('var_dump');
$handler = is_array($handler) ? $handler[0] : null;
restore_error_handler();
if ($handler === $this) {
restore_error_handler();
set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
if ($this->isRoot) {
set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
} else {
set_error_handler(array($this, 'handleError'));
}
}
}
}
@@ -350,9 +360,9 @@ class ErrorHandler
*
* @internal
*/
public function handleError($type, $message, $file, $line, array $context)
public function handleError($type, $message, $file, $line, array $context, array $backtrace = null)
{
$level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR;
$level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
$log = $this->loggedErrors & $type;
$throw = $this->thrownErrors & $type & $level;
$type &= $level | $this->screamedErrors;
@@ -367,6 +377,15 @@ class ErrorHandler
$context = $e;
}
if (null !== $backtrace && $type & E_ERROR) {
// E_ERROR fatal errors are triggered on HHVM when
// hhvm.error_handling.call_user_handler_on_fatals=1
// which is the way to get their backtrace.
$this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
return true;
}
if ($throw) {
if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
// Checking for class existence is a work around for https://bugs.php.net/42098
@@ -402,17 +421,24 @@ class ErrorHandler
if ($this->scopedErrors & $type) {
$e['scope_vars'] = $context;
if ($trace) {
$e['stack'] = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
$e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
}
} elseif ($trace) {
$e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
if (null === $backtrace) {
$e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
} else {
foreach ($backtrace as &$frame) {
unset($frame['args'], $frame);
}
$e['stack'] = $backtrace;
}
}
}
if ($this->isRecursive) {
$log = 0;
} elseif (self::$stackedErrorLevels) {
self::$stackedErrors[] = array($this->loggers[$type], $message, $e);
self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
} else {
try {
$this->isRecursive = true;
@@ -429,17 +455,17 @@ class ErrorHandler
}
/**
* Handles an exception by logging then forwarding it to an other handler.
* Handles an exception by logging then forwarding it to another handler.
*
* @param \Exception|\BaseException $exception An exception to handle
* @param array $error An array as returned by error_get_last()
* @param \Exception|\Throwable $exception An exception to handle
* @param array $error An array as returned by error_get_last()
*
* @internal
*/
public function handleException($exception, array $error = null)
{
if (!$exception instanceof \Exception) {
$exception = new FatalBaseException($exception);
$exception = new FatalThrowableError($exception);
}
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
@@ -451,15 +477,17 @@ class ErrorHandler
'level' => error_reporting(),
'stack' => $exception->getTrace(),
);
if ($exception instanceof FatalBaseException) {
$error = array(
'type' => $type,
'message' => $message = $exception->getMessage(),
'file' => $e['file'],
'line' => $e['line'],
);
} elseif ($exception instanceof FatalErrorException) {
$message = 'Fatal '.$exception->getMessage();
if ($exception instanceof FatalErrorException) {
if ($exception instanceof FatalThrowableError) {
$error = array(
'type' => $type,
'message' => $message = $exception->getMessage(),
'file' => $e['file'],
'line' => $e['line'],
);
} else {
$message = 'Fatal '.$exception->getMessage();
}
} elseif ($exception instanceof \ErrorException) {
$message = 'Uncaught '.$exception->getMessage();
if ($exception instanceof ContextErrorException) {
@@ -486,9 +514,9 @@ class ErrorHandler
try {
call_user_func($this->exceptionHandler, $exception);
} catch (\Exception $handlerException) {
$this->exceptionHandler = null;
$this->handleException($handlerException);
} catch (\BaseException $handlerException) {
} catch (\Throwable $handlerException) {
}
if (isset($handlerException)) {
$this->exceptionHandler = null;
$this->handleException($handlerException);
}
@@ -503,9 +531,13 @@ class ErrorHandler
*/
public static function handleFatalError(array $error = null)
{
self::$reservedMemory = '';
if (null === self::$reservedMemory) {
return;
}
$handler = set_error_handler('var_dump', 0);
self::$reservedMemory = null;
$handler = set_error_handler('var_dump');
$handler = is_array($handler) ? $handler[0] : null;
restore_error_handler();
@@ -525,14 +557,15 @@ class ErrorHandler
// Handled below
}
if ($error && ($error['type'] & (E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR))) {
if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
// Let's not throw anymore but keep logging
$handler->throwAt(0, true);
$trace = isset($error['backtrace']) ? $error['backtrace'] : null;
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
$exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false);
$exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
} else {
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true);
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
}
} elseif (!isset($exception)) {
return;
@@ -581,7 +614,7 @@ class ErrorHandler
self::$stackedErrors = array();
foreach ($errors as $e) {
$e[0][0]->log($e[0][1], $e[1], $e[2]);
$e[0]->log($e[1], $e[2], $e[3]);
}
}
}
@@ -649,7 +682,7 @@ class ErrorHandler
{
@trigger_error('The '.__METHOD__.' static method is deprecated since version 2.6 and will be removed in 3.0. Use the setLoggers() or setDefaultLogger() methods instead.', E_USER_DEPRECATED);
$handler = set_error_handler('var_dump', 0);
$handler = set_error_handler('var_dump');
$handler = is_array($handler) ? $handler[0] : null;
restore_error_handler();
if (!$handler instanceof self) {

View File

@@ -35,11 +35,19 @@ use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErr
*/
class FatalErrorException extends LegacyFatalErrorException
{
public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true)
public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
{
parent::__construct($message, $code, $severity, $filename, $lineno);
if (null !== $traceOffset) {
if (null !== $trace) {
if (!$traceArgs) {
foreach ($trace as &$frame) {
unset($frame['args'], $frame['this'], $frame);
}
}
$this->setTrace($trace);
} elseif (null !== $traceOffset) {
if (function_exists('xdebug_get_function_stack')) {
$trace = xdebug_get_function_stack();
if (0 < $traceOffset) {
@@ -48,7 +56,7 @@ class FatalErrorException extends LegacyFatalErrorException
foreach ($trace as &$frame) {
if (!isset($frame['type'])) {
// XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
// XDebug pre 2.1.1 doesn't currently set the call type key http://bugs.xdebug.org/view.php?id=695
if (isset($frame['class'])) {
$frame['type'] = '::';
}

View File

@@ -12,18 +12,18 @@
namespace Symfony\Component\Debug\Exception;
/**
* Base Fatal Error Exception.
* Fatal Throwable Error.
*
* @author Nicolas Grekas <p@tchwork.com>
*/
class FatalBaseException extends FatalErrorException
class FatalThrowableError extends FatalErrorException
{
public function __construct(\BaseException $e)
public function __construct(\Throwable $e)
{
if ($e instanceof \ParseException) {
if ($e instanceof \ParseError) {
$message = 'Parse error: '.$e->getMessage();
$severity = E_PARSE;
} elseif ($e instanceof \TypeException) {
} elseif ($e instanceof \TypeError) {
$message = 'Type error: '.$e->getMessage();
$severity = E_RECOVERABLE_ERROR;
} else {

View File

@@ -94,8 +94,13 @@ class FlattenException extends LegacyFlattenException
$e->setClass(get_class($exception));
$e->setFile($exception->getFile());
$e->setLine($exception->getLine());
if ($exception->getPrevious()) {
$e->setPrevious(static::create($exception->getPrevious()));
$previous = $exception->getPrevious();
if ($previous instanceof \Exception) {
$e->setPrevious(static::create($previous));
} elseif ($previous instanceof \Throwable) {
$e->setPrevious(static::create(new FatalThrowableError($previous)));
}
return $e;

View File

@@ -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);
}
/**
@@ -235,7 +238,7 @@ class ExceptionHandler
$ind = $count - $position + 1;
$class = $this->formatClass($e['class']);
$message = nl2br($this->escapeHtml($e['message']));
$content .= sprintf(<<<EOF
$content .= sprintf(<<<'EOF'
<h2 class="block_exception clear_fix">
<span class="exception_counter">%d/%d</span>
<span class="exception_title">%s%s:</span>
@@ -286,7 +289,7 @@ EOF;
*/
public function getStylesheet(FlattenException $exception)
{
return <<<EOF
return <<<'EOF'
.sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
.sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
.sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }

View File

@@ -1,4 +1,4 @@
Copyright (c) 2004-2015 Fabien Potencier
Copyright (c) 2004-2016 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -15,6 +15,7 @@ Debug::enable();
You can also use the tools individually:
```php
use Symfony\Component\Debug\DebugClassLoader;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
@@ -25,11 +26,9 @@ if ('cli' !== php_sapi_name()) {
ini_set('display_errors', 1);
}
ErrorHandler::register();
DebugClassLoader::enable();
```
Note that the `Debug::enable()` call also registers the debug class loader
from the Symfony ClassLoader component when available.
This component can optionally take advantage of the features of the HttpKernel
and HttpFoundation components.

View File

@@ -56,7 +56,7 @@ Symfony\Component\Debug\Exception\UndefinedFunctionException Object
[message:protected] => Attempted to call function "notexist" from namespace "Symfony\Component\Debug".
[string:Exception:private] =>
[code:protected] => 0
[file:protected] => -
[file:protected] => %s
[line:protected] => %d
[trace:Exception:private] => Array
(

View File

@@ -64,6 +64,9 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
if (PHP_VERSION_ID >= 70000) {
$this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.');
}
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('HHVM is not handled in this test case.');
}
ob_start();
@@ -86,6 +89,9 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) {
$this->markTestSkipped('The ContextErrorException class is already loaded.');
}
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('HHVM is not handled in this test case.');
}
ErrorHandler::register();
@@ -106,10 +112,10 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
restore_exception_handler();
$this->assertStringStartsWith(__FILE__, $exception->getFile());
if (PHP_VERSION_ID < 70000) {
$this->assertRegexp('/^Runtime Notice: Declaration/', $exception->getMessage());
$this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage());
$this->assertEquals(E_STRICT, $exception->getSeverity());
} else {
$this->assertRegexp('/^Warning: Declaration/', $exception->getMessage());
$this->assertRegExp('/^Warning: Declaration/', $exception->getMessage());
$this->assertEquals(E_WARNING, $exception->getSeverity());
}
} catch (\Exception $exception) {
@@ -130,6 +136,7 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Case mismatch between class and real file names
*/
public function testFileCaseMismatch()
{
@@ -168,7 +175,7 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
*/
public function testDeprecatedSuper($class, $super, $type)
{
set_error_handler('var_dump', 0);
set_error_handler(function() { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_DEPRECATED);
@@ -198,7 +205,7 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
public function testDeprecatedSuperInSameNamespace()
{
set_error_handler('var_dump', 0);
set_error_handler(function() { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
@@ -224,7 +231,7 @@ class DebugClassLoaderTest extends \PHPUnit_Framework_TestCase
$this->markTestSkipped('PHP7 already prevents using reserved names.');
}
set_error_handler('var_dump', 0);
set_error_handler(function() { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
@@ -258,6 +265,8 @@ class ClassLoader
public function findFile($class)
{
$fixtureDir = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR;
if (__NAMESPACE__.'\TestingUnsilencing' === $class) {
eval('-- parse error --');
} elseif (__NAMESPACE__.'\TestingStacking' === $class) {
@@ -265,15 +274,15 @@ class ClassLoader
} elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
} elseif (__NAMESPACE__.'\Fixtures\CaseMismatch' === $class) {
return __DIR__.'/Fixtures/CaseMismatch.php';
return $fixtureDir.'CaseMismatch.php';
} elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
return __DIR__.'/Fixtures/psr4/Psr4CaseMismatch.php';
return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) {
return __DIR__.'/Fixtures/reallyNotPsr0.php';
return $fixtureDir.'reallyNotPsr0.php';
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) {
return __DIR__.'/Fixtures/notPsr0Bis.php';
return $fixtureDir.'notPsr0Bis.php';
} elseif (__NAMESPACE__.'\Fixtures\DeprecatedInterface' === $class) {
return __DIR__.'/Fixtures/DeprecatedInterface.php';
return $fixtureDir.'DeprecatedInterface.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) {

View File

@@ -77,7 +77,7 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(E_NOTICE, $exception->getSeverity());
$this->assertEquals(__FILE__, $exception->getFile());
$this->assertRegexp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
$this->assertRegExp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage());
$this->assertArrayHasKey('foobar', $exception->getContext());
$trace = $exception->getTrace();
@@ -169,8 +169,6 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
public function testHandleError()
{
$this->iniSet('error_reporting', -1);
try {
$handler = ErrorHandler::register();
$handler->throwAt(0, true);
@@ -270,6 +268,28 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
}
}
public function testHandleDeprecation()
{
$that = $this;
$logArgCheck = function ($level, $message, $context) use ($that) {
$that->assertEquals(LogLevel::INFO, $level);
$that->assertArrayHasKey('level', $context);
$that->assertEquals(E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED, $context['level']);
$that->assertArrayHasKey('stack', $context);
};
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger
->expects($this->once())
->method('log')
->will($this->returnCallback($logArgCheck))
;
$handler = new ErrorHandler();
$handler->setDefaultLogger($logger);
@$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array());
}
public function testHandleException()
{
try {
@@ -318,6 +338,40 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
}
}
public function testErrorStacking()
{
try {
$handler = ErrorHandler::register();
$handler->screamAt(E_USER_WARNING);
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger
->expects($this->exactly(2))
->method('log')
->withConsecutive(
array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')),
array($this->equalTo(LogLevel::DEBUG), $this->equalTo('Silenced warning'))
)
;
$handler->setDefaultLogger($logger, array(E_USER_WARNING => LogLevel::WARNING));
ErrorHandler::stackErrors();
@trigger_error('Silenced warning', E_USER_WARNING);
$logger->log(LogLevel::WARNING, 'Dummy log');
ErrorHandler::unstackErrors();
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
public function testHandleFatalError()
{
try {
@@ -359,13 +413,57 @@ class ErrorHandlerTest extends \PHPUnit_Framework_TestCase
}
}
public function testHandleFatalErrorOnHHVM()
{
try {
$handler = ErrorHandler::register();
$logger = $this->getMock('Psr\Log\LoggerInterface');
$logger
->expects($this->once())
->method('log')
->with(
$this->equalTo(LogLevel::CRITICAL),
$this->equalTo('Fatal Error: foo'),
$this->equalTo(array(
'type' => 1,
'file' => 'bar',
'line' => 123,
'level' => -1,
'stack' => array(456),
))
)
;
$handler->setDefaultLogger($logger, E_ERROR);
$error = array(
'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors
'message' => 'foo',
'file' => 'bar',
'line' => 123,
'context' => array(123),
'backtrace' => array(456),
);
call_user_func_array(array($handler, 'handleError'), $error);
$handler->handleFatalError($error);
restore_error_handler();
restore_exception_handler();
} catch (\Exception $e) {
restore_error_handler();
restore_exception_handler();
throw $e;
}
}
/**
* @group legacy
*/
public function testLegacyInterface()
{
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
try {
$handler = ErrorHandler::register(0);
$this->assertFalse($handler->handle(0, 'foo', 'foo.php', 12, array()));

View File

@@ -131,6 +131,20 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
$this->assertSame(array($flattened2), $flattened->getAllPrevious());
}
/**
* @requires PHP 7.0
*/
public function testPreviousError()
{
$exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42));
$flattened = FlattenException::create($exception)->getPrevious();
$this->assertEquals($flattened->getMessage(), 'Parse error: Oh noes!', 'The message is copied from the original exception.');
$this->assertEquals($flattened->getCode(), 42, 'The code is copied from the original exception.');
$this->assertEquals($flattened->getClass(), 'Symfony\Component\Debug\Exception\FatalThrowableError', 'The class is set to the class of the original exception');
}
/**
* @dataProvider flattenDataProvider
*/

View File

@@ -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('<h1>Whoops, looks like something went wrong.</h1>', $response->getContent());
$this->assertNotContains('<h2 class="block_exception clear_fix">', $response->getContent());
ob_start();
$handler->sendPhpResponse(new \RuntimeException('Foo'));
$response = ob_get_clean();
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response);
$this->assertNotContains('<h2 class="block_exception clear_fix">', $response);
$handler = new ExceptionHandler(true);
$response = $handler->createResponse(new \RuntimeException('Foo'));
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response->getContent());
$this->assertContains('<h2 class="block_exception clear_fix">', $response->getContent());
ob_start();
$handler->sendPhpResponse(new \RuntimeException('Foo'));
$response = ob_get_clean();
$this->assertContains('<h1>Whoops, looks like something went wrong.</h1>', $response);
$this->assertContains('<h2 class="block_exception clear_fix">', $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('%A<span class="exception_message">Foo</span>%A<span class="exception_message">Bar</span>%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) {

View File

@@ -61,7 +61,7 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
array_map('spl_autoload_register', $autoloaders);
}
$this->assertInstanceof('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
$this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
$this->assertSame($translatedMessage, $exception->getMessage());
$this->assertSame($error['type'], $exception->getSeverity());
$this->assertSame($error['file'], $exception->getFile());
@@ -73,8 +73,6 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
*/
public function testLegacyHandleClassNotFound()
{
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
$prefixes = array('Symfony\Component\Debug\Exception\\' => realpath(__DIR__.'/../../Exception'));
$symfonyUniversalClassLoader = new SymfonyUniversalClassLoader();
$symfonyUniversalClassLoader->registerPrefixes($prefixes);
@@ -197,6 +195,6 @@ class ClassNotFoundFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
$handler = new ClassNotFoundFatalErrorHandler();
$exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
$this->assertInstanceof('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
$this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
}
}

View File

@@ -24,7 +24,7 @@ class UndefinedFunctionFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
$handler = new UndefinedFunctionFatalErrorHandler();
$exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
$this->assertInstanceof('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception);
$this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception);
// class names are case insensitive and PHP/HHVM do not return the same
$this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage()));
$this->assertSame($error['type'], $exception->getSeverity());

View File

@@ -24,7 +24,7 @@ class UndefinedMethodFatalErrorHandlerTest extends \PHPUnit_Framework_TestCase
$handler = new UndefinedMethodFatalErrorHandler();
$exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
$this->assertInstanceof('Symfony\Component\Debug\Exception\UndefinedMethodException', $exception);
$this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedMethodException', $exception);
$this->assertSame($translatedMessage, $exception->getMessage());
$this->assertSame($error['type'], $exception->getSeverity());
$this->assertSame($error['file'], $exception->getFile());

38
Tests/HeaderMock.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* 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();
}

View File

@@ -23,17 +23,14 @@
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
},
"require-dev": {
"symfony/phpunit-bridge": "~2.7",
"symfony/class-loader": "~2.2",
"symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2",
"symfony/http-foundation": "~2.1"
},
"suggest": {
"symfony/http-foundation": "",
"symfony/http-kernel": ""
"symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Debug\\": "" }
"psr-4": { "Symfony\\Component\\Debug\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"extra": {