Compare commits

...

66 Commits

Author SHA1 Message Date
Nicolas Grekas 3b97c83b47 [Debug] Fix case sensitivity checks 2016-03-30 11:14:15 +02:00
Dan Blows ef78aaaa3e [Debug] Replaced logic for detecting filesystem case sensitivity 2016-03-13 11:12:56 +01:00
Nicolas Grekas 8dc1218161 Merge branch '2.3' into 2.7
* 2.3:
  [HttpFoundation] Fix transient test
  [HttpFoundation] Add a dependency on the mbstring polyfill
  add readme files where missing
  Don't use reflections when possible
  [Form] Update form tests after the ICU data update
  [Intl] Update tests and the number formatter to match behaviour of the intl extension
  [Intl] Update the ICU data to version 55
  [Intl] Fix the update-data.php script in preparation for ICU 5.5
  Use constant instead of function call.
  fixed test name
  automatically generate safe fallback filename

Conflicts:
	src/Symfony/Component/Debug/Debug.php
	src/Symfony/Component/HttpFoundation/composer.json
	src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php
2016-03-07 14:45:47 +01:00
Fabien Potencier d251523f4e minor #18025 [2.7] Don't use reflection when possible (Ener-Getick)
This PR was merged into the 2.7 branch.

Discussion
----------

[2.7] Don't use reflection when possible

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

See https://github.com/symfony/symfony/pull/18021

Commits
-------

35be501 Don't use reflections when possible
2016-03-06 11:26:36 +01:00
Ener-Getick f2e4849892 Don't use reflections when possible 2016-03-05 18:34:36 +01:00
Konstantin.Myakshin a6f7b78e40 Use constant instead of function call. 2016-03-04 15:04:09 +02:00
Fabien Potencier 26527ccf6f Merge branch '2.3' into 2.7
* 2.3:
  Updated all the README files
  [TwigBundle] Fix failing test on appveyor
  [FrameworkBundle] Fix a regression in handling absolute and namespaced template paths
  Allow to normalize \Traversable
  Remove _path from query parameters when fragment is a subrequest and request attributes are already set Added tests for _path removal in FragmentListener
  Simplified everything
  Added a test
  Fixed the problem in an easier way
  Fixed a syntax issue
  Improved the error message when a template is not found
  [CodingStandards] Conformed to coding standards
  [TwigBundle] fixed Include file locations in "Template could not be found" exception
2016-03-04 08:52:28 +01:00
Javier Eguiluz 9233292b81 Updated all the README files 2016-03-04 08:12:06 +01:00
Nicolas Grekas e96f1ff28e [Debug] Tell that the extension is for PHP 5 only 2016-01-26 00:34:19 +01:00
Lebnik ef9b1c139e Remove unnecessary code
```
php > echo (E_ALL | E_STRICT) & (0 | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
4352
php > echo (0 | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
4352
php > echo (2 | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
4354
```
2016-01-21 15:16:05 +03:00
Fabien Potencier 9044cdf657 fixed CS 2016-01-21 09:40:25 +01:00
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
reecefowell 075070230c Silence invasive deprecation warnings, opt-in for warnings 2015-06-08 10:37:21 +01: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
Fabien Potencier 1df2971b27 Merge branch '2.6' into 2.7
* 2.6: (30 commits)
  [Translation] fixed JSON loader on PHP 7 when file is empty
  Fix typo
  Check instance of FormBuilderInterface instead of FormBuilder
  [Security] TokenBasedRememberMeServices test to show why encoding username is required
  [Security] AbstractRememberMeServices::encodeCookie() validates cookie parts
  fixed typo
  [console][formater] allow format toString object.
  [HttpFoundation] Fix baseUrl when script filename is contained in pathInfo
  Avoid redirection to XHR URIs
  [HttpFoundation] IpUtils::checkIp4() should allow  networks
  [2.6] Fix HTML escaping of to-source links
  Fix HTML escaping of to-source links
  ExceptionHandler: More Encoding
  Fix the rendering of deprecation log messages
  [FrameworkBundle] Removed unnecessary parameter in TemplateController
  [DomCrawler] Throw an exception if a form field path is incomplete.
  Fixed the indentation in the compiled template for the DumpNode
  [Console] Delete duplicate test in CommandTest
  [TwigBundle] Refresh twig paths when resources change.
  WebProfiler break words
  ...

Conflicts:
	src/Symfony/Bridge/Twig/composer.json
	src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig
	src/Symfony/Component/Debug/ExceptionHandler.php
2015-05-22 16:54:25 +02:00
Fabien Potencier 4851a041c4 fixed typo 2015-05-20 15:09:45 +02:00
Nicolas Grekas 366f3fe9ea [2.6] Fix HTML escaping of to-source links 2015-05-19 17:48:49 -07:00
Nicolas Grekas 30d1de52f1 Fix HTML escaping of to-source links 2015-05-19 17:44:44 -07:00
Alexander Menk d59aecf5f4 ExceptionHandler: More Encoding 2015-05-19 17:33:46 -07:00
Fabien Potencier 366a668f66 Merge branch '2.6' into 2.7
* 2.6:
  [DebugBundle] Allow alternative destination for dumps
  [DebugBundle] Use output mechanism of dumpers instead of echoing
  [DebugBundle] Always collect dumps
  Fix tests in HHVM
  CS: Pre incrementation/decrementation should be used if possible

Conflicts:
	src/Symfony/Component/Finder/Expression/Glob.php
2015-05-15 15:33:16 +02:00
Fabien Potencier c214e92851 Merge branch '2.3' into 2.6
* 2.3:
  Fix tests in HHVM
  CS: Pre incrementation/decrementation should be used if possible

Conflicts:
	src/Symfony/Bundle/TwigBundle/Command/LintCommand.php
	src/Symfony/Component/Console/Helper/TableHelper.php
	src/Symfony/Component/EventDispatcher/Tests/EventDispatcherTest.php
	src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php
	src/Symfony/Component/HttpKernel/HttpCache/EsiResponseCacheStrategy.php
	src/Symfony/Component/Security/Acl/Dbal/AclProvider.php
	src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php
2015-05-15 15:32:45 +02:00
Fabien Potencier dfe71c73cf minor #14121 CS: Pre incrementation/decrementation should be used if possible (gharlan)
This PR was merged into the 2.3 branch.

Discussion
----------

CS: Pre incrementation/decrementation should be used if possible

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

Fixes provided by new fixer: https://github.com/FriendsOfPHP/PHP-CS-Fixer/pull/1113

If this pr is merged I would change the level of the fixer to `symfony`.

Commits
-------

c5123d6 CS: Pre incrementation/decrementation should be used if possible
2015-05-15 15:28:34 +02:00
Nicolas Grekas 8bc9390ba3 [Debug 2.3] Fix test for PHP7 2015-05-06 12:13:27 +02:00
Gregor Harlan 01c8bc9bac CS: Pre incrementation/decrementation should be used if possible 2015-04-07 19:54:22 +02:00
21 changed files with 475 additions and 213 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ class Debug
error_reporting(-1);
}
if ('cli' !== php_sapi_name()) {
if ('cli' !== PHP_SAPI) {
ini_set('display_errors', 0);
ExceptionHandler::register();
} elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
+106 -36
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,20 +30,19 @@ 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)
{
$this->wasFinder = is_object($classLoader) && method_exists($classLoader, 'findFile');
if ($this->wasFinder) {
trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
@trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
$this->classLoader = array($classLoader, 'loadClass');
$this->isFinder = true;
} else {
@@ -54,7 +51,26 @@ class DebugClassLoader
}
if (!isset(self::$caseCheck)) {
self::$caseCheck = false !== stripos(PHP_OS, 'win') ? (false !== stripos(PHP_OS, 'darwin') ? 2 : 1) : 0;
$file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
$i = strrpos($file, DIRECTORY_SEPARATOR);
$dir = substr($file, 0, 1 + $i);
$file = substr($file, 1 + $i);
$test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
$test = realpath($dir.$test);
if (false === $test || false === $i) {
// filesystem is case sensitive
self::$caseCheck = 0;
} elseif (substr($test, -strlen($file)) === $file) {
// filesystem is case insensitive and realpath() normalizes the case of characters
self::$caseCheck = 1;
} elseif (false !== stripos(PHP_OS, 'darwin')) {
// on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters
self::$caseCheck = 2;
} else {
// filesystem case checks failed, fallback to disabling them
self::$caseCheck = 0;
}
}
}
@@ -127,7 +143,7 @@ class DebugClassLoader
*/
public function findFile($class)
{
trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
if ($this->wasFinder) {
return $this->classLoader[0]->findFile($class);
@@ -150,7 +166,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 +195,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 {
@@ -196,16 +212,16 @@ class DebugClassLoader
break;
}
}
$parent = $refl->getParentClass();
$parent = get_parent_class($class);
if (!$parent || strncmp($ns, $parent->name, $len)) {
if ($parent && isset(self::$deprecated[$parent->name]) && strncmp($ns, $parent->name, $len)) {
trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent->name, self::$deprecated[$parent->name]), E_USER_DEPRECATED);
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);
}
foreach ($refl->getInterfaceNames() as $interface) {
if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len) && !($parent && $parent->implementsInterface($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);
foreach (class_implements($class) as $interface) {
if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len) && !is_subclass_of($parent, $interface)) {
@trigger_error(sprintf('The %s %s %s that is deprecated %s', $name, interface_exists($class) ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
}
}
}
@@ -220,35 +236,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)));
}
}
+69 -36
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];
@@ -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]);
}
}
}
@@ -611,7 +644,7 @@ class ErrorHandler
*/
public function setLevel($level)
{
trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
$level = null === $level ? error_reporting() : $level;
$this->throwAt($level, true);
@@ -626,7 +659,7 @@ class ErrorHandler
*/
public function setDisplayErrors($displayErrors)
{
trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the throwAt() method instead.', E_USER_DEPRECATED);
if ($displayErrors) {
$this->throwAt($this->displayErrors, true);
@@ -647,9 +680,9 @@ class ErrorHandler
*/
public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
{
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);
@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) {
@@ -684,7 +717,7 @@ class ErrorHandler
*/
public function handleFatal()
{
trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the handleFatalError() method instead.', E_USER_DEPRECATED);
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.6 and will be removed in 3.0. Use the handleFatalError() method instead.', E_USER_DEPRECATED);
static::handleFatalError();
}
+1 -1
View File
@@ -11,7 +11,7 @@
namespace Symfony\Component\Debug\Exception;
trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
@trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
/**
* @author Fabien Potencier <fabien@symfony.com>
+11 -3
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'] = '::';
}
@@ -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 {
+7 -2
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;
+16 -13
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; }
@@ -380,7 +383,7 @@ EOF;
$file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
if ($linkFormat = $this->fileLinkFormat) {
$link = str_replace(array('%f', '%l'), array($path, $line), $linkFormat);
$link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
}
@@ -422,19 +425,19 @@ EOF;
}
/**
* Returns an UTF-8 and HTML encoded string
* Returns an UTF-8 and HTML encoded string.
*
* @deprecated since version 2.7, to be removed in 3.0.
*/
protected static function utf8Htmlize($str)
{
trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
return htmlspecialchars($str, ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
}
/**
* HTML-encodes a string
* HTML-encodes a string.
*/
private function escapeHtml($str)
{
+1 -1
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
+6 -36
View File
@@ -1,43 +1,13 @@
Debug Component
===============
Debug provides tools to make debugging easier.
Enabling all debug tools is as easy as calling the `enable()` method on the
main `Debug` class:
```php
use Symfony\Component\Debug\Debug;
Debug::enable();
```
You can also use the tools individually:
```php
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\Debug\ExceptionHandler;
if ('cli' !== php_sapi_name()) {
ini_set('display_errors', 0);
ExceptionHandler::register();
} elseif (!ini_get('log_errors') || ini_get('error_log')) {
ini_set('display_errors', 1);
}
ErrorHandler::register();
```
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.
The Debug component provides tools to ease debugging PHP code.
Resources
---------
You can run the unit tests with the following command:
$ cd path/to/Symfony/Component/Debug/
$ composer install
$ phpunit
* [Documentation](https://symfony.com/doc/current/components/debug/index.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)
+4 -3
View File
@@ -1,7 +1,9 @@
Symfony Debug Extension
=======================
Symfony Debug Extension for PHP 5
=================================
This extension publishes several functions to help building powerful debugging tools.
It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes.
It is not required thus not provided for PHP 7.
symfony_zval_info()
-------------------
@@ -122,7 +124,6 @@ array(3) {
Usage
-----
The extension is compatible with ZTS mode, and should be supported by PHP5.3, 5.4, 5.5 and 5.6.
To enable the extension from source, run:
```
+1 -1
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
(
+19 -10
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) {
+103 -5
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()));
+17 -3
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
*/
@@ -189,9 +203,9 @@ class FlattenExceptionTest extends \PHPUnit_Framework_TestCase
public function testTooBigArray()
{
$a = array();
for ($i = 0; $i < 20; $i++) {
for ($j = 0; $j < 50; $j++) {
for ($k = 0; $k < 10; $k++) {
for ($i = 0; $i < 20; ++$i) {
for ($j = 0; $j < 50; ++$j) {
for ($k = 0; $k < 10; ++$k) {
$a[$i][$j][$k] = 'value';
}
}
+61 -43
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) {
@@ -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);
}
}
@@ -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());
@@ -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
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();
}
+5 -8
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": {