Compare commits

...

67 Commits

Author SHA1 Message Date
Nicolas Grekas
1eff904a95 Merge branch '3.4' into 4.3
* 3.4:
  [Debug] fix ClassNotFoundFatalErrorHandler
  [Dotenv] Fixed infinite loop with missing quote followed by quoted value
  [TwigBridge] button_widget now has its title attr translated even if its label = null or false
  [PhpUnitBridge] When using phpenv + phpenv-composer plugin, composer executable is wrapped into a bash script
  [Security] Prevent canceled remember-me cookie from being accepted
  [FrameworkBundle][TranslationUpdateCommand] Do not output positive feedback on stderr
2020-01-08 18:19:22 +01:00
Nicolas Grekas
70dd18e93b [Debug] fix ClassNotFoundFatalErrorHandler 2020-01-08 17:36:15 +01:00
Nicolas Grekas
e45fa0c74a Merge branch '3.4' into 4.3
* 3.4:
  Update links to documentation
  [Validator] Add the missing translations for the Arabic (ar) locale
  ensure to expect no validation for the right reasons
  [PhpUnitBridge] Add test case for @expectedDeprecation annotation
  Update year in license files
  [Console][FormatterHelper] Use helper strlen statically and remove duplicated code
  Fix BC issue in phpDoc Reflection library
  [Translator] Performance improvement in MessageCatalogue and catalogue operations.
2020-01-04 13:24:57 +01:00
Shaharia Azam
9a81b6360b Update links to documentation 2020-01-04 13:05:51 +01:00
Jan Rosier
cbe127b719 Update year in license files 2020-01-01 12:03:25 +01:00
Nicolas Grekas
c533fe8d14 Fix displaying anonymous classes on PHP 7.4 2019-12-16 15:20:08 +01:00
Nicolas Grekas
ba2ce2f0ee Merge branch '3.4' into 4.3
* 3.4:
  Use `::class` constants instead of `__NAMESPACE__` when possible
2019-12-16 12:02:49 +01:00
Artem Henvald
9d32af2d83 Use ::class constants instead of __NAMESPACE__ when possible 2019-12-16 11:25:54 +01:00
Nicolas Grekas
7793eea884 bug #34091 [Debug] work around failing chdir() on Darwin (mary2501)
This PR was merged into the 4.3 branch.

Discussion
----------

[Debug] work around failing chdir() on Darwin

| Q             | A
| ------------- | ---
| Branch?       |  4.3 for bug fixes <!-- see below -->
| Bug fix?      | yes
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tickets       | Fix https://github.com/happybottoms/coverd/issues/15 <!-- prefix each issue number with "Fix #", if any -->
| License       | MIT
| Doc PR        | symfony/symfony-docs#... <!-- required for new features -->
<!--
Replace this notice by a short README for your feature/bugfix. This will help people
understand your PR and can be used as a start for the documentation.

