Compare commits

...

82 Commits
v4.2.11 ... 4.3

Author SHA1 Message Date
Nicolas Grekas
8e36299635 Fix displaying anonymous classes on PHP >= 7.4.2 2020-01-25 13:32:28 +01:00
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
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
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
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
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
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
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
Nicolas Grekas
4e025104f1 Merge branch '4.2' into 4.3
* 4.2:
  Use willReturn() instead of will(returnValue()).
2019-05-30 18:10:05 +02:00
Nicolas Grekas
97cde06d79 Merge branch '4.2' into 4.3
* 4.2:
  minor: add some test in the ldap component
  [Bridge\ProxyManager] isProxyCandidate() does not take into account interfaces
  [Routing][AnnotationClassLoader] fix utf-8 encoding in default route name
  fixed a phpdoc
  [Debug] Wrap call to require_once in a try/catch
  prevent deprecation when filesize matches error code
  [PropertyInfo] Add missing documentation link in Readme
  Use the current working dir as default first arg in 'link' binary
  Respect parent class contract in ContainerAwareDoctrineEventManager
  [Validator] Add the missing translations for the Danish ("da") locale
  [PropertyAccess] Add missing property to PropertyAccessor
  [Cache] fix saving unrelated keys in recursive callback calls
  [Serializer] Fix denormalization of object with variadic constructor typed argument
  Allow set 'None' on samesite cookie flag
  Making cache rebuild correctly with MessageSubscriberInterface return values
  Fix finding parent definition
2019-05-20 18:16:12 +02:00
Nicolas Grekas
bcb342fd9c Merge branch '4.2'
* 4.2:
  Catch empty deprecation.log silently (fixes #31050)
  minor: the meaning of the data breach was not correct
  Optimize SVGs
  property normalizer should also pass format and context to isAllowedAttribute
2019-04-11 14:10:52 +02:00
Christian Flothmann
dba19a100b Merge branch '4.2'
* 4.2:
  fix tests
  fix PHPUnit 4.8 compatibility
  [Debug] Fixed error handling when an error is already handled when another error is already handled (5)
  sync validator translations
2019-04-07 21:49:19 +02:00
Nicolas Grekas
85c2c0c26f Merge branch '4.2'
* 4.2:
  fix translating file validation error message
  [Validator] Add missing Hungarian translations
  Improving deprecation message of the Twig templates directory src/Resources/views
  [3.4] [Validator] Add missing french validation translations.
  [Validator] Only traverse arrays that are cascaded into
  Handle case where no translations were found
  [Validator] Translate unique collection message to Hungarian
  fix tests
  Run test in separate process
  Use a class name that does not actually exist
  [Profiler] Fix dark theme elements color
  fix horizontal spacing of inlined Bootstrap forms
  [Translator] Warm up the translations cache in dev
  turn failed file uploads into form errors
2019-04-07 11:58:10 +02:00
Fabien Potencier
91691fa245 feature #28879 [Debug] Mimic __toString php behavior in FlattenException (Deltachaos)
This PR was merged into the 4.3-dev branch.

Discussion
----------

[Debug] Mimic __toString php behavior in FlattenException

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

The `Symfony\Component\Debug\Exception\FlattenException` object is returned by `Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector::getException` method, but the docblock of this method indicates that it should return `\Exception` object.

As the `FlattenException` class should behave as much as possible like a php `\Exception` object, it should implement the same methods as `\Exception`.

This PR is adding `__toString` and `getTraceAsString` methods. Those methods are (in my opinion) the most useful methods of a `\Exception` object. A potential use case (where i am stumbled across this inconsistency) is to get the last exception of a request in a `WebTestCase` using the profiler and printing the trace.

Commits
-------

514a1b506c [Debug] Mimic __toString php behavior in FlattenException
2019-03-31 11:12:58 +02:00
Nicolas Grekas
2a9e82faff Merge branch '4.2'
* 4.2:
  [TwigBridge] remove deprecation triggered when using Twig 2.7
2019-03-10 18:10:06 +01:00
Nicolas Grekas
6d4484cd4b Merge branch '4.2'
* 4.2: (27 commits)
  cs fix
  cs fix
  [PHPUnit-Bridge] override some environment variables
  [TwigBridge] Remove use spaceless tag
  Upgrade zookeeper ext
  [translation] Update defaut format from yml to yaml
  Change default log level for output streams
  update docblock to match the actual behavior
  Don't resolve the Deprecation error handler mode until a deprecation is triggered
  compatibility with phpunit8
  Make 'headers' key optional for encoded messages
  [Debug][DebugClassLoader] Detect annotations before blank docblock lines on final and internal methods
  Fix undefined variable fromConstructor when passing context to getTypes
  Added translations for chineese language.
  Allow 3rd argument to be null
  Remove whitespace (tab on blank line)
  [Monolog] Really reset logger when calling logger::reset()
  [Form] Fixes debug:form appears many times as type extensions configured with new getExtendedTypes method
  Update src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
  Update src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php
  ...
2019-03-10 11:14:34 +01:00
Fabien Potencier
2372d7084d Merge branch '4.2'
* 4.2:
  detect annotations before blank docblock lines
  Serializer: Use the context in supports calls
2019-03-04 12:23:10 +01:00
Fabien Potencier
5f14d80d8b Merge branch '4.2'
* 4.2:
  fixed CS
  Autoconfig: don't automatically tag decorators
  removed suggestion
  [PropertyAccess] Fixed PropertyPathBuilder remove that fails to reset internal indexes
  bumped Symfony version to 4.2.5
  updated VERSION for 4.2.4
  updated CHANGELOG for 4.2.4
  bumped Symfony version to 3.4.24
  updated VERSION for 3.4.23
  update CONTRIBUTORS for 3.4.23
  updated CHANGELOG for 3.4.23
  [Routing][ServiceRouterLoader] Remove an outdated comment
2019-03-04 10:16:46 +01:00
Nicolas Grekas
2533ffde4d Drop more usages of Serializable 2019-03-04 09:45:35 +01:00
Fabien Potencier
806e831d70 Merge branch '4.2'
* 4.2:
  Removed non-existing parameters for LogoutUrlGenerator calls
  [WebProfilerBundle] toolbar: invisible route name in Firefox
  Drop spurious execution bit
  [HttpKernel] Correctly merging cache directives in HttpCache/ResponseCacheStrategy
  [Validator] Add the missing translations for the Latvian ("lv") locale
  Fixed the DebugClassLoader compatibility with eval()'d code on Darwin
  [Validator] Update Serbian translation file
2019-03-03 19:12:18 +01:00
Nicolas Grekas
a850962740 Merge branch '4.2'
* 4.2: (26 commits)
  Apply php-cs-fixer rule for array_key_exists()
  [Cache] fix warming up cache.system and apcu
  [Security] Change FormAuthenticator if condition
  handles multi-byte characters in autocomplete
  speed up tests running them without debug flag
  [Translations] added missing Croatian validators
  Fix getItems() performance issue with RedisCluster (php-redis)
  [VarDumper] Keep a ref to objects to ensure their handle cannot be reused while cloning
  IntegerType: reject submitted non-integer numbers
  be keen to newcomers
  [HttpKernel] Fix possible infinite loop of exceptions
  fixed CS
  [Validator] Added missing translations for Afrikaans
  do not validate non-submitted form fields in PATCH requests
  Update usage example in ArrayInput doc block.
  [Console] Prevent ArgvInput::getFirstArgument() from returning an option value
  [Validator] Fixed duplicate UUID
  fixed CS
  [EventDispatcher] Fix unknown priority
  Avoid mutating the Finder when building the iterator
  ...
2019-02-23 16:22:31 +01:00
Maximilian Ruta
c6af9101fb [Debug] Mimic __toString php behavior in FlattenException 2019-02-21 14:05:12 +01:00
Przemysław Bogusz
4792c7baab Additional addons for the ghost 2019-02-21 00:39:50 +01:00
Nicolas Grekas
091fd557df Merge branch '4.2'
* 4.2:
  [Console] Fix command testing with missing inputs
  [Validator] Sync no/nb translation files
  [Translation] Added a script to display the status of translations
  [Validator] Added missing translations for Norwegian (\"no\") locale #30179
  [Security\Guard] bump lowest version of security-core
  [TwigBridge] Fix test
  Remove unnecessary ProgressBar stdout writes (fixes flickering)
  [Validator] improve translations for albanian ("sq") locale
  [VarDumper] fix serializing Stub instances
  [Validator] Added missing use statement for UnexpectedTypeException
  Don't resolve the Deprecation error handler mode until a deprecation is triggered
  bug #30245 fix lost namespace in eval (fizzka)
  fix lost namespace in eval
  [Twig] removed usage of non-namespaced classes
  added missing dot
  Update validators.lt.xlf
  #30172 Add the missing validation translations for the Luxembourgish …
  [Debug][ErrorHandler] Preserve next error handler
2019-02-19 19:29:52 +01:00
Przemysław Bogusz
f47ba47df3 Add element to ghost in Exception 2019-02-14 10:10:17 +01:00
Javier Eguiluz
8f517eb954 [Debug] Display more details in the simple error page of Debug 2019-02-07 10:41:41 +01:00
Fabien Potencier
c7ac313d92 minor #29988 [Debug][DebugClassLoader] Match callable() type for parameters not defined in sub classes (fancyweb)
This PR was merged into the 4.3-dev branch.

Discussion
----------

[Debug][DebugClassLoader] Match callable() type for parameters not defined in sub classes

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

Added test fixture for multi param, no param type and multi spaces as well.

BTW, I didn't understand why there was a positive lookbehind on the current regex. Looks useless to me and tests passes without it.

Commits
-------

89c89c9776 [Debug][DebugClassLoader] Match callable() type for parameters not defined in sub classes
2019-01-27 11:31:13 +01:00
Thomas Calvet
97a066c39a [Debug][DebugClassLoader] Match callable() type for parameters not defined in sub classes 2019-01-26 12:58:26 +01:00
Nicolas Grekas
4b3f518420 Merge branch '4.2'
* 4.2:
  [HttpFoundation] Check file exists before unlink
  [Console] Fixed #29835: ConfirmationQuestion with default true for answer '0'
  [Cache] PDO-based cache pool table autocreation does not work
  [Translation] Concatenated translation messages
  [Form] ensure compatibility with older PHPUnit mocks
  [Serializer] Docblock about throwing exceptions on serializer
  [Cache] fix used variable name
  [Debug][ErrorHandler] Preserve our error handler when a logger set another one
  [Form] Changed UrlType input type to text when default_protocol is not null
  [Bugfix] MemcachedSessionHandler::close() must close connection
  Always pass $key to NullAdapter->createCacheItem
2019-01-25 15:35:46 +01:00
Nicolas Grekas
643df31c6a Merge branch '4.2'
* 4.2:
  Bump phpunit bridge cache id
  [appveyor] fix create-project phpunit
  Fix HttpKernel Debug requirement
  Fix heredoc
  use final annotation to allow mocking the class
  synchronise the form builder docblock
  Grammar fix in exception message
  fix tests
  forward the parse error to the calling code
  Avoid dots in generated class names.
  [Debug][DebugClassLoader] Match more cases for final, deprecated and internal classes / methods extends
  ensure compatibility with older PHPUnit mocks
  [Security] Do not mix usage of password_*() functions and sodium_*() ones
2019-01-24 22:40:22 +01:00
Fabien Potencier
7cdd4f6f12 fixed CS 2019-01-16 23:37:52 +01:00
Fabien Potencier
f49c101672 fixed CS 2019-01-16 22:53:45 +01:00
Fabien Potencier
9f1401aebf Merge branch '4.2' into short-array-master
* 4.2:
  fixed CS
  fixed CS
  fixed tests
  fixed CS
  fixed CS
  fixed CS
  fixed short array CS in comments
  fixed CS in ExpressionLanguage fixtures
  fixed CS in generated files
  fixed CS on generated container files
  fixed CS on Form PHP templates
  fixed CS on YAML fixtures
  fixed fixtures
  switched array() to []
2019-01-16 22:53:39 +01:00
Fabien Potencier
789a7a9031 Merge branch '4.2'
* 4.2:
  bump required Twig version
  fix compatibility with Twig >= 2.6.1
  [Form] SA fix
  fix compatibility with PHPUnit 4.8
  remove return type hint for PHP 5 compatibility
  SCA: minor code tweaks
  Component CssSelector tests
  [DebugClassLoader] Readd findFile() method
  [Console] Fix composer.json suggest/provide
  Revert "bug #29597 [DI] fix reporting bindings on overriden services as unused (nicolas-grekas)"
  Fixed exception wording
  Fix SwiftMailerHandler to support Monolog's latest reset functionality
2019-01-14 16:34:34 +01:00
Fabien Potencier
b04503aa3b feature #28902 [Debug] Detect virtual methods using @method (ro0NL)
This PR was squashed before being merged into the 4.3-dev branch (closes #28902).

Discussion
----------

[Debug] Detect virtual methods using @method

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | https://github.com/symfony/symfony/pull/28897#issuecomment-430542792
| License       | MIT
| Doc PR        | https://github.com/symfony/symfony-docs/issues/10504

My first Debug PR, so im still on it. But early feedback welcome.

In #28901 we'll introduce a new virtual interface method using `@method` annotation. IIUC the idea is to trigger whenever such a method is overridden.

Commits
-------

38877c32ac [Debug] Detect virtual methods using @method
2019-01-05 09:11:12 +01:00
Roland Franssen
42fa73a995 [Debug] Detect virtual methods using @method 2019-01-05 09:11:02 +01:00
Christian Flothmann
c0ed02a95c Merge branch '4.2'
* 4.2:
  update years in license files
  Fix: Adjust DocBlock
  \"ParserTest->getParserTestData()\" -> only some more tests
  access the container getting it from the kernel
  Replace slave and master by replica and primary
  Fix erasing cookies issue
  [Lock] Pedantic improvements for lock
  [EventDispatcher] Fixed phpdoc on interface
  update year in license files
  [VarExporter] fix exporting array indexes
  [SecurityBundle] Fix traceable voters
  [Console] Fix help text for single command applications
  Fix random test failure on lock
  improve error message when using test client without the BrowserKit component
  Fixed minor typos in an error message
  [Event Dispatcher] fixed 29703: TraceableEventDispatcher reset now sets callStack to null with test to dispatch after reset.
  Fixed minor typos
  Fix: Method can also return null
  [Stopwatch] Fixed phpdoc for category name
2019-01-03 10:16:58 +01:00
Nicolas Grekas
7f2f295f38 Merge branch '4.2'
* 4.2: (27 commits)
  [VarExporter] dont call userland code with uninitialized objects
  Fix typos in doc blocks
  [Debug] ignore underscore vs backslash namespaces in DebugClassLoader
  [TwigBridge][Form] Prevent multiple rendering of form collection prototypes
  [FrameworkBundle] fix describing routes with no controllers
  [DI] move RegisterServiceSubscribersPass before DecoratorServicePass
  Update ValidationListener.php
  [Yaml] ensures that the mb_internal_encoding is reset to its initial value
  [Messenger] Restore message handlers laziness
  [WebLink] Fixed documentation link
  [Security] getTargetPath of TargetPathTrait must return string or null
  [Hackday][Serializer] Deserialization ignores argument type hint from phpdoc for array in constructor argument
  Optimize perf by replacing call_user_func with dynamic vars
  [Cache] Fix dsn parsing
  [Routing] fix dumping same-path routes with placeholders
  [WebProfilerBundle][TwigBundle] CSS fixes
  Add a docblock for FormFactoryInterface
  [Security] defer log message in guard authenticator
  [Validator] Added IBAN format for Vatican City State
  merge conflicts
  ...
2018-12-13 13:43:21 +01:00
Nicolas Grekas
170e2f8f61 feature #28954 [Debug] Mark ErrorHandler and ExceptionHandler classes as final (fancyweb)
This PR was merged into the 4.3-dev branch.

Discussion
----------

[Debug] Mark ErrorHandler and ExceptionHandler classes as final

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

The goal of marking this method final is to be able to change the argument signature to `\Throwable` in Symfony 5.0

We will then be able to convert the incoming `\Throwable` to `\ErrorException` thanks to the `FatalThrowableError` class.

The use case is when you use the `ExceptionHandler::register()` method of the `Debug` component with a custom `set_error_handler()` that don't handle this conversion. This is for example the case of the `Drupal` one.

Commits
-------

2a4e2e614b [Debug] Mark the ErrorHandler and ExceptionHandler classes as final
2018-12-01 11:04:56 +01:00
Nicolas Grekas
e597d2960c Merge branch '4.2'
* 4.2:
  [DI] fix combinatorial explosion when analyzing the service graph
  [Debug] workaround opcache bug mutating "$this" !?!
2018-11-28 19:24:33 +01:00
Fabien Potencier
fbd644bb30 updated version to 4.3 2018-11-26 17:19:01 +01:00
Thomas Calvet
436274c5b8 [Debug] Mark the ErrorHandler and ExceptionHandler classes as final 2018-10-23 11:56:45 +02:00
25 changed files with 443 additions and 87 deletions

View File

@@ -1,6 +1,14 @@
CHANGELOG
=========
4.3.0
-----
* made the `ErrorHandler` and `ExceptionHandler` classes final
* added `Exception\FlattenException::getAsString` and
`Exception\FlattenException::getTraceAsString` to increase compatibility to php
exception objects
4.0.0
-----

View File

@@ -39,6 +39,7 @@ class DebugClassLoader
private static $internalMethods = [];
private static $annotatedParameters = [];
private static $darwinCache = ['/' => ['/', []]];
private static $method = [];
public function __construct(callable $classLoader)
{
@@ -236,6 +237,24 @@ class DebugClassLoader
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)) {
foreach ($notice as $method) {
$static = '' !== $method[1];
$name = $method[2];
$description = $method[3] ?? null;
if (false === strpos($name, '(')) {
$name .= '()';
}
if (null !== $description) {
$description = trim($description);
if (!isset($method[4])) {
$description .= '.';
}
}
self::$method[$class][] = [$class, $name, $static, $description];
}
}
}
$parent = get_parent_class($class);
@@ -266,6 +285,28 @@ class DebugClassLoader
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])) {
if ($refl->isAbstract()) {
if (isset(self::$method[$class])) {
self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]);
} else {
self::$method[$class] = self::$method[$use];
}
} elseif (!$refl->isInterface()) {
$hasCall = $refl->hasMethod('__call');
$hasStaticCall = $refl->hasMethod('__callStatic');
foreach (self::$method[$use] as $method) {
list($interface, $name, $static, $description) = $method;
if ($static ? $hasStaticCall : $hasCall) {
continue;
}
$realName = substr($name, 0, strpos($name, '('));
if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) {
$deprecations[] = sprintf('Class "%s" should implement method "%s::%s"%s', $class, ($static ? 'static ' : '').$interface, $name, null == $description ? '.' : ': '.$description);
}
}
}
}
}
if (trait_exists($class)) {
@@ -311,7 +352,7 @@ class DebugClassLoader
}
foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) {
if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param (.*?)(?<= )\\\${$parameterName}\\b/", $doc))) {
if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) {
$deprecations[] = sprintf($deprecation, $class);
}
}
@@ -334,7 +375,7 @@ class DebugClassLoader
if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) {
continue;
}
if (!preg_match_all('#\n\s+\* @param (.*?)(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) {
if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) {
continue;
}
if (!isset(self::$annotatedParameters[$class][$method->name])) {
@@ -354,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, '.'));
@@ -370,7 +417,7 @@ class DebugClassLoader
array_splice($tail, 0, $i + 1);
if (!$tail) {
return;
return null;
}
$tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail);
@@ -386,6 +433,8 @@ class DebugClassLoader
) {
return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)];
}
return null;
}
/**
@@ -406,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);
@@ -433,7 +486,7 @@ class DebugClassLoader
}
if (isset($dirFiles[$file])) {
return $real .= $dirFiles[$file];
return $real.$dirFiles[$file];
}
$kFile = strtolower($file);
@@ -452,7 +505,7 @@ class DebugClassLoader
self::$darwinCache[$kDir][1] = $dirFiles;
}
return $real .= $dirFiles[$kFile];
return $real.$dirFiles[$kFile];
}
/**

View File

@@ -45,6 +45,8 @@ use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
*
* @author Nicolas Grekas <p@tchwork.com>
* @author Grégoire Pineau <lyrixx@lyrixx.info>
*
* @final since Symfony 4.3
*/
class ErrorHandler
{
@@ -380,8 +382,7 @@ class ErrorHandler
*/
public function handleError($type, $message, $file, $line)
{
// @deprecated to be removed in Symfony 5.0
if (\PHP_VERSION_ID >= 70300 && $message && '"' === $message[0] && 0 === strpos($message, '"continue') && preg_match('/^"continue(?: \d++)?" targeting switch is equivalent to "break(?: \d++)?"\. Did you mean to use "continue(?: \d++)?"\?$/', $message)) {
if (\PHP_VERSION_ID >= 70300 && E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) {
$type = E_DEPRECATED;
}
@@ -441,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);
@@ -457,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']
@@ -574,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

@@ -27,6 +27,7 @@ class FlattenException
private $code;
private $previous;
private $trace;
private $traceAsString;
private $class;
private $statusCode;
private $headers;
@@ -171,7 +172,7 @@ 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) {
$message = preg_replace_callback('/class@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0];
}, $message);
}
@@ -239,6 +240,8 @@ class FlattenException
public function setTraceFromThrowable(\Throwable $throwable)
{
$this->traceAsString = $throwable->getTraceAsString();
return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
}
@@ -324,4 +327,33 @@ class FlattenException
return $array['__PHP_Incomplete_Class_Name'];
}
public function getTraceAsString()
{
return $this->traceAsString;
}
public function getAsString()
{
$message = '';
$next = false;
foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) {
if ($next) {
$message .= 'Next ';
} else {
$next = true;
}
$message .= $exception->getClass();
if ('' != $exception->getMessage()) {
$message .= ': '.$exception->getMessage();
}
$message .= ' in '.$exception->getFile().':'.$exception->getLine().
"\nStack trace:\n".$exception->getTraceAsString()."\n\n";
}
return rtrim($message);
}
}

View File

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

File diff suppressed because one or more lines are too long

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();
@@ -294,6 +288,11 @@ class DebugClassLoaderTest extends TestCase
$this->assertSame([
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::quzMethod()" method will require a new "Quz $quz" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.',
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::whereAmI()" method will require a new "bool $matrix" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.',
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "$noType" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.',
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "callable(\Throwable|null $reason, mixed $value) $callback" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.',
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "string $param" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.',
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "callable ($a, $b) $anotherOne" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.',
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "Type$WithDollarIsStillAType $ccc" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.',
'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::isSymfony()" method will require a new "true $yes" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.',
], $deprecations);
}
@@ -304,7 +303,47 @@ 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();
$this->assertSame([], $deprecations);
}
public function testVirtualUse()
{
$deprecations = [];
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists('Test\\'.ExtendsVirtual::class, true);
error_reporting($e);
restore_error_handler();
$this->assertSame([
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::sameLineInterfaceMethodNoBraces()".',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::newLineInterfaceMethod()": Some description!',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::newLineInterfaceMethodNoBraces()": Description.',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::invalidInterfaceMethod()".',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::invalidInterfaceMethodNoBraces()".',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::complexInterfaceMethod($arg, ...$args)".',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::complexInterfaceMethodTyped($arg, int ...$args)": Description ...',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "static Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::staticMethodNoBraces()".',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "static Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::staticMethodTyped(int $arg)": Description.',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "static Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::staticMethodTypedNoBraces()".',
'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtual" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualSubInterface::subInterfaceMethod()".',
], $deprecations);
}
public function testVirtualUseWithMagicCall()
{
$deprecations = [];
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists('Test\\'.ExtendsVirtualMagicCall::class, true);
error_reporting($e);
restore_error_handler();
@@ -314,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));
}
}
@@ -333,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';
@@ -347,31 +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\\'.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\\'.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\\'.ExtendsVirtualAbstract::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; abstract class ExtendsVirtualAbstract extends ExtendsVirtualAbstractBase {
public static function staticMethod() { }
public function ownAbstractMethod() { }
public function interfaceMethod() { }
}');
} 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\\'.ExtendsVirtualMagicCall::class === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsVirtualMagicCall extends \\'.__NAMESPACE__.'\Fixtures\VirtualClassMagicCall implements \\'.__NAMESPACE__.'\Fixtures\VirtualInterface {
}');
}
return null;
}
}

View File

@@ -283,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);
@@ -491,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()
@@ -346,6 +358,41 @@ class FlattenExceptionTest extends TestCase
$this->assertSame('Class "RuntimeException@anonymous" blah.', $flattened->getMessage());
}
public function testToStringEmptyMessage()
{
$exception = new \RuntimeException();
$flattened = FlattenException::create($exception);
$this->assertSame($exception->getTraceAsString(), $flattened->getTraceAsString());
$this->assertSame($exception->__toString(), $flattened->getAsString());
}
public function testToString()
{
$test = function ($a, $b, $c, $d) {
return new \RuntimeException('This is a test message');
};
$exception = $test('foo123', 1, null, 1.5);
$flattened = FlattenException::create($exception);
$this->assertSame($exception->getTraceAsString(), $flattened->getTraceAsString());
$this->assertSame($exception->__toString(), $flattened->getAsString());
}
public function testToStringParent()
{
$exception = new \LogicException('This is message 1');
$exception = new \RuntimeException('This is messsage 2', 500, $exception);
$flattened = FlattenException::create($exception);
$this->assertSame($exception->getTraceAsString(), $flattened->getTraceAsString());
$this->assertSame($exception->__toString(), $flattened->getAsString());
}
private function createException($foo)
{
return new \Exception();

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,17 @@ class ExceptionHandlerTest extends TestCase
$handler->sendPhpResponse(new \RuntimeException('Foo'));
$response = ob_get_clean();
$this->assertContains('Whoops, looks like something went wrong.', $response);
$this->assertContains('<div class="trace trace-as-html">', $response);
$this->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"
content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">';
ob_start();
$handler->sendPhpResponse(new \RuntimeException($htmlWithXss));
$response = ob_get_clean();
$this->assertStringContainsString(sprintf('<h1 class="break-long-words exception-message">%s</h1>', htmlspecialchars($htmlWithXss, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8')), $response);
}
public function testStatusCode()
@@ -60,7 +69,7 @@ class ExceptionHandlerTest extends TestCase
$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],
@@ -116,7 +125,7 @@ class ExceptionHandlerTest extends TestCase
});
$handler->handle(new \Exception());
ob_end_flush(); // Necessary because of this PHP bug : https://bugs.php.net/bug.php?id=76563
ob_end_flush(); // Necessary because of this PHP bug : https://bugs.php.net/76563
$this->assertSame('ccc', ob_get_clean());
}
@@ -157,7 +166,7 @@ class ExceptionHandlerTest extends TestCase
private function assertThatTheExceptionWasOutput($content, $expectedClass, $expectedTitle, $expectedMessage)
{
$this->assertContains(sprintf('<span class="exception_title"><abbr title="%s">%s</abbr></span>', $expectedClass, $expectedTitle), $content);
$this->assertContains(sprintf('<p class="break-long-words trace-message">%s</p>', $expectedMessage), $content);
$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;
}
}

View File

@@ -11,4 +11,17 @@ interface InterfaceWithAnnotatedParameters
* @param bool $matrix
*/
public function whereAmI();
/**
* @param $noType
* @param callable(\Throwable|null $reason, mixed $value) $callback and a comment
* about this great param
* @param string $param (comment with $dollar)
* @param $defined
* @param callable ($a, $b) $anotherOne
* @param callable (mixed $a, $b) $definedCallable
* @param Type$WithDollarIsStillAType $ccc
* @param \JustAType
*/
public function iAmHere();
}

View File

@@ -21,4 +21,12 @@ class SubClassWithAnnotatedParameters extends ClassWithAnnotatedParameters imple
public function whereAmI()
{
}
/**
* @param $defined
* @param Type\Does\Not\Matter $definedCallable
*/
public function iAmHere()
{
}
}

View File

@@ -0,0 +1,11 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @method string classMethod()
*/
class VirtualClass
{
use VirtualTrait;
}

View File

@@ -0,0 +1,18 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @method string magicMethod()
* @method static string staticMagicMethod()
*/
class VirtualClassMagicCall
{
public static function __callStatic($name, $arguments)
{
}
public function __call($name, $arguments)
{
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @method string interfaceMethod()
* @method sameLineInterfaceMethod($arg)
* @method sameLineInterfaceMethodNoBraces
*
* Ignored
* @method
* @method
*
* Not ignored
* @method newLineInterfaceMethod() Some description!
* @method \stdClass newLineInterfaceMethodNoBraces Description
*
* Invalid
* @method unknownType invalidInterfaceMethod()
* @method unknownType|string invalidInterfaceMethodNoBraces
*
* Complex
* @method complexInterfaceMethod($arg, ...$args)
* @method string[]|int complexInterfaceMethodTyped($arg, int ...$args) Description ...
*
* Static
* @method static Foo&Bar staticMethod()
* @method static staticMethodNoBraces
* @method static \stdClass staticMethodTyped(int $arg) Description
* @method static \stdClass[] staticMethodTypedNoBraces
*/
interface VirtualInterface
{
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @method string subInterfaceMethod()
*/
interface VirtualSubInterface extends VirtualInterface
{
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @method string traitMethod()
*/
trait VirtualTrait
{
}

View File

@@ -24,7 +24,7 @@ var_dump([
$eHandler[0]->setExceptionHandler('print_r');
if (true) {
class Broken implements \Serializable
class Broken implements \JsonSerializable
{
}
}
@@ -37,6 +37,6 @@ array(1) {
}
object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) {
["message":protected]=>
string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)"
string(179) "Error: Class Symfony\Component\Debug\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)"
%a
}

View File

@@ -34,7 +34,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "4.2-dev"
"dev-master": "4.3-dev"
}
}
}