Additionally (see https://symfony.com/roadmap):
 - Always add tests and ensure they pass.
 - Never break backward compatibility (see https://symfony.com/bc).
 - Bug fixes must be submitted against the lowest maintained branch where they apply
   (lowest branches are regularly merged to upper ones so they get the fixes too.)
 - Features and deprecations must be submitted against branch 4.4.
 - Legacy code removals go to the master branch.
-->

Commits
-------

f40373eb7c [Debug] work around failing chdir() on Darwin
2019-11-28 11:55:21 +01:00
Maria Grazia Patteri
e8d70531f3 [Debug] work around failing chdir() on Darwin 2019-11-28 11:53:46 +01:00
Nicolas Grekas
5ea9c3e019 Merge branch '3.4' into 4.3
* 3.4:
  #30432 fix an error message
  fix paths to detect code owners
  [Validator] Ensure numeric subpaths do not cause errors on PHP 7.4
  Remove unused local variables in tests
  Make sure to collect child forms created on *_SET_DATA events
  do not render errors for checkboxes twice
2019-10-28 18:07:32 +01:00
Thomas Calvet
f72e33fdb1 Remove unused local variables in tests 2019-10-24 17:33:53 +02:00
Nicolas Grekas
cc5c1efd0e Merge branch '3.4' into 4.3
* 3.4:
  Re-enable previously failing PHP 7.4 test cases
  Revert "bug #33618 fix tests depending on other components' tests (xabbuh)"
  install from source to include components tests
2019-09-19 17:51:53 +02:00
Nicolas Grekas
b3e7ce815d Re-enable previously failing PHP 7.4 test cases 2019-09-19 17:32:51 +02:00
Fabien Potencier
c1a032ce81 Simplify usage of dirname() 2019-09-10 13:22:25 +02:00
Alexander M. Turek
afcdea44a2 Fix inconsistent return points. 2019-08-20 16:27:59 +02:00
Nicolas Grekas
ed30cb9da5 Merge branch '3.4' into 4.3
* 3.4:
  Fix inconsistent return points.
  [Security/Core] UserInterface::getPassword() can return null
  [Router] Fix TraceableUrlMatcher behaviour with trailing slash
2019-08-20 16:07:54 +02:00
Alexander M. Turek
0b60030091 Fix inconsistent return points. 2019-08-20 15:31:17 +02:00
Nicolas Grekas
2d8ff49ce0 Merge branch '3.4' into 4.3
* 3.4:
  Fix return statements
  [TwigBridge] add missing dep
  Add false type to ChoiceListFactoryInterface::createView $label argument
2019-08-13 08:39:03 +02:00
Nicolas Grekas
2ab93347e8 Fix return statements 2019-08-13 08:33:05 +02:00
Nicolas Grekas
692aa71df2 Merge branch '3.4' into 4.3
* 3.4:
  Improve some URLs
  Fix test compatibility with 4.x components
  [Cache] cs fix
2019-08-08 17:11:33 +02:00
Nicolas Grekas
4645282605 minor #32800 Improve some URLs (Arman-Hosseini)
This PR was squashed before being merged into the 3.4 branch (closes #32800).

Discussion
----------

Improve some URLs

| Q             | A
| ------------- | ---
| Branch?       | 3.4 <!-- see below -->
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- please update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | N/A   <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | N/A <!-- required for new features -->

<!--
Replace this notice by a short README for your feature/bugfix. This will help people
understand your PR and can be used as a start for the documentation.

Additionally (see https://symfony.com/roadmap):
 - Bug fixes must be submitted against the lowest maintained branch where they apply
   (lowest branches are regularly merged to upper ones so they get the fixes too).
 - Features and deprecations must be submitted against branch 4.4.
 - Legacy code removals go to the master branch.
-->

Commits
-------

fab17a4487 Improve some URLs
2019-08-08 17:01:55 +02:00
Arman Hosseini
93fd0e9f20 Improve some URLs 2019-08-08 17:01:12 +02:00
Jérémy Derussé
3ec8596803 Disable phpunit typehint patch on 4.3 branch 2019-08-08 11:29:19 +02:00
Nicolas Grekas
19056a4079 Merge branch '3.4' into 4.3
* 3.4:
  Fix inconsistent return points.
  Fix remaining tests
2019-08-07 13:52:19 +02:00
Mario Blažek
12e1811d2b Remove deprecated assertContains 2019-08-07 10:22:11 +02:00
Jérémy Derussé
c5366e87da Fix remaining tests 2019-08-06 15:24:37 +02:00
Nicolas Grekas
406bb25021 Merge branch '3.4' into 4.3
* 3.4:
  bump phpunit-bridge cache-id
  Use assertStringContainsString when needed
  Use assert assertContainsEquals when needed
  Use assertEqualsWithDelta when required
2019-08-06 09:11:09 +02:00
Jérémy Derussé
a78bf4dc3a Use assertStringContainsString when needed 2019-08-06 08:15:37 +02:00
Nicolas Grekas
dda62cdc3a Merge branch '3.4' into 4.3
* 3.4:
  Remove use of ForwardCompatTrait
  Remove deprecated methods assertArraySubset
2019-08-03 23:50:52 +02:00
Jérémy Derussé
4dc880d082 Remove use of ForwardCompatTrait 2019-08-03 23:15:25 +02:00
Nicolas Grekas
288013687b Merge branch '3.4' into 4.3
* 3.4:
  Adopt `@PHPUnit55Migration:risky` rule of php-cs-fixer
2019-08-03 16:00:31 +02:00
Nicolas Grekas
63f26f1891 Adopt @PHPUnit55Migration:risky rule of php-cs-fixer 2019-08-03 15:46:27 +02:00
Nicolas Grekas
91730bdf7d Merge branch '3.4' into 4.3
* 3.4:
  Fix tests
  Fix deprecated phpunit annotation
2019-08-02 14:15:04 +02:00
Jérémy Derussé
bef2cd01a1 Fix deprecated phpunit annotation 2019-08-02 00:48:42 +02:00
Nicolas Grekas
1fd323489f Merge branch '3.4' into 4.3
* 3.4:
  [Cache] fix cs
  Make tests support phpunit 8
2019-08-01 00:32:32 +02:00
Nicolas Grekas
22fea487fa Make tests support phpunit 8 2019-07-31 23:55:24 +02:00
Nicolas Grekas
8ff6ff5f51 Merge branch '3.4' into 4.3
* 3.4:
  Fix travis script
  minor fix for wrong case
  [HttpFoundation] Fix `getMaxFilesize`
  [Cache] fix warning on PHP 7.4
  [Console] fix warning on PHP 7.4
  Don't add value of (default/static) objects to the signature
  fix(yml): fix comment in milti line value
2019-07-31 14:41:55 +02:00
Tobias Weichart
89429ed0eb minor fix for wrong case 2019-07-31 08:13:25 +01:00
Nicolas Grekas
527887c385 Merge branch '4.2' into 4.3
* 4.2:
  [FrameworkBundle] [SecurityBundle] Rename internal WebTestCase to avoid confusion
  ignore not existing translator service
  [FrameworkBundle] [SecurityBundle] Rename internal WebTestCase to avoid confusion
  revert private properties handling
  [HttpFoundation] Fix URLs
  [VarDumper] finish PHP 7.4 support and add tests
  [VarDumper] Use \ReflectionReference for determining if a key is a reference (php >= 7.4)
  Ignore missing translation dependency in FrameworkBundle
  Remove dead tests fixtures
  Remove more dead tests fixtures
  Remove dead tests fixtures
  [Debug][ExceptionHandler] Add tests for custom handlers
2019-07-23 13:21:36 +02:00
Nicolas Grekas
f832ecacfb Merge branch '3.4' into 4.2
* 3.4:
  [FrameworkBundle] [SecurityBundle] Rename internal WebTestCase to avoid confusion
  revert private properties handling
  [HttpFoundation] Fix URLs
  [VarDumper] finish PHP 7.4 support and add tests
  [VarDumper] Use \ReflectionReference for determining if a key is a reference (php >= 7.4)
  Ignore missing translation dependency in FrameworkBundle
  [Debug][ExceptionHandler] Add tests for custom handlers
2019-07-23 11:50:15 +02:00
Nicolas Grekas
bc977cb268 minor #32619 [Debug][ExceptionHandler] Add tests for custom handlers (fancyweb)
This PR was merged into the 3.4 branch.

Discussion
----------

[Debug][ExceptionHandler] Add tests for custom handlers

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

In https://github.com/symfony/symfony/pull/31694 I mixed many things but the whole PR was closed. I wrote some tests for custom handlers + the handle tests don't use mock anymore

I think they are useful even if the `ExceptionHandler` will disappear in the new component because it will still exists in 4.4 for the next 3 years.

Commits
-------

c53e25332a [Debug][ExceptionHandler] Add tests for custom handlers
2019-07-23 10:39:19 +02:00
Nicolas Grekas
340a0fc6ed Merge branch '3.4' into 4.2
* 3.4:
  Remove dead tests fixtures
2019-07-19 14:05:51 +02:00
Nicolas Grekas
dabd21d13b minor #32623 Remove dead tests fixtures (fancyweb)
This PR was merged into the 3.4 branch.

Discussion
----------

Remove dead tests fixtures

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

Once this is merged up to 4.2, I will check 4.2.

Commits
-------

f7e24c2c80 Remove dead tests fixtures
2019-07-19 14:05:10 +02:00
Thomas Calvet
b6f28caaf2 Remove dead tests fixtures 2019-07-19 13:52:08 +02:00
Thomas Calvet
5bf4824968 [Debug][ExceptionHandler] Add tests for custom handlers 2019-07-19 10:43:44 +02:00
Nicolas Grekas
fb91321bee Merge branch '4.2' into 4.3
* 4.2:
  fix tests
  [Validator] Added support for validation of giga values
  Fix Debug component tests
2019-07-19 10:33:28 +02:00
Nicolas Grekas
2fdd843f5e Merge branch '3.4' into 4.2
* 3.4:
  fix tests
  [Validator] Added support for validation of giga values
  Fix Debug component tests
2019-07-19 10:33:10 +02:00
Nicolas Grekas
dff676526c minor #32612 [Debug] Fix 3.4 tests (yceruto)
This PR was merged into the 3.4 branch.

Discussion
----------

[Debug] Fix 3.4 tests

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

Commits
-------

77fa283091 Fix Debug component tests
2019-07-19 10:32:24 +02:00
Yonel Ceruto
b49ea98332 Fix Debug component tests 2019-07-18 18:35:50 -04:00
Nicolas Grekas
5f3e892c1c Merge branch '4.2' into 4.3
* 4.2: (23 commits)
  fix cs
  Use mocks before replacing the error handler
  [Config] Do not use absolute path when computing the vendor freshness
  Bump minimum version of symfony/phpunit-bridge
  Container*::getServiceIds() should return an array of string
  [Config][ReflectionClassResource] Use ternary instead of null coaelscing operator
  [Validator] Add missing Russian and Ukrainian translations
  [Translation] Use HTTPS and fix a url
  [Config] Fix for signatures of typed properties
  [Validator] Add missing Hungarian translations
  [Validator] Add Lithuanian translation for Range validator
  Add HTTPS to a URL
  sync translation files
  PHPDoc fixes
  Add notInRange translation
  Add danish translation for Range validator
  Add german translation for Range validator
  Update validators.es.xlf
  [Validator] Add missing en and fr translation ids from 4.4
  [Debug][DebugClassLoader] Don't check class if the included file don't exist
  ...
2019-07-18 12:34:59 +02:00
Nicolas Grekas
7a65fe00f9 Merge branch '3.4' into 4.2
* 3.4: (23 commits)
  fix cs
  Use mocks before replacing the error handler
  [Config] Do not use absolute path when computing the vendor freshness
  Bump minimum version of symfony/phpunit-bridge
  Container*::getServiceIds() should return an array of string
  [Config][ReflectionClassResource] Use ternary instead of null coaelscing operator
  [Validator] Add missing Russian and Ukrainian translations
  [Translation] Use HTTPS and fix a url
  [Config] Fix for signatures of typed properties
  [Validator] Add missing Hungarian translations
  [Validator] Add Lithuanian translation for Range validator
  Add HTTPS to a URL
  sync translation files
  PHPDoc fixes
  Add notInRange translation
  Add danish translation for Range validator
  Add german translation for Range validator
  Update validators.es.xlf
  [Validator] Add missing en and fr translation ids from 4.4
  [Debug][DebugClassLoader] Don't check class if the included file don't exist
  ...
2019-07-18 12:29:22 +02:00
Grégoire Paris
a808f15333 Use mocks before replacing the error handler
We want the bridge to mute the deprecations triggered when building mocks.
2019-07-18 08:26:12 +02:00
Thomas Calvet
32d260af46 [Debug][DebugClassLoader] Don't check class if the included file don't exist 2019-07-12 10:40:08 +02:00
Fabien Potencier
8ab610f0b0 Merge branch '4.2' into 4.3
* 4.2:
  fixed CS
  [Debug][DebugClassLoader] Include found files instead of requiring them
2019-07-12 08:54:53 +03:00
Fabien Potencier
8a212666c0 Merge branch '3.4' into 4.2
* 3.4:
  fixed CS
  [Debug][DebugClassLoader] Include found files instead of requiring them
2019-07-12 08:51:03 +03:00
Thomas Calvet
740602e8b0 [Debug][DebugClassLoader] Include found files instead of requiring them 2019-07-11 20:09:53 +02:00
Christian Flothmann
8ca4340b26 Merge branch '4.2' into 4.3
* 4.2:
  fix Debug component dependencies
  [travis] not all components have a master branch
2019-06-28 14:12:54 +02:00
Christian Flothmann
b6d3ae55c0 Merge branch '3.4' into 4.2
* 3.4:
  fix Debug component dependencies
  [travis] not all components have a master branch
2019-06-28 14:00:38 +02:00
Christian Flothmann
d58c0d65d7 fix Debug component dependencies 2019-06-28 11:18:39 +02:00
Nicolas Grekas
d8f4fb3815 Merge branch '4.2' into 4.3
* 4.2:
  [FrameworkBundle] minor: fix typo in SessionTest
  [Debug] workaround BC break in PHP 7.3
2019-06-19 17:27:09 +02:00
Nicolas Grekas
bb91fa5ab9 Merge branch '3.4' into 4.2
* 3.4:
  [FrameworkBundle] minor: fix typo in SessionTest
  [Debug] workaround BC break in PHP 7.3
2019-06-19 17:26:44 +02:00
Nicolas Grekas
1172dc1abe [Debug] workaround BC break in PHP 7.3 2019-06-18 23:26:03 +02:00
Fabien Potencier
a30d8fe728 fixed CS 2019-06-13 13:03:18 +02:00
Fabien Potencier
7d9d22bcd0 Merge branch '4.2' into 4.3
* 4.2:
  fixed CS
  fixed CS
  [HttpKernel] Remove TestEventDispatcher.
2019-06-13 13:01:17 +02:00
Fabien Potencier
d0bff29e62 fixed CS 2019-06-13 12:57:15 +02:00
Fabien Potencier
7e1a4ec082 fixed CS 2019-06-13 12:34:15 +02:00
16 changed files with 232 additions and 187 deletions

View File

@@ -153,11 +153,11 @@ class DebugClassLoader
if (!$file = $this->classLoader[0]->findFile($class) ?: false) {
// no-op
} elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) {
require $file;
include $file;
return;
} else {
require $file;
} elseif (false === include $file) {
return;
}
} else {
($this->classLoader)($class);
@@ -172,7 +172,7 @@ class DebugClassLoader
private function checkClass($class, $file = null)
{
$exists = null === $file || \class_exists($class, false) || \interface_exists($class, false) || \trait_exists($class, false);
$exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
if (null !== $file && $class && '\\' === $class[0]) {
$class = substr($class, 1);
@@ -190,7 +190,7 @@ class DebugClassLoader
}
$name = $refl->getName();
if ($name !== $class && 0 === \strcasecmp($name, $class)) {
if ($name !== $class && 0 === strcasecmp($name, $class)) {
throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
}
@@ -223,22 +223,22 @@ class DebugClassLoader
$deprecations = [];
// Don't trigger deprecations for classes in the same vendor
if (2 > $len = 1 + (\strpos($class, '\\') ?: \strpos($class, '_'))) {
if (2 > $len = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) {
$len = 0;
$ns = '';
} else {
$ns = \str_replace('_', '\\', \substr($class, 0, $len));
$ns = str_replace('_', '\\', substr($class, 0, $len));
}
// Detect annotations on the class
if (false !== $doc = $refl->getDocComment()) {
foreach (['final', 'deprecated', 'internal'] as $annotation) {
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
}
}
if ($refl->isInterface() && false !== \strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) {
if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) {
foreach ($notice as $method) {
$static = '' !== $method[1];
$name = $method[2];
@@ -257,7 +257,7 @@ class DebugClassLoader
}
}
$parent = \get_parent_class($class);
$parent = get_parent_class($class);
$parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent);
if ($parent) {
$parentAndOwnInterfaces[$parent] = $parent;
@@ -272,17 +272,17 @@ class DebugClassLoader
}
// Detect if the parent is annotated
foreach ($parentAndOwnInterfaces + \class_uses($class, false) as $use) {
foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) {
if (!isset(self::$checkedClasses[$use])) {
$this->checkClass($use);
}
if (isset(self::$deprecated[$use]) && \strncmp($ns, \str_replace('_', '\\', $use), $len) && !isset(self::$deprecated[$class])) {
if (isset(self::$deprecated[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len) && !isset(self::$deprecated[$class])) {
$type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait');
$verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
$deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s.', $class, $type, $verb, $use, self::$deprecated[$use]);
}
if (isset(self::$internal[$use]) && \strncmp($ns, \str_replace('_', '\\', $use), $len)) {
if (isset(self::$internal[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len)) {
$deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $class);
}
if (isset(self::$method[$use])) {
@@ -309,7 +309,7 @@ class DebugClassLoader
}
}
if (\trait_exists($class)) {
if (trait_exists($class)) {
return $deprecations;
}
@@ -337,7 +337,7 @@ class DebugClassLoader
if (isset(self::$internalMethods[$class][$method->name])) {
list($declaringClass, $message) = self::$internalMethods[$class][$method->name];
if (\strncmp($ns, $declaringClass, $len)) {
if (strncmp($ns, $declaringClass, $len)) {
$deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
}
}
@@ -365,14 +365,14 @@ class DebugClassLoader
$finalOrInternal = false;
foreach (['final', 'internal'] as $annotation) {
if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
$message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message];
$finalOrInternal = true;
}
}
if ($finalOrInternal || $method->isConstructor() || false === \strpos($doc, '@param') || StatelessInvocation::class === $class) {
if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) {
continue;
}
if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) {
@@ -395,6 +395,12 @@ class DebugClassLoader
return $deprecations;
}
/**
* @param string $file
* @param string $class
*
* @return array|null
*/
public function checkCase(\ReflectionClass $refl, $file, $class)
{
$real = explode('\\', $class.strrchr($file, '.'));
@@ -411,7 +417,7 @@ class DebugClassLoader
array_splice($tail, 0, $i + 1);
if (!$tail) {
return;
return null;
}
$tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
@@ -427,6 +433,8 @@ class DebugClassLoader
) {
return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)];
}
return null;
}
/**
@@ -447,7 +455,11 @@ class DebugClassLoader
$real = self::$darwinCache[$kDir][0];
} else {
$dir = getcwd();
chdir($real);
if (!@chdir($real)) {
return $real.$file;
}
$real = getcwd().'/';
chdir($dir);
@@ -474,7 +486,7 @@ class DebugClassLoader
}
if (isset($dirFiles[$file])) {
return $real .= $dirFiles[$file];
return $real.$dirFiles[$file];
}
$kFile = strtolower($file);
@@ -493,7 +505,7 @@ class DebugClassLoader
self::$darwinCache[$kDir][1] = $dirFiles;
}
return $real .= $dirFiles[$kFile];
return $real.$dirFiles[$kFile];
}
/**

View File

@@ -382,6 +382,10 @@ class ErrorHandler
*/
public function handleError($type, $message, $file, $line)
{
if (\PHP_VERSION_ID >= 70300 && E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) {
$type = E_DEPRECATED;
}
// Level is the current error reporting level to manage silent error.
$level = error_reporting();
$silenced = 0 === ($level & $type);
@@ -438,7 +442,7 @@ class ErrorHandler
self::$silencedErrorCache[$id][$message] = $errorAsException;
}
if (null === $lightTrace) {
return;
return true;
}
} else {
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
@@ -454,7 +458,7 @@ class ErrorHandler
}
if ($throw) {
if (E_USER_ERROR & $type) {
if (\PHP_VERSION_ID < 70400 && E_USER_ERROR & $type) {
for ($i = 1; isset($backtrace[$i]); ++$i) {
if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
&& '__toString' === $backtrace[$i]['function']
@@ -571,7 +575,9 @@ class ErrorHandler
$this->exceptionHandler = null;
try {
if (null !== $exceptionHandler) {
return $exceptionHandler($exception);
$exceptionHandler($exception);
return;
}
$handlerException = $handlerException ?: $exception;
} catch (\Throwable $handlerException) {

View File

@@ -172,8 +172,8 @@ class FlattenException
public function setMessage($message)
{
if (false !== strpos($message, "class@anonymous\0")) {
$message = preg_replace_callback('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/', function ($m) {
return \class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
$message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:)[0-9a-fA-F]++/', function ($m) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
}, $message);
}

View File

@@ -54,7 +54,7 @@ class SilencedErrorContext implements \JsonSerializable
return $this->trace;
}
public function JsonSerialize()
public function jsonSerialize()
{
return [
'severity' => $this->severity,

View File

@@ -252,7 +252,11 @@ EOF
foreach ($e['trace'] as $trace) {
$content .= '<tr><td>';
if ($trace['function']) {
$content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
$content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>', $this->formatClass($trace['class']), $trace['type'], $trace['function']);
if (isset($trace['args'])) {
$content .= sprintf('(<span class="trace-arguments">%s</span>)', $this->formatArgs($trace['args']));
}
}
if (isset($trace['file']) && isset($trace['line'])) {
$content .= $this->formatPath($trace['file'], $trace['line']);
@@ -457,10 +461,10 @@ EOF;
private function addElementToGhost()
{
if (!isset(self::GHOST_ADDONS[\date('m-d')])) {
if (!isset(self::GHOST_ADDONS[date('m-d')])) {
return '';
}
return '<path d="'.self::GHOST_ADDONS[\date('m-d')].'" fill="#fff" fill-opacity="0.6"></path>';
return '<path d="'.self::GHOST_ADDONS[date('m-d')].'" fill="#fff" fill-opacity="0.6"></path>';
}
}

View File

@@ -33,11 +33,11 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
$notFoundSuffix = '\' not found';
$notFoundSuffixLen = \strlen($notFoundSuffix);
if ($notFoundSuffixLen > $messageLen) {
return;
return null;
}
if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
return;
return null;
}
foreach (['class', 'interface', 'trait'] as $typeName) {
@@ -71,6 +71,8 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
return new ClassNotFoundException($message, $exception);
}
return null;
}
/**

View File

@@ -30,17 +30,17 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
$notFoundSuffix = '()';
$notFoundSuffixLen = \strlen($notFoundSuffix);
if ($notFoundSuffixLen > $messageLen) {
return;
return null;
}
if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
return;
return null;
}
$prefix = 'Call to undefined function ';
$prefixLen = \strlen($prefix);
if (0 !== strpos($error['message'], $prefix)) {
return;
return null;
}
$fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);

View File

@@ -28,7 +28,7 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
{
preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
if (!$matches) {
return;
return null;
}
$className = $matches[1];

View File

@@ -1,4 +1,4 @@
Copyright (c) 2004-2019 Fabien Potencier
Copyright (c) 2004-2020 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

@@ -6,7 +6,7 @@ The Debug component provides tools to ease debugging PHP code.
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/debug/index.html)
* [Documentation](https://symfony.com/doc/current/components/debug.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)

View File

@@ -23,7 +23,7 @@ class DebugClassLoaderTest extends TestCase
private $loader;
protected function setUp()
protected function setUp(): void
{
$this->errorReporting = error_reporting(E_ALL);
$this->loader = new ClassLoader();
@@ -31,7 +31,7 @@ class DebugClassLoaderTest extends TestCase
DebugClassLoader::enable();
}
protected function tearDown()
protected function tearDown(): void
{
DebugClassLoader::disable();
spl_autoload_unregister([$this->loader, 'loadClass']);
@@ -58,49 +58,43 @@ class DebugClassLoaderTest extends TestCase
$this->fail('DebugClassLoader did not register');
}
/**
* @expectedException \Exception
* @expectedExceptionMessage boo
*/
public function testThrowingClass()
{
$this->expectException('Exception');
$this->expectExceptionMessage('boo');
try {
class_exists(__NAMESPACE__.'\Fixtures\Throwing');
class_exists(Fixtures\Throwing::class);
$this->fail('Exception expected');
} catch (\Exception $e) {
$this->assertSame('boo', $e->getMessage());
}
// the second call also should throw
class_exists(__NAMESPACE__.'\Fixtures\Throwing');
class_exists(Fixtures\Throwing::class);
}
/**
* @expectedException \RuntimeException
*/
public function testNameCaseMismatch()
{
class_exists(__NAMESPACE__.'\TestingCaseMismatch', true);
$this->expectException('RuntimeException');
$this->expectExceptionMessage('Case mismatch between loaded and declared class names');
class_exists(TestingCaseMismatch::class, true);
}
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Case mismatch between class and real file names
*/
public function testFileCaseMismatch()
{
$this->expectException('RuntimeException');
$this->expectExceptionMessage('Case mismatch between class and real file names');
if (!file_exists(__DIR__.'/Fixtures/CaseMismatch.php')) {
$this->markTestSkipped('Can only be run on case insensitive filesystems');
}
class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true);
class_exists(Fixtures\CaseMismatch::class, true);
}
/**
* @expectedException \RuntimeException
*/
public function testPsr4CaseMismatch()
{
$this->expectException('RuntimeException');
$this->expectExceptionMessage('Case mismatch between loaded and declared class names');
class_exists(__NAMESPACE__.'\Fixtures\Psr4CaseMismatch', true);
}
@@ -116,7 +110,7 @@ class DebugClassLoaderTest extends TestCase
public function testClassAlias()
{
$this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\ClassAlias', true));
$this->assertTrue(class_exists(Fixtures\ClassAlias::class, true));
}
/**
@@ -158,7 +152,7 @@ class DebugClassLoaderTest extends TestCase
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
class_exists('Test\\'.__NAMESPACE__.'\\NonDeprecatedInterfaceClass', true);
class_exists('Test\\'.NonDeprecatedInterfaceClass::class, true);
error_reporting($e);
restore_error_handler();
@@ -205,7 +199,7 @@ class DebugClassLoaderTest extends TestCase
require __DIR__.'/Fixtures/FinalClasses.php';
$i = 1;
while (class_exists($finalClass = __NAMESPACE__.'\\Fixtures\\FinalClass'.$i++, false)) {
while (class_exists($finalClass = Fixtures\FinalClass::class.$i++, false)) {
spl_autoload_call($finalClass);
class_exists('Test\\'.__NAMESPACE__.'\\Extends'.substr($finalClass, strrpos($finalClass, '\\') + 1), true);
}
@@ -231,7 +225,7 @@ class DebugClassLoaderTest extends TestCase
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true);
class_exists(Fixtures\ExtendedFinalMethod::class, true);
error_reporting($e);
restore_error_handler();
@@ -250,7 +244,7 @@ class DebugClassLoaderTest extends TestCase
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true);
class_exists('Test\\'.ExtendsAnnotatedClass::class, true);
error_reporting($e);
restore_error_handler();
@@ -267,7 +261,7 @@ class DebugClassLoaderTest extends TestCase
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true);
class_exists('Test\\'.ExtendsInternals::class, true);
error_reporting($e);
restore_error_handler();
@@ -286,7 +280,7 @@ class DebugClassLoaderTest extends TestCase
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists(__NAMESPACE__.'\\Fixtures\SubClassWithAnnotatedParameters', true);
class_exists(Fixtures\SubClassWithAnnotatedParameters::class, true);
error_reporting($e);
restore_error_handler();
@@ -309,7 +303,7 @@ class DebugClassLoaderTest extends TestCase
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists('Test\\'.__NAMESPACE__.'\\UseTraitWithInternalMethod', true);
class_exists('Test\\'.UseTraitWithInternalMethod::class, true);
error_reporting($e);
restore_error_handler();
@@ -323,7 +317,7 @@ class DebugClassLoaderTest extends TestCase
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsVirtual', true);
class_exists('Test\\'.ExtendsVirtual::class, true);
error_reporting($e);
restore_error_handler();
@@ -349,7 +343,7 @@ class DebugClassLoaderTest extends TestCase
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsVirtualMagicCall', true);
class_exists('Test\\'.ExtendsVirtualMagicCall::class, true);
error_reporting($e);
restore_error_handler();
@@ -359,7 +353,7 @@ class DebugClassLoaderTest extends TestCase
public function testEvaluatedCode()
{
$this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\DefinitionInEvaluatedCode', true));
$this->assertTrue(class_exists(Fixtures\DefinitionInEvaluatedCode::class, true));
}
}
@@ -378,11 +372,11 @@ class ClassLoader
{
$fixtureDir = __DIR__.\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR;
if (__NAMESPACE__.'\TestingUnsilencing' === $class) {
if (TestingUnsilencing::class === $class) {
eval('-- parse error --');
} elseif (__NAMESPACE__.'\TestingStacking' === $class) {
} elseif (TestingStacking::class === $class) {
eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }');
} elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
} elseif (TestingCaseMismatch::class === $class) {
eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
} elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
return $fixtureDir.'psr4'.\DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
@@ -392,57 +386,59 @@ class ClassLoader
return $fixtureDir.'notPsr0Bis.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) {
} elseif ('Test\\'.DeprecatedParentClass::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedParentClass extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}');
} elseif ('Test\\'.__NAMESPACE__.'\DeprecatedInterfaceClass' === $class) {
} elseif ('Test\\'.DeprecatedInterfaceClass::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class DeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\DeprecatedInterface {}');
} elseif ('Test\\'.__NAMESPACE__.'\NonDeprecatedInterfaceClass' === $class) {
} elseif ('Test\\'.NonDeprecatedInterfaceClass::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}');
} elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) {
} elseif ('Test\\'.Float::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
} elseif (0 === strpos($class, 'Test\\'.__NAMESPACE__.'\ExtendsFinalClass')) {
} elseif (0 === strpos($class, 'Test\\'.ExtendsFinalClass::class)) {
$classShortName = substr($class, strrpos($class, '\\') + 1);
eval('namespace Test\\'.__NAMESPACE__.'; class '.$classShortName.' extends \\'.__NAMESPACE__.'\Fixtures\\'.substr($classShortName, 7).' {}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) {
} elseif ('Test\\'.ExtendsAnnotatedClass::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass {
public function deprecatedMethod() { }
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) {
} elseif ('Test\\'.ExtendsInternals::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent {
use \\'.__NAMESPACE__.'\Fixtures\InternalTrait;
public function internalMethod() { }
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) {
} elseif ('Test\\'.ExtendsInternalsParent::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }');
} elseif ('Test\\'.__NAMESPACE__.'\UseTraitWithInternalMethod' === $class) {
} elseif ('Test\\'.UseTraitWithInternalMethod::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class UseTraitWithInternalMethod { use \\'.__NAMESPACE__.'\Fixtures\TraitWithInternalMethod; }');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtual' === $class) {
} elseif ('Test\\'.ExtendsVirtual::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsVirtual extends ExtendsVirtualParent implements \\'.__NAMESPACE__.'\Fixtures\VirtualSubInterface {
public function ownClassMethod() { }
public function classMethod() { }
public function sameLineInterfaceMethodNoBraces() { }
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualParent' === $class) {
} elseif ('Test\\'.ExtendsVirtualParent::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsVirtualParent extends ExtendsVirtualAbstract {
public function ownParentMethod() { }
public function traitMethod() { }
public function sameLineInterfaceMethod() { }
public function staticMethodNoBraces() { } // should be static
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualAbstract' === $class) {
} elseif ('Test\\'.ExtendsVirtualAbstract::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; abstract class ExtendsVirtualAbstract extends ExtendsVirtualAbstractBase {
public static function staticMethod() { }
public function ownAbstractMethod() { }
public function interfaceMethod() { }
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualAbstractBase' === $class) {
} elseif ('Test\\'.ExtendsVirtualAbstractBase::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; abstract class ExtendsVirtualAbstractBase extends \\'.__NAMESPACE__.'\Fixtures\VirtualClass implements \\'.__NAMESPACE__.'\Fixtures\VirtualInterface {
public function ownAbstractBaseMethod() { }
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualMagicCall' === $class) {
} elseif ('Test\\'.ExtendsVirtualMagicCall::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsVirtualMagicCall extends \\'.__NAMESPACE__.'\Fixtures\VirtualClassMagicCall implements \\'.__NAMESPACE__.'\Fixtures\VirtualInterface {
}');
}
return null;
}
}

View File

@@ -70,8 +70,8 @@ class ErrorHandlerTest extends TestCase
public function testErrorGetLast()
{
$handler = ErrorHandler::register();
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$handler->setDefaultLogger($logger);
$handler->screamAt(E_ALL);
@@ -143,9 +143,8 @@ class ErrorHandlerTest extends TestCase
public function testDefaultLogger()
{
try {
$handler = ErrorHandler::register();
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$handler->setDefaultLogger($logger, E_NOTICE);
$handler->setDefaultLogger($logger, [E_USER_NOTICE => LogLevel::CRITICAL]);
@@ -284,6 +283,10 @@ class ErrorHandlerTest extends TestCase
public function testHandleUserError()
{
if (\PHP_VERSION_ID >= 70400) {
$this->markTestSkipped('PHP 7.4 allows __toString to throw exceptions');
}
try {
$handler = ErrorHandler::register();
$handler->throwAt(0, true);
@@ -331,12 +334,11 @@ class ErrorHandlerTest extends TestCase
public function testHandleException()
{
try {
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$exception = new \Exception('foo');
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$logArgCheck = function ($level, $message, $context) {
$this->assertSame('Uncaught Exception: foo', $message);
$this->assertArrayHasKey('exception', $context);
@@ -442,6 +444,7 @@ class ErrorHandlerTest extends TestCase
public function testHandleFatalError()
{
try {
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$handler = ErrorHandler::register();
$error = [
@@ -451,8 +454,6 @@ class ErrorHandlerTest extends TestCase
'line' => 123,
];
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$logArgCheck = function ($level, $message, $context) {
$this->assertEquals('Fatal Parse Error: foo', $message);
$this->assertArrayHasKey('exception', $context);
@@ -494,11 +495,9 @@ class ErrorHandlerTest extends TestCase
$this->assertStringStartsWith("Attempted to load class \"IReallyReallyDoNotExistAnywhereInTheRepositoryISwear\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
}
/**
* @expectedException \Exception
*/
public function testCustomExceptionHandler()
{
$this->expectException('Exception');
$handler = new ErrorHandler();
$handler->setExceptionHandler(function ($e) use ($handler) {
$handler->handleException($e);

View File

@@ -237,6 +237,10 @@ class FlattenExceptionTest extends TestCase
public function testArguments()
{
if (\PHP_VERSION_ID >= 70400) {
$this->markTestSkipped('PHP 7.4 removes arguments from exception traces.');
}
$dh = opendir(__DIR__);
$fh = tmpfile();
@@ -294,22 +298,30 @@ class FlattenExceptionTest extends TestCase
// assertEquals() does not like NAN values.
$this->assertEquals($array[$i][0], 'float');
$this->assertTrue(is_nan($array[$i++][1]));
$this->assertNan($array[$i][1]);
}
public function testRecursionInArguments()
{
if (\PHP_VERSION_ID >= 70400) {
$this->markTestSkipped('PHP 7.4 removes arguments from exception traces.');
}
$a = null;
$a = ['foo', [2, &$a]];
$exception = $this->createException($a);
$flattened = FlattenException::create($exception);
$trace = $flattened->getTrace();
$this->assertContains('*DEEP NESTED ARRAY*', serialize($trace));
$this->assertStringContainsString('*DEEP NESTED ARRAY*', serialize($trace));
}
public function testTooBigArray()
{
if (\PHP_VERSION_ID >= 70400) {
$this->markTestSkipped('PHP 7.4 removes arguments from exception traces.');
}
$a = [];
for ($i = 0; $i < 20; ++$i) {
for ($j = 0; $j < 50; ++$j) {
@@ -329,8 +341,8 @@ class FlattenExceptionTest extends TestCase
$serializeTrace = serialize($trace);
$this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace);
$this->assertNotContains('*value1*', $serializeTrace);
$this->assertStringContainsString('*SKIPPED over 10000 entries*', $serializeTrace);
$this->assertStringNotContainsString('*value1*', $serializeTrace);
}
public function testAnonymousClass()

View File

@@ -21,12 +21,12 @@ require_once __DIR__.'/HeaderMock.php';
class ExceptionHandlerTest extends TestCase
{
protected function setUp()
protected function setUp(): void
{
testHeader();
}
protected function tearDown()
protected function tearDown(): void
{
testHeader();
}
@@ -39,8 +39,8 @@ class ExceptionHandlerTest extends TestCase
$handler->sendPhpResponse(new \RuntimeException('Foo'));
$response = ob_get_clean();
$this->assertContains('Whoops, looks like something went wrong.', $response);
$this->assertNotContains('<div class="trace trace-as-html">', $response);
$this->assertStringContainsString('Whoops, looks like something went wrong.', $response);
$this->assertStringNotContainsString('<div class="trace trace-as-html">', $response);
$handler = new ExceptionHandler(true);
@@ -48,8 +48,8 @@ class ExceptionHandlerTest extends TestCase
$handler->sendPhpResponse(new \RuntimeException('Foo'));
$response = ob_get_clean();
$this->assertContains('<h1 class="break-long-words exception-message">Foo</h1>', $response);
$this->assertContains('<div class="trace trace-as-html">', $response);
$this->assertStringContainsString('<h1 class="break-long-words exception-message">Foo</h1>', $response);
$this->assertStringContainsString('<div class="trace trace-as-html">', $response);
// taken from https://www.owasp.org/index.php/Cross-site_Scripting_(XSS)
$htmlWithXss = '<body onload=alert(\'test1\')> <b onmouseover=alert(\'Wufff!\')>click me!</b> <img src="j&#X41vascript:alert(\'test2\')"> <meta http-equiv="refresh"
@@ -58,7 +58,7 @@ content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg"
$handler->sendPhpResponse(new \RuntimeException($htmlWithXss));
$response = ob_get_clean();
$this->assertContains(sprintf('<h1 class="break-long-words exception-message">%s</h1>', htmlspecialchars($htmlWithXss, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8')), $response);
$this->assertStringContainsString(sprintf('<h1 class="break-long-words exception-message">%s</h1>', htmlspecialchars($htmlWithXss, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8')), $response);
}
public function testStatusCode()
@@ -69,7 +69,7 @@ content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg"
$handler->sendPhpResponse(new NotFoundHttpException('Foo'));
$response = ob_get_clean();
$this->assertContains('Sorry, the page you are looking for could not be found.', $response);
$this->assertStringContainsString('Sorry, the page you are looking for could not be found.', $response);
$expectedHeaders = [
['HTTP/1.0 404', true, null],
@@ -85,7 +85,7 @@ content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg"
ob_start();
$handler->sendPhpResponse(new MethodNotAllowedHttpException(['POST']));
$response = ob_get_clean();
ob_get_clean();
$expectedHeaders = [
['HTTP/1.0 405', true, null],
@@ -108,35 +108,65 @@ content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg"
public function testHandle()
{
$exception = new \Exception('foo');
$handler = new ExceptionHandler(true);
ob_start();
$handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(['sendPhpResponse'])->getMock();
$handler
->expects($this->exactly(2))
->method('sendPhpResponse');
$handler->handle(new \Exception('foo'));
$handler->handle($exception);
$this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'foo');
}
$handler->setHandler(function ($e) use ($exception) {
$this->assertSame($exception, $e);
public function testHandleWithACustomHandlerThatOutputsSomething()
{
$handler = new ExceptionHandler(true);
ob_start();
$handler->setHandler(function () {
echo 'ccc';
});
$handler->handle($exception);
$handler->handle(new \Exception());
ob_end_flush(); // Necessary because of this PHP bug : https://bugs.php.net/76563
$this->assertSame('ccc', ob_get_clean());
}
public function testHandleWithACustomHandlerThatOutputsNothing()
{
$handler = new ExceptionHandler(true);
$handler->setHandler(function () {});
$handler->handle(new \Exception('ccc'));
$this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'ccc');
}
public function testHandleWithACustomHandlerThatFails()
{
$handler = new ExceptionHandler(true);
$handler->setHandler(function () {
throw new \RuntimeException();
});
$handler->handle(new \Exception('ccc'));
$this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'ccc');
}
public function testHandleOutOfMemoryException()
{
$exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__);
$handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(['sendPhpResponse'])->getMock();
$handler
->expects($this->once())
->method('sendPhpResponse');
$handler->setHandler(function ($e) {
$handler = new ExceptionHandler(true);
ob_start();
$handler->setHandler(function () {
$this->fail('OutOfMemoryException should bypass the handler');
});
$handler->handle($exception);
$handler->handle(new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__));
$this->assertThatTheExceptionWasOutput(ob_get_clean(), OutOfMemoryException::class, 'OutOfMemoryException', 'foo');
}
private function assertThatTheExceptionWasOutput($content, $expectedClass, $expectedTitle, $expectedMessage)
{
$this->assertStringContainsString(sprintf('<span class="exception_title"><abbr title="%s">%s</abbr></span>', $expectedClass, $expectedTitle), $content);
$this->assertStringContainsString(sprintf('<p class="break-long-words trace-message">%s</p>', $expectedMessage), $content);
}
}

View File

@@ -19,7 +19,7 @@ use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
class ClassNotFoundFatalErrorHandlerTest extends TestCase
{
public static function setUpBeforeClass()
public static function setUpBeforeClass(): void
{
foreach (spl_autoload_functions() as $function) {
if (!\is_array($function)) {
@@ -29,10 +29,14 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
// get class loaders wrapped by DebugClassLoader
if ($function[0] instanceof DebugClassLoader) {
$function = $function[0]->getClassLoader();
if (!\is_array($function)) {
continue;
}
}
if ($function[0] instanceof ComposerClassLoader) {
$function[0]->add('Symfony_Component_Debug_Tests_Fixtures', \dirname(\dirname(\dirname(\dirname(\dirname(__DIR__))))));
$function[0]->add('Symfony_Component_Debug_Tests_Fixtures', \dirname(__DIR__, 5));
break;
}
}
@@ -61,7 +65,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
}
$this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
$this->assertSame($translatedMessage, $exception->getMessage());
$this->assertRegExp($translatedMessage, $exception->getMessage());
$this->assertSame($error['type'], $exception->getSeverity());
$this->assertSame($error['file'], $exception->getFile());
$this->assertSame($error['line'], $exception->getLine());
@@ -71,6 +75,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
{
$autoloader = new ComposerClassLoader();
$autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception'));
$autoloader->add('Symfony_Component_Debug_Tests_Fixtures', realpath(__DIR__.'/../../Tests/Fixtures'));
$debugClassLoader = new DebugClassLoader([$autoloader, 'loadClass']);
@@ -82,7 +87,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
'file' => 'foo.php',
'message' => 'Class \'WhizBangFactory\' not found',
],
"Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?",
"/^Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement\?$/",
],
[
[
@@ -91,7 +96,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found',
],
"Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?",
"/^Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/",
],
[
[
@@ -100,7 +105,8 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
'file' => 'foo.php',
'message' => 'Class \'UndefinedFunctionException\' not found',
],
"Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
"/^Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for .*\"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/",
[$debugClassLoader, 'loadClass'],
],
[
[
@@ -109,35 +115,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
'file' => 'foo.php',
'message' => 'Class \'PEARClass\' not found',
],
"Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"?",
],
[
[
'type' => 1,
'line' => 12,
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
],
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
],
[
[
'type' => 1,
'line' => 12,
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
],
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
[$autoloader, 'loadClass'],
],
[
[
'type' => 1,
'line' => 12,
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
],
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?",
"/^Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"\?$/",
[$debugClassLoader, 'loadClass'],
],
[
@@ -147,7 +125,37 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
],
"Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?",
"/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for .*\"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/",
[$debugClassLoader, 'loadClass'],
],
[
[
'type' => 1,
'line' => 12,
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
],
"/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for \"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/",
[$autoloader, 'loadClass'],
],
[
[
'type' => 1,
'line' => 12,
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
],
"/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for \"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?/",
[$debugClassLoader, 'loadClass'],
],
[
[
'type' => 1,
'line' => 12,
'file' => 'foo.php',
'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
],
"/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/",
function ($className) { /* do nothing here */ },
],
];

View File

@@ -1,24 +0,0 @@
<?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\Tests;
use Symfony\Component\Debug\ExceptionHandler;
class MockExceptionHandler extends ExceptionHandler
{
public $e;
public function handle(\Exception $e)
{
$this->e = $e;
}
}