Compare commits

...

71 Commits
3.3 ... v4.0.2

Author SHA1 Message Date
Nicolas Grekas
8c3e709209 Merge branch '3.4' into 4.0
* 3.4: (22 commits)
  fix merge
  [Translation] Fix InvalidArgumentException when using untranslated plural forms from .po files
  Fixed exit code with non-integer throwable code
  [HttpFoundation] Support 0 bit netmask in IPv6 ()
  [DI] Impossible to set an environment variable and then an array as container parameter
  [Process] remove false-positive BC breaking exception on Windows
  Tweaking class not found autowiring error
  [LDAP] added missing dots at the end of some exception messages.
  [TwigBridge] Add missing dev requirement for workflow
  fixed #25440
  empty lines don't count for indent detection
  Set `width: auto` on WebProfiler toolbar's reset.
  [Lock] Fix incorrect phpdoc
  [Process] Dont rely on putenv(), it fails on ZTS PHP
  [HttpKernel] detect deprecations thrown by container initialization during tests
  [HttpKernel] Fix logging of post-terminate errors/exceptions
  [DI] Add context to service-not-found exceptions thrown by service locators
  [Debug] Fix catching fatal errors in case of nested error handlers
  [VarDumper] Fixed file links leave blank pages when ide is configured
  Fix hidden currency element with Bootstrap 3 theme
  ...
2017-12-12 09:41:51 +01:00
Nicolas Grekas
543deab3ff Merge branch '3.3' into 3.4
* 3.3:
  fix merge
  [Translation] Fix InvalidArgumentException when using untranslated plural forms from .po files
  Fixed exit code with non-integer throwable code
  Add suggestions
  Added instructions to upgrade Symfony applications to 4.x
2017-12-12 09:27:14 +01:00
Fabien Potencier
8895e0f1a9 Merge branch '3.3' into 3.4
* 3.3:
  [HttpFoundation] Support 0 bit netmask in IPv6 ()
  [DI] Impossible to set an environment variable and then an array as container parameter
  [LDAP] added missing dots at the end of some exception messages.
  Set `width: auto` on WebProfiler toolbar's reset.
  [Process] Dont rely on putenv(), it fails on ZTS PHP
  [HttpKernel] detect deprecations thrown by container initialization during tests
  [HttpKernel] Fix logging of post-terminate errors/exceptions
  [Debug] Fix catching fatal errors in case of nested error handlers
  [VarDumper] Fixed file links leave blank pages when ide is configured
  Fix hidden currency element with Bootstrap 3 theme
2017-12-11 14:06:16 -08:00
Nicolas Grekas
26a15dab86 Merge branch '3.4'
* 3.4:
  [Debug] Fix undefined variable $lightTrace
  [Bridge/PhpUnit] fix installation path
2017-11-21 10:27:49 +01:00
Nicolas Grekas
fb2001e5d8 [Debug] Fix undefined variable $lightTrace 2017-11-21 10:01:46 +01:00
Nicolas Grekas
a5069bdba7 Merge branch '3.4'
* 3.4:
  [Bridge/PhpUnit] Fix compat with phpunit 4.8 & bridge <=3.3.13
  Move deprecation under use statements
  Remove function_exists(__phpunit_run_isolated_test) checks
2017-11-19 22:10:49 +02:00
Nicolas Grekas
d120b899c0 Merge branch '3.3' into 3.4
* 3.3:
  [Bridge/PhpUnit] Fix compat with phpunit 4.8 & bridge <=3.3.13
  Remove function_exists(__phpunit_run_isolated_test) checks
2017-11-19 22:09:36 +02:00
Nicolas Grekas
92697a71cd Merge branch '3.4'
* 3.4:
  [TwigBridge] Fixed the .form-check-input class in the bs4 templates
  [Console] Fix traversable autocomplete values
  [SecurityBundle] Improve deprecations
  [DI] Friendlier name for generated container in "as_files" mode
  [Debug] Remove false-positive deprecation from DebugClassLoader
  [SecurityBundle] Add missing quotes in deprecation messages
  [ExpressionLanguage] Fix PhpDoc type-hints on Token value
  bumped Symfony version to 3.3.12
  Add default translations path option and convention
  updated VERSION for 3.3.11
  updated CHANGELOG for 3.3.11
  bumped Symfony version to 2.8.30
  updated VERSION for 2.8.29
  updated CHANGELOG for 2.8.29
  bumped Symfony version to 2.7.37
  updated VERSION for 2.7.36
  update CONTRIBUTORS for 2.7.36
  updated CHANGELOG for 2.7.36
2017-11-12 17:47:31 +01:00
Nicolas Grekas
24b7bbfc7c [Debug] Remove false-positive deprecation from DebugClassLoader 2017-11-11 16:39:06 +01:00
Nicolas Grekas
ca8a6e958e Merge branch '3.4'
* 3.4: (21 commits)
  fixed CS
  HttpCache lock update
  [Intl] Update ICU data to 60.1
  [YAML] Allow to parse custom tags when linting yaml files
  [HttpKernel][Debug] Remove noise from stack frames of deprecations
  [WebServerBundle] prevent console.terminate from being fired after stopping server
  [Validator] Fix Costa Rica IBAN format
  [Bridge/ProxyManager] Remove direct reference to value holder property
  [Validator] Add Belarus IBAN format
  [Config] Fix cannotBeEmpty()
  [Debug] More aggressively aggregate silenced notices per file+line
  [HttpFoundation] minor session-related fix
  [Cache][Lock] Add RedisProxy for lazy Redis connections
  [TwigBridge] [Bootstrap 4] Fix validation error design for expanded choiceType
  [FrameworkBundle] Specifically inject the debug dispatcher in the collector
  [WebserverBundle] fixed the bug that caused that the webserver would …
  update the pull request template
  [Stopwatch] minor fix
  Add default mapping path for validator component
  Add default mapping path for serializer component
  ...
2017-11-10 20:37:45 +01:00
Fabien Potencier
b25b18421a Merge branch '3.3' into 3.4
* 3.3:
  [Intl] Update ICU data to 60.1
  [YAML] Allow to parse custom tags when linting yaml files
  [HttpKernel][Debug] Remove noise from stack frames of deprecations
  [Validator] Fix Costa Rica IBAN format
  [Bridge/ProxyManager] Remove direct reference to value holder property
  [Validator] Add Belarus IBAN format
  [FrameworkBundle] Specifically inject the debug dispatcher in the collector
  [WebserverBundle] fixed the bug that caused that the webserver would …
  update the pull request template
  [Stopwatch] minor fix
2017-11-10 11:03:56 -08:00
Nicolas Grekas
def1666122 [Debug] More aggressively aggregate silenced notices per file+line 2017-11-10 10:14:26 +01:00
Nicolas Grekas
d61d1eb839 Replace more docblocks by type-hints 2017-11-07 15:45:01 +01:00
Nicolas Grekas
a5bb97fb9f Merge branch '3.4'
* 3.4:
  [DI] minor docblock fixes
2017-10-24 16:16:56 +02:00
Nicolas Grekas
9ebd154442 Merge branch '3.3' into 3.4
* 3.3:
  [DI] minor docblock fixes
2017-10-24 16:12:06 +02:00
Nicolas Grekas
c8e7639261 Merge branch '3.4'
* 3.4: (26 commits)
  [Routing] Fix resource miss
  [Security] Fixed auth provider authenticate() cannot return void
  [FrameworkBundle][Serializer] Move DateIntervalNormalizer definition to xml
  declare argument type
  Improving annotation loader message
  [FrameworkBundle][Serializer] Move normalizer/encoders definitions to xml file & remove unnecessary checks
  Update UPGRADE-4.0.md
  streamed response should return $this
  $isClientIpsVali is not used
  [WebServerBundle] Prevent commands from being registered by convention
  content can be a resource
  Adding the Form default theme files to be warmed up in Twig's cache
  Remove BC Break label from `NullDumper` class
  Username and password in basic auth are allowed to contain '.'
  Remove obsolete PHPDoc from UriSigner
  [Serializer] YamlEncoder: throw if the Yaml component isn't installed
  [Serializer] ObjectNormalizer: throw if PropertyAccess isn't installed
  [PropertyInfo] Add support for the iterable type
  pdo session fix
  Fixed pathinfo calculation for requests starting with a question mark.  - fix bad conflict resolving issue  - port symfony/symfony#21968 to 3.3+
  ...
2017-10-20 12:28:39 -07:00
Fabien Potencier
723643a94b Merge branch '3.3' into 3.4
* 3.3: (22 commits)
  [Routing] Fix resource miss
  [Security] Fixed auth provider authenticate() cannot return void
  declare argument type
  [FrameworkBundle][Serializer] Move normalizer/encoders definitions to xml file & remove unnecessary checks
  streamed response should return $this
  $isClientIpsVali is not used
  content can be a resource
  Adding the Form default theme files to be warmed up in Twig's cache
  Remove BC Break label from `NullDumper` class
  Username and password in basic auth are allowed to contain '.'
  Remove obsolete PHPDoc from UriSigner
  [Serializer] YamlEncoder: throw if the Yaml component isn't installed
  [Serializer] ObjectNormalizer: throw if PropertyAccess isn't installed
  [PropertyInfo] Add support for the iterable type
  pdo session fix
  Fixed pathinfo calculation for requests starting with a question mark.  - fix bad conflict resolving issue  - port symfony/symfony#21968 to 3.3+
  Fixed unsetting from loosely equal keys OrderedHashMap
  add DOMElement as return type in Crawler::getIterator to support foreach support in ide
  Fixed mistake in exception expectation
  [Debug] Fix same vendor detection in class loader
  ...
2017-10-20 11:48:32 -07:00
Nicolas Grekas
a76f02e3af Merge branch '3.4'
* 3.4:
  fix merge
  fix merge
  [FORM] Prevent forms from extending itself as a parent
  fix merge
  Fix 7.2 compat layer
  [DI] Prefixed env vars and load time inlining are incompatible
  bug #24499 [Bridge\PhpUnit] Fix infinite loop when running isolated method (bis) (nicolas-grekas)
  Fix PHP 7.2 support
  [HttpFoundation] Add missing session.lazy_write config option
  [DI] Exclude inline services declared in XML from autowiring candidates
  [HttpFoundation] Combine Cache-Control headers
  [Form] fix parsing invalid floating point numbers
  Escape command usage when displaying it in the text descriptor
  [DI] Throw accurate failures when accessing removed services
  [DI] Turn private defs to non-public ones before removing passes
  Use for=ID on radio/checkbox label.
2017-10-10 16:32:10 +02:00
Nicolas Grekas
147025beaf Merge branch '3.3' into 3.4
* 3.3:
  fix merge
  fix merge
  fix merge
  Fix 7.2 compat layer
  Fix PHP 7.2 support
  [HttpFoundation] Add missing session.lazy_write config option
  [HttpFoundation] Combine Cache-Control headers
  [Form] fix parsing invalid floating point numbers
  Escape command usage when displaying it in the text descriptor
  Use for=ID on radio/checkbox label.
2017-10-10 12:38:39 +02:00
Nicolas Grekas
61c2bb6dc9 Merge branch '3.4'
* 3.4: (33 commits)
  Remove remaining `@experimental` annotations
  Tests and fix for issue in array model data in EntityType field with multiple=true
  [Validator] Add unique entity violation cause
  [Lock] Automaticaly release lock when user forget it
  [Form] Fixed PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible
  fixed CS
  [FrameworkBundle] Don't clear app pools on cache:clear
  Hide label button when its setted to false
  removed useless PHPDoc
  [HttpFoundation] Return instance in StreamedResponse
  [Form] Fix FormInterface::submit() annotation
  [PHPUnitBridge] don't remove when set to  empty string
  PdoSessionHandler: fix advisory lock for pgsql when session.sid_bits_per_character > 4
  HttpCache does not consider ESI resources in HEAD requests
  Fix translation for "This field was not expected"
  [Routing] Enhance Route(Collection) docblocks
  Added improvement for accuracy in MoneyToLocalizedStringTransformer.
  Removed unused private property
  Use correct verb form in the pull request template
  Use PHP_MAXPATHLEN in Filesystem.
  ...
2017-10-02 08:59:24 +02:00
Nicolas Grekas
44c8fb3f90 Merge branch '3.3' into 3.4
* 3.3: (23 commits)
  Tests and fix for issue in array model data in EntityType field with multiple=true
  [Form] Fixed PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible
  removed useless PHPDoc
  [Form] Fix FormInterface::submit() annotation
  [PHPUnitBridge] don't remove when set to  empty string
  PdoSessionHandler: fix advisory lock for pgsql when session.sid_bits_per_character > 4
  HttpCache does not consider ESI resources in HEAD requests
  Fix translation for "This field was not expected"
  [Routing] Enhance Route(Collection) docblocks
  Added improvement for accuracy in MoneyToLocalizedStringTransformer.
  Removed unused private property
  Use correct verb form in the pull request template
  Use PHP_MAXPATHLEN in Filesystem.
  Added null as explicit return type (?TokenInterface)
  [FrameworkBundle] Fix Routing\DelegatingLoader
  Render all line breaks according to the exception message
  [Form] Fix phpdoc
  [DI] remove confusing code
  [Form] Fixed GroupSequence with "constraints" option
  [Validator] Clarify UUID validator behavior
  ...
2017-10-02 08:49:52 +02:00
Fabien Potencier
82a670d33f Merge branch '3.4'
* 3.4:
  Display form defaults on debug:form
  [Serializer][FrameworkBundle] Add a DateInterval normalizer
  fix merge
  CS: recover no_break_comment
  [DI] Fix non-instantiables auto-discovery
2017-09-15 10:31:55 -07:00
Nicolas Grekas
70e9d372ae Merge branch '3.4'
* 3.4:
  [CS][2.7] yoda_style, no_unneeded_curly_braces, no_unneeded_final_method, semicolon_after_instruction
  Reset stopwatch.
  [Filesystem] mirror - fix copying content with same name as source/target.
  Removed unnecessary getDefinition() call.
  .php_cs.dist - simplify config
  [WebProfilerBundle] fixed TemplateManager when using Twig 2 without compat interfaces
2017-09-15 12:16:43 +02:00
Nicolas Grekas
970ca21e12 Merge branch '3.3' into 3.4
* 3.3:
  [CS][2.7] yoda_style, no_unneeded_curly_braces, no_unneeded_final_method, semicolon_after_instruction
  [Filesystem] mirror - fix copying content with same name as source/target.
  Removed unnecessary getDefinition() call.
  .php_cs.dist - simplify config
  [WebProfilerBundle] fixed TemplateManager when using Twig 2 without compat interfaces
2017-09-15 12:12:22 +02:00
Nicolas Grekas
c5a160f3ba Merge branch '2.8' into 3.3
* 2.8:
  [CS][2.7] yoda_style, no_unneeded_curly_braces, no_unneeded_final_method, semicolon_after_instruction
  [Filesystem] mirror - fix copying content with same name as source/target.
  .php_cs.dist - simplify config
  [WebProfilerBundle] fixed TemplateManager when using Twig 2 without compat interfaces
2017-09-15 12:08:59 +02:00
Christian Flothmann
ce79328087 Merge branch '3.4'
* 3.4:
  [Debug] fix test assertion
2017-09-12 12:12:59 +02:00
Christian Flothmann
1407679206 [Debug] fix test assertion 2017-09-12 10:02:51 +02:00
Fabien Potencier
67c2aa7896 Merge branch '3.4'
* 3.4:
  fixed CS
  fixed CS
  fixed CS
2017-09-11 14:36:26 -07:00
Fabien Potencier
c0a3a6b4f2 fixed CS 2017-09-11 14:34:45 -07:00
Fabien Potencier
1eb7f04f24 Merge branch '3.4'
* 3.4:
  [CS] Apply phpdoc_annotation_without_dot
  bumped Symfony version to 3.3.10
  updated VERSION for 3.3.9
  updated CHANGELOG for 3.3.9
  [DomCrawler] Fix conversion to int on GetPhpFiles
  Remove `protected_to_private` rule.
  Filtering empty uuids in ORMQueryBuilderLoader.
2017-09-11 13:45:27 -07:00
Fabien Potencier
820b5ae4c3 Merge branch '3.3' into 3.4
* 3.3:
  [CS] Apply phpdoc_annotation_without_dot
  bumped Symfony version to 3.3.10
  updated VERSION for 3.3.9
  updated CHANGELOG for 3.3.9
  [DomCrawler] Fix conversion to int on GetPhpFiles
  Remove `protected_to_private` rule.
  Filtering empty uuids in ORMQueryBuilderLoader.
2017-09-11 13:45:17 -07:00
Nicolas Grekas
96bc445c20 Merge branch '3.4'
* 3.4:
  [HttpKernel] Deprecate EnvParametersResource
  [Lock] Check TTL expiration in lock acquisition
  Fix race condition in tests between cache and lock
  Improved how links are displayed in exception messages
2017-09-03 16:49:52 +02:00
Nicolas Grekas
33f6f36c28 Merge branch '3.3' into 3.4
* 3.3:
  Fix race condition in tests between cache and lock
  Improved how links are displayed in exception messages
2017-09-03 16:49:34 +02:00
Robin Chalas
09d2d7c077 Merge branch '3.4'
* 3.4: (38 commits)
  Fix merge
  [Lock] Expose an expiringDate and isExpired method in Lock
  [VarDumper] fix DateCasterTest
  [config] Add ability to deprecate a node
  feature #22382 [config] Add abbitily to deprecate a node (Nyholm, fabpot, sanpii)
  Fix segfault in period caster
  Create an interface for TranslationReader and moved TranslationLoader to Translation component
  Always require symfony/polyfill-apcu to provide APCuIterator everywhere
  [Lock] Fix some tests that require pcntl_sigwaitinfo() function
  bumped Symfony version to 3.3.9
  updated VERSION for 3.3.8
  updated CHANGELOG for 3.3.8
  [DI] Fix tracking env var placeholders nested in object graphs
  bumped Symfony version to 3.3.8
  updated VERSION for 3.3.7
  updated CHANGELOG for 3.3.7
  Add period caster
  [DI] improve psr4-based service discovery with namespace option
  [DI] Fix tracking env vars when merging configs (bis)
  removed obsolete comment
  ...
2017-08-30 01:06:25 +02:00
Fabien Potencier
f43bc2e05d Merge branch '3.3' into 3.4
* 3.3: (27 commits)
  Always require symfony/polyfill-apcu to provide APCuIterator everywhere
  bumped Symfony version to 3.3.9
  updated VERSION for 3.3.8
  updated CHANGELOG for 3.3.8
  [DI] Fix tracking env var placeholders nested in object graphs
  bumped Symfony version to 3.3.8
  updated VERSION for 3.3.7
  updated CHANGELOG for 3.3.7
  [DI] Fix tracking env vars when merging configs (bis)
  removed obsolete comment
  install PHPUnit 6 on PHP 7.2
  [Cache] Use zend.detect_unicode instead of zend.multibyte
  Fix case sensitive typo in use class name
  [VarDumper] Enhance docblock to tell about AbstractDumper::dumpLine(-1)
  [Debug] Remove false-positive check in DebugClassLoader
  [Validator] Fix use of GroupSequenceProvider in child classes
  Change number PHPDoc type to int|float
  [Cache] Workaround zend.detect_unicode + zend.multibyte
  [VarDumper] Strengthen dumped JS
  [VarDumper] Strengthen dumped JS
  ...
2017-08-29 14:00:42 -07:00
Nicolas Grekas
07bc974dbe Merge branch '3.4'
* 3.4: (23 commits)
  [DI] Allow dumping inline services in Yaml
  fixed CS
  [2.8] Modify 2.8 upgrade doc - key option is deprecated.
  Fix lock failling test
  [Debug] Correctly detect methods not from the same vendor
  [HttpKernel] Deprecated commands auto-registration
  Fix minors in date caster
  [FrameworkBundle] Catch Fatal errors in commands registration
  [Debug] Detect internal and deprecated methods
  [Profiler] Make the validator toolbar item consistent with the form one
  [DebugBundle] Reword an outdated comment about var dumper wiring
  updated CHANGELOG
  [HttpFoundation] Remove length limit on ETag
  [DI] Fix some docblocks
  [DI] Fix some docblocks
  Fixed the exception page design in responsive mode
  [Console] Log exit codes as debug messages instead of errors
  Fixed UPGRADE-4.0 about Container::set
  Ignore memcached missing key error on dession destroy
  [FrameworkBundle] Allow micro kernel to subscribe events easily
  ...
2017-08-10 16:21:53 +02:00
Fabien Potencier
50bda5b4b8 Merge branch '3.3' into 3.4
* 3.3:
  fixed CS
  [2.8] Modify 2.8 upgrade doc - key option is deprecated.
  [DebugBundle] Reword an outdated comment about var dumper wiring
  [DI] Fix some docblocks
  [DI] Fix some docblocks
  Fixed the exception page design in responsive mode
  [Console] Log exit codes as debug messages instead of errors
  Fixed UPGRADE-4.0 about Container::set
  Ignore memcached missing key error on dession destroy
  bumped Symfony version to 3.2.14
  updated VERSION for 3.2.13
  updated CHANGELOG for 3.2.13
2017-08-10 09:07:17 +02:00
Guilhem Niot
f28018d622 [Debug] Correctly detect methods not from the same vendor 2017-08-09 18:59:29 +02:00
Guilhem Niot
b7190d5620 [Debug] Detect internal and deprecated methods 2017-08-09 18:15:33 +02:00
Nicolas Grekas
620550389a Merge branch '3.4'
* 3.4:
  [Debug] Trigger a deprecation when using an internal class/trait/interface
  [DI] Generate one file per service factory
2017-08-07 20:06:09 +02:00
Guilhem Niot
3be4178b91 [Debug] Trigger a deprecation when using an internal class/trait/interface 2017-08-07 14:30:49 +02:00
Nicolas Grekas
c9fcef80c3 Merge branch '3.3' into 3.4
* 3.3:
  Removed useless argument $definition
  Fix comment
  [Config] Fix checking class existence freshness
  bumped Symfony version to 3.3.7
  updated VERSION for 3.3.6
  updated CHANGELOG for 3.3.6
  Bump minimal PHP version to ^5.5.9|>=7.0.8
2017-08-03 11:34:20 +02:00
Nicolas Grekas
56cb55542f Merge branch '3.4'
* 3.4:
  [DI] Remove unused props from the PhpDumper
  [VarDumper] Keep and reuse array stubs in memory
  [DI][ProxyManager] Pass the factory code to execute to DumperInterface::getProxyFactoryCode()
  [Workflow] Adding workflow name to the announce event
  [ProxyManager] Cleanup fixtures
  [Console][WebServerBundle] Use "exec" when possible
  [Debug] HTML-escape array key
  Add some phpdocs for IDE autocompletion and better SCA
  Fixed typo in docblock
2017-07-28 17:35:42 +02:00
Nicolas Grekas
97592888b9 Merge branch '3.3' into 3.4
* 3.3:
  [DI] Remove unused props from the PhpDumper
  [VarDumper] Keep and reuse array stubs in memory
  [ProxyManager] Cleanup fixtures
  [Console][WebServerBundle] Use "exec" when possible
  [Debug] HTML-escape array key
  Add some phpdocs for IDE autocompletion and better SCA
  Fixed typo in docblock
2017-07-28 17:30:20 +02:00
Nicolas Grekas
15b0a06a42 Merge branch '3.4'
* 3.4:
  Minor cleanups
2017-07-06 16:37:40 +03:00
Nicolas Grekas
296d63b9b2 Minor cleanups 2017-07-06 16:36:30 +03:00
Nicolas Grekas
b76a3de8c5 feature #22804 [Debug] Removed ContextErrorException (mbabker)
This PR was merged into the 4.0-dev branch.

Discussion
----------

[Debug] Removed ContextErrorException

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

Commits
-------

76dc317 Removed ContextErrorException
2017-07-06 16:32:31 +03:00
Michael Babker
856a3e180b Removed ContextErrorException 2017-07-06 07:23:02 -05:00
Nicolas Grekas
78aeb1c848 Merge branch '3.4'
* 3.4:
  Deprecate support for stacked errors
  fixed tests
  [HttpFoundation] Find the original request protocol version
  fixed CS
  Add support for microseconds in Stopwatch
  Preserve HttpOnly value when deserializing a header
  add minimum and maximum amount of pixels to Image validator
  fixed CHANGELOG
  [DX] [TwigBundle] Enhance the new exception page design
  [BrowserKit] Emulate back/forward browser navigation
  Fix deprecated message
  [Component][Serializer][Normalizer] : Deal it with Has Method for the Normalizer/Denormalizer
  [Validator] improve the changelog
  [FrameworkBundle] Wire inner translator
  [FrameworkBundle][HttpKernel] Move addcachearmer, addcacheclearer compiler pass
  [FrameworkBundle][Translation] Move translation compiler pass
2017-07-06 13:49:06 +03:00
Nicolas Grekas
ee6732177c Merge branch '3.3' into 3.4
* 3.3: (33 commits)
  Preserve HttpOnly value when deserializing a header
  [DX] [TwigBundle] Enhance the new exception page design
  Fix deprecated message
  [DI][Security] Prevent unwanted deprecation notices when using Expression Languages
  bumped Symfony version to 3.3.5
  updated VERSION for 3.3.4
  updated CHANGELOG for 3.3.4
  [VarDumper] Reduce size of serialized Data objects
  bumped Symfony version to 3.2.12
  updated VERSION for 3.2.11
  updated CHANGELOG for 3.2.11
  fixed bad merge
  Fix indent of methods
  [Cache] Handle APCu failures gracefully
  [DoctrineBridge] Use normalizedIds for resetting entity manager services
  [FrameworkBundle] Do not remove files from assets dir
  [FrameworkBundle] 3.3: Don't get() private services from debug:router
  bumped Symfony version to 3.3.4
  updated VERSION for 3.3.3
  updated CHANGELOG for 3.3.3
  ...
2017-07-06 13:23:40 +03:00
Michael Babker
18ac7ae10d Deprecate support for stacked errors 2017-07-06 13:08:05 +03:00
Fabien Potencier
d11ca28ddc Merge branch '3.3'
* 3.3:
  [DI][Security] Prevent unwanted deprecation notices when using Expression Languages
  bumped Symfony version to 3.3.5
  updated VERSION for 3.3.4
  updated CHANGELOG for 3.3.4
  [VarDumper] Reduce size of serialized Data objects
  bumped Symfony version to 3.2.12
  updated VERSION for 3.2.11
  updated CHANGELOG for 3.2.11
  [DoctrineBridge] Use normalizedIds for resetting entity manager services
2017-07-06 09:25:25 +03:00
Nek (Maxime Veber)
78a5af2f68 Remove HHVM support (second edition) 2017-07-03 10:26:05 +03:00
Nicolas Grekas
2b1c9fd1e3 Merge branch '3.4'
* 3.4:
  [MonologBridge] Do not silence errors in ServerLogHandler::formatRecord
  bumped Symfony version to 3.3.3
  updated VERSION for 3.3.2
  updated CHANGELOG for 3.3.2
  [HttpKernel][Debug] Fix missing trace on deprecations collected during bootstrapping & silenced errors
  [PropertyInfo] Made ReflectionExtractor's prefix lists instance variables
2017-06-07 16:10:47 +02:00
Nicolas Grekas
9d40ad561e Merge branch '3.3' into 3.4
* 3.3:
  [MonologBridge] Do not silence errors in ServerLogHandler::formatRecord
  bumped Symfony version to 3.3.3
  updated VERSION for 3.3.2
  updated CHANGELOG for 3.3.2
  [HttpKernel][Debug] Fix missing trace on deprecations collected during bootstrapping & silenced errors
2017-06-07 16:09:28 +02:00
Fabien Potencier
68792b216c removed HHVM support 2017-06-01 15:17:54 -07:00
Fabien Potencier
854252d112 Merge branch '3.4'
* 3.4: (31 commits)
  Using FQ name for PHP_VERSION_ID
  [EventDispatcher] Handle laziness internally instead of relying on ClosureProxyArgument
  Fix CacheCollectorPass priority
  [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323
  [Routing] Allow GET requests to be redirected. Fixes #23004
  [DI] Deal with inlined non-shared services
  [Cache] Ignore missing annotations.php
  [DI] Autowiring exception thrown when inlined service is removed
  Improving deprecation message when hitting the "deprecated type" lookup, but an alias is available
  Harden the debugging of Twig filters and functions
  Fixing a bug where an autowiring exception was thrown even when that service was removed
  Remove extra arg in call to TraceableAdapter::start()
  Support unknown compiler log format
  [Config] Allow empty globs
  Fix decorating TagAware adapters in dev
  [Profiler] Fix clicking on links inside toggle
  [Profiler] Fix text selection on exception pages
  bumped Symfony version to 3.3.1
  updated VERSION for 3.3.0
  updated CHANGELOG for 3.3.0
  ...
2017-06-01 14:04:19 -07:00
Fabien Potencier
6694bfe6ac Merge branch '3.3' into 3.4
* 3.3: (31 commits)
  Using FQ name for PHP_VERSION_ID
  [EventDispatcher] Handle laziness internally instead of relying on ClosureProxyArgument
  Fix CacheCollectorPass priority
  [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323
  [Routing] Allow GET requests to be redirected. Fixes #23004
  [DI] Deal with inlined non-shared services
  [Cache] Ignore missing annotations.php
  [DI] Autowiring exception thrown when inlined service is removed
  Improving deprecation message when hitting the "deprecated type" lookup, but an alias is available
  Harden the debugging of Twig filters and functions
  Fixing a bug where an autowiring exception was thrown even when that service was removed
  Remove extra arg in call to TraceableAdapter::start()
  Support unknown compiler log format
  [Config] Allow empty globs
  Fix decorating TagAware adapters in dev
  [Profiler] Fix clicking on links inside toggle
  [Profiler] Fix text selection on exception pages
  bumped Symfony version to 3.3.1
  updated VERSION for 3.3.0
  updated CHANGELOG for 3.3.0
  ...
2017-06-01 14:02:15 -07:00
Nicolas Grekas
e2471c3c27 Merge branch '3.4'
* 3.4:
  typo
  Fixed options stub values display in form profiler
  [Console] Fix tests
  Make the simple exception pages match the new style
  [Console] Fixed different behaviour of key and value user inputs in multiple choice question
  Adjust PHPUnit class_alias check to also check for namespaced class
  [Cache] Dont use pipelining with RedisCluster
  [Yaml] fix colon without space deprecation
  [Intl] Fix intl tests for PHP < 5.5.10
2017-05-28 13:01:50 +02:00
Nicolas Grekas
0f82f184dd Merge branch '3.3' into 3.4
* 3.3:
  typo
  Fixed options stub values display in form profiler
  [Console] Fix tests
  Make the simple exception pages match the new style
  [Console] Fixed different behaviour of key and value user inputs in multiple choice question
  Adjust PHPUnit class_alias check to also check for namespaced class
  [Cache] Dont use pipelining with RedisCluster
  [Yaml] fix colon without space deprecation
  [Intl] Fix intl tests for PHP < 5.5.10
2017-05-28 12:56:43 +02:00
Nicolas Grekas
20bb3a9837 [3.4] Allow 4.* deps 2017-05-24 11:02:43 +02:00
Robin Chalas
00425e7ce6 CS Fixes 2017-05-22 11:03:40 +02:00
Maxime Steinhausser
2c92bb4d75 Remove PHP < 7.1.3 code 2017-05-22 08:50:05 +02:00
Christian Flothmann
c5b6e2628d [ClassLoader] remove the component
(cherry picked from commit c365ae2)
2017-05-21 12:04:58 +02:00
Nicolas Grekas
70a4a261d5 [Debug][VarDumper] Remove the symfony_debug C extension 2017-05-19 19:05:40 +02:00
Nicolas Grekas
7faa20c95d Tweak travis and appveyor for Symfony 4 2017-05-18 15:50:33 +02:00
Fabien Potencier
2803d2ea75 bumped minimum version to PHP 7.1 2017-05-18 14:57:29 +02:00
Nicolas Grekas
369b129a04 Merge branch '3.4'
* 3.4:
  Allow individual bridges, bundles and components to be used with 4.0
2017-05-18 14:56:38 +02:00
Kévin Dunglas
91dc1c8129 Allow individual bridges, bundles and components to be used with 4.0 2017-05-18 14:56:12 +02:00
Fabien Potencier
c7a4bc2a59 updated version to 4.0 2017-05-17 18:33:00 +02:00
Fabien Potencier
627c397b80 updated version to 3.4 2017-05-17 18:21:40 +02:00
31 changed files with 276 additions and 1325 deletions

View File

@@ -1,6 +1,17 @@
CHANGELOG
=========
4.0.0
-----
* removed the symfony_debug extension
* removed `ContextErrorException`
3.4.0
-----
* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()`
3.3.0
-----

View File

@@ -25,9 +25,6 @@ class Debug
*
* This method registers an error handler and an exception handler.
*
* If the Symfony ClassLoader component is available, a special
* class loader is also registered.
*
* @param int $errorReportingLevel The level of error reporting you want
* @param bool $displayErrors Whether to display errors (for development) or just log them (for production)
*/

View File

@@ -31,7 +31,8 @@ class DebugClassLoader
private static $final = array();
private static $finalMethods = array();
private static $deprecated = array();
private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
private static $internal = array();
private static $internalMethods = array();
private static $darwinCache = array('/' => array('/', array()));
public function __construct(callable $classLoader)
@@ -132,7 +133,7 @@ class DebugClassLoader
*/
public function loadClass($class)
{
ErrorHandler::stackErrors();
$e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
try {
if ($this->isFinder && !isset($this->loaded[$class])) {
@@ -145,7 +146,7 @@ class DebugClassLoader
$file = false;
}
} finally {
ErrorHandler::unstackErrors();
error_reporting($e);
}
$exists = class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
@@ -162,81 +163,90 @@ class DebugClassLoader
throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name));
}
$parent = get_parent_class($class);
// Don't trigger deprecations for classes in the same vendor
if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
$len = 0;
$ns = '';
} else {
$ns = substr($name, 0, $len);
}
// Not an interface nor a trait
if (class_exists($name, false)) {
if (preg_match('#\n \* @final(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
self::$final[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
}
if ($parent && isset(self::$final[$parent])) {
@trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED);
}
// Inherit @final annotations
self::$finalMethods[$name] = $parent && isset(self::$finalMethods[$parent]) ? self::$finalMethods[$parent] : array();
foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
if ($method->class !== $name) {
continue;
}
if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
@trigger_error(sprintf('%s It may change without further notice as of its next major version. You should not extend it from "%s".', self::$finalMethods[$parent][$method->name], $name), E_USER_DEPRECATED);
}
$doc = $method->getDocComment();
if (false === $doc || false === strpos($doc, '@final')) {
continue;
}
if (preg_match('#\n\s+\* @final(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
$message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
self::$finalMethods[$name][$method->name] = sprintf('The "%s::%s()" method is considered final%s.', $name, $method->name, $message);
// Detect annotations on the class
if (false !== $doc = $refl->getDocComment()) {
foreach (array('final', 'deprecated', 'internal') as $annotation) {
if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) {
self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
}
}
}
if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
@trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
} elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
} else {
// Don't trigger deprecations for classes in the same vendor
if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) {
$len = 0;
$ns = '';
} else {
$ns = substr($name, 0, $len);
$parentAndTraits = class_uses($name, false);
if ($parent = get_parent_class($class)) {
$parentAndTraits[] = $parent;
if (isset(self::$final[$parent])) {
@trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED);
}
}
// Detect if the parent is annotated
foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) {
if (isset(self::$deprecated[$use]) && strncmp($ns, $use, $len)) {
$type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait');
$verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses');
@trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED);
}
if (isset(self::$internal[$use]) && strncmp($ns, $use, $len)) {
@trigger_error(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], $name), E_USER_DEPRECATED);
}
}
// Inherit @final and @internal annotations for methods
self::$finalMethods[$name] = array();
self::$internalMethods[$name] = array();
foreach ($parentAndTraits as $use) {
foreach (array('finalMethods', 'internalMethods') as $property) {
if (isset(self::${$property}[$use])) {
self::${$property}[$name] = array_merge(self::${$property}[$name], self::${$property}[$use]);
}
}
}
$isClass = class_exists($name, false);
foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) {
if ($method->class !== $name) {
continue;
}
if (!$parent || strncmp($ns, $parent, $len)) {
if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
@trigger_error(sprintf('The "%s" class extends "%s" that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
}
// Method from a trait
if ($method->getFilename() !== $refl->getFileName()) {
continue;
}
$parentInterfaces = array();
$deprecatedInterfaces = array();
if ($parent) {
foreach (class_implements($parent) as $interface) {
$parentInterfaces[$interface] = 1;
if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) {
list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
@trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED);
}
foreach ($parentAndTraits as $use) {
if (isset(self::$internalMethods[$use][$method->name])) {
list($declaringClass, $message) = self::$internalMethods[$use][$method->name];
if (strncmp($ns, $declaringClass, $len)) {
@trigger_error(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, $name), E_USER_DEPRECATED);
}
}
}
foreach ($refl->getInterfaceNames() as $interface) {
if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
$deprecatedInterfaces[] = $interface;
}
foreach (class_implements($interface) as $interface) {
$parentInterfaces[$interface] = 1;
}
}
// Detect method annotations
if (false === $doc = $method->getDocComment()) {
continue;
}
foreach ($deprecatedInterfaces as $interface) {
if (!isset($parentInterfaces[$interface])) {
@trigger_error(sprintf('The "%s" %s "%s" that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
}
foreach (array('final', 'internal') as $annotation) {
if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) {
$message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : '';
self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message);
}
}
}
@@ -339,4 +349,31 @@ class DebugClassLoader
return true;
}
}
/**
* `class_implements` includes interfaces from the parents so we have to manually exclude them.
*
* @param string $class
* @param string|false $parent
*
* @return string[]
*/
private function getOwnInterfaces($class, $parent)
{
$ownInterfaces = class_implements($class, false);
if ($parent) {
foreach (class_implements($parent, false) as $interface) {
unset($ownInterfaces[$interface]);
}
}
foreach ($ownInterfaces as $interface) {
foreach (class_implements($interface) as $interface) {
unset($ownInterfaces[$interface]);
}
}
return $ownInterfaces;
}
}

View File

@@ -13,7 +13,6 @@ namespace Symfony\Component\Debug;
use Psr\Log\LogLevel;
use Psr\Log\LoggerInterface;
use Symfony\Component\Debug\Exception\ContextErrorException;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Symfony\Component\Debug\Exception\OutOfMemoryException;
@@ -97,8 +96,6 @@ class ErrorHandler
private $bootstrappingLogger;
private static $reservedMemory;
private static $stackedErrors = array();
private static $stackedErrorLevels = array();
private static $toStringException = null;
private static $silencedErrorCache = array();
private static $silencedErrorCount = 0;
@@ -382,10 +379,8 @@ class ErrorHandler
if (4 < $numArgs = func_num_args()) {
$context = $scope ? (func_get_arg(4) ?: array()) : array();
$backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM
} else {
$context = array();
$backtrace = null;
}
if (isset($context['GLOBALS']) && $scope) {
@@ -394,53 +389,45 @@ class ErrorHandler
$context = $e;
}
if (null !== $backtrace && $type & E_ERROR) {
// E_ERROR fatal errors are triggered on HHVM when
// hhvm.error_handling.call_user_handler_on_fatals=1
// which is the way to get their backtrace.
$this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
return true;
}
$logMessage = $this->levels[$type].': '.$message;
if (null !== self::$toStringException) {
$errorAsException = self::$toStringException;
self::$toStringException = null;
} elseif (!$throw && !($type & $level)) {
if (isset(self::$silencedErrorCache[$message])) {
$lightTrace = null;
$errorAsException = self::$silencedErrorCache[$message];
++$errorAsException->count;
} else {
if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
$lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array();
$errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
} elseif (isset(self::$silencedErrorCache[$id][$message])) {
$lightTrace = null;
$errorAsException = self::$silencedErrorCache[$id][$message];
++$errorAsException->count;
} else {
$lightTrace = array();
$errorAsException = null;
}
if (100 < ++self::$silencedErrorCount) {
self::$silencedErrorCache = $lightTrace = array();
self::$silencedErrorCount = 1;
}
self::$silencedErrorCache[$message] = $errorAsException;
if ($errorAsException) {
self::$silencedErrorCache[$id][$message] = $errorAsException;
}
if (null === $lightTrace) {
return;
}
} else {
if ($scope) {
$errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context);
} else {
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
}
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
// Clean the trace by removing function arguments and the first frames added by the error handler itself.
if ($throw || $this->tracedErrors & $type) {
$backtrace = $backtrace ?: $errorAsException->getTrace();
$backtrace = $errorAsException->getTrace();
$lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
$this->traceReflector->setValue($errorAsException, $lightTrace);
} else {
$this->traceReflector->setValue($errorAsException, array());
$backtrace = array();
}
}
@@ -454,32 +441,25 @@ class ErrorHandler
&& ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
) {
// Here, we know trigger_error() has been called from __toString().
// HHVM is fine with throwing from __toString() but PHP triggers a fatal error instead.
// PHP triggers a fatal error when throwing from __toString().
// A small convention allows working around the limitation:
// given a caught $e exception in __toString(), quitting the method with
// `return trigger_error($e, E_USER_ERROR);` allows this error handler
// to make $e get through the __toString() barrier.
foreach ($context as $e) {
if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
if (1 === $i) {
// On HHVM
$errorAsException = $e;
break;
}
if ($e instanceof \Throwable && $e->__toString() === $message) {
self::$toStringException = $e;
return true;
}
}
if (1 < $i) {
// On PHP (not on HHVM), display the original error message instead of the default one.
$this->handleException($errorAsException);
// Display the original error message instead of the default one.
$this->handleException($errorAsException);
// Stop the process by giving back the error to the native handler.
return false;
}
// Stop the process by giving back the error to the native handler.
return false;
}
}
}
@@ -489,18 +469,11 @@ class ErrorHandler
if ($this->isRecursive) {
$log = 0;
} elseif (self::$stackedErrorLevels) {
self::$stackedErrors[] = array(
$this->loggers[$type][0],
($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG,
$logMessage,
array('exception' => $errorAsException),
);
} else {
try {
$this->isRecursive = true;
$level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG;
$this->loggers[$type][0]->log($level, $logMessage, array('exception' => $errorAsException));
$this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array());
} finally {
$this->isRecursive = false;
}
@@ -549,7 +522,6 @@ class ErrorHandler
if ($this->loggedErrors & $type) {
try {
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception));
} catch (\Exception $handlerException) {
} catch (\Throwable $handlerException) {
}
}
@@ -566,7 +538,6 @@ class ErrorHandler
return \call_user_func($this->exceptionHandler, $exception);
}
$handlerException = $handlerException ?: $exception;
} catch (\Exception $handlerException) {
} catch (\Throwable $handlerException) {
}
$this->exceptionHandler = null;
@@ -619,16 +590,6 @@ class ErrorHandler
$error = error_get_last();
}
try {
while (self::$stackedErrorLevels) {
static::unstackErrors();
}
} catch (\Exception $exception) {
// Handled below
} catch (\Throwable $exception) {
// Handled below
}
if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
// Let's not throw anymore but keep logging
$handler->throwAt(0, true);
@@ -639,10 +600,12 @@ class ErrorHandler
} else {
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
}
} else {
$exception = null;
}
try {
if (isset($exception)) {
if (null !== $exception) {
self::$exitCode = 255;
$handler->handleException($exception, $error);
}
@@ -656,47 +619,6 @@ class ErrorHandler
}
}
/**
* Configures the error handler for delayed handling.
* Ensures also that non-catchable fatal errors are never silenced.
*
* As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724
* PHP has a compile stage where it behaves unusually. To workaround it,
* we plug an error handler that only stacks errors for later.
*
* The most important feature of this is to prevent
* autoloading until unstackErrors() is called.
*/
public static function stackErrors()
{
self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
}
/**
* Unstacks stacked errors and forwards to the logger.
*/
public static function unstackErrors()
{
$level = array_pop(self::$stackedErrorLevels);
if (null !== $level) {
$errorReportingLevel = error_reporting($level);
if ($errorReportingLevel !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
// If the user changed the error level, do not overwrite it
error_reporting($errorReportingLevel);
}
}
if (empty(self::$stackedErrorLevels)) {
$errors = self::$stackedErrors;
self::$stackedErrors = array();
foreach ($errors as $error) {
$error[0]->log($error[1], $error[2], $error[3]);
}
}
}
/**
* Gets the fatal error handlers.
*

View File

@@ -18,7 +18,7 @@ namespace Symfony\Component\Debug\Exception;
*/
class ClassNotFoundException extends FatalErrorException
{
public function __construct($message, \ErrorException $previous)
public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,

View File

@@ -1,40 +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\Exception;
/**
* Error Exception with Variable Context.
*
* @author Christian Sciberras <uuf6429@gmail.com>
*
* @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0.
*/
class ContextErrorException extends \ErrorException
{
private $context = array();
public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
{
parent::__construct($message, $code, $severity, $filename, $lineno);
$this->context = $context;
}
/**
* @return array Array of variables that existed when the exception occurred
*/
public function getContext()
{
@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED);
return $this->context;
}
}

View File

@@ -18,7 +18,7 @@ namespace Symfony\Component\Debug\Exception;
*/
class FatalErrorException extends \ErrorException
{
public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null)
{
parent::__construct($message, $code, $severity, $filename, $lineno);
@@ -60,11 +60,6 @@ class FatalErrorException extends \ErrorException
unset($frame);
$trace = array_reverse($trace);
} elseif (function_exists('symfony_debug_backtrace')) {
$trace = symfony_debug_backtrace();
if (0 < $traceOffset) {
array_splice($trace, 0, $traceOffset);
}
} else {
$trace = array();
}

View File

@@ -25,7 +25,7 @@ class SilencedErrorContext implements \JsonSerializable
private $line;
private $trace;
public function __construct($severity, $file, $line, array $trace = array(), $count = 1)
public function __construct(int $severity, string $file, int $line, array $trace = array(), int $count = 1)
{
$this->severity = $severity;
$this->file = $file;

View File

@@ -18,7 +18,7 @@ namespace Symfony\Component\Debug\Exception;
*/
class UndefinedFunctionException extends FatalErrorException
{
public function __construct($message, \ErrorException $previous)
public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,

View File

@@ -18,7 +18,7 @@ namespace Symfony\Component\Debug\Exception;
*/
class UndefinedMethodException extends FatalErrorException
{
public function __construct($message, \ErrorException $previous)
public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,

View File

@@ -36,7 +36,7 @@ class ExceptionHandler
private $caughtLength;
private $fileLinkFormat;
public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
public function __construct(bool $debug = true, string $charset = null, $fileLinkFormat = null)
{
$this->debug = $debug;
$this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';

View File

@@ -83,7 +83,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
*
* @return array An array of possible fully qualified class names
*/
private function getClassCandidates($class)
private function getClassCandidates(string $class): array
{
if (!is_array($functions = spl_autoload_functions())) {
return array();
@@ -124,14 +124,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
return array_unique($classes);
}
/**
* @param string $path
* @param string $class
* @param string $prefix
*
* @return array
*/
private function findClassInPath($path, $class, $prefix)
private function findClassInPath(string $path, string $class, string $prefix): array
{
if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
return array();
@@ -148,14 +141,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
return $classes;
}
/**
* @param string $path
* @param string $file
* @param string $prefix
*
* @return string|null
*/
private function convertFileToClass($path, $file, $prefix)
private function convertFileToClass(string $path, string $file, string $prefix): ?string
{
$candidates = array(
// namespaced class
@@ -192,14 +178,11 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
return $candidate;
}
}
return null;
}
/**
* @param string $class
*
* @return bool
*/
private function classExists($class)
private function classExists(string $class): bool
{
return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
}

View File

@@ -1,134 +0,0 @@
Symfony Debug Extension for PHP 5
=================================
This extension publishes several functions to help building powerful debugging tools.
It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes.
It is not required thus not provided for PHP 7.
symfony_zval_info()
-------------------
- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP,
- does work with references, preventing memory copying.
Its behavior is about the same as:
```php
<?php
function symfony_zval_info($key, $array, $options = 0)
{
// $options is currently not used, but could be in future version.
if (!array_key_exists($key, $array)) {
return null;
}
$info = array(
'type' => gettype($array[$key]),
'zval_hash' => /* hashed memory address of $array[$key] */,
'zval_refcount' => /* internal zval refcount of $array[$key] */,
'zval_isref' => /* is_ref status of $array[$key] */,
);
switch ($info['type']) {
case 'object':
$info += array(
'object_class' => get_class($array[$key]),
'object_refcount' => /* internal object refcount of $array[$key] */,
'object_hash' => spl_object_hash($array[$key]),
'object_handle' => /* internal object handle $array[$key] */,
);
break;
case 'resource':
$info += array(
'resource_handle' => (int) $array[$key],
'resource_type' => get_resource_type($array[$key]),
'resource_refcount' => /* internal resource refcount of $array[$key] */,
);
break;
case 'array':
$info += array(
'array_count' => count($array[$key]),
);
break;
case 'string':
$info += array(
'strlen' => strlen($array[$key]),
);
break;
}
return $info;
}
```
symfony_debug_backtrace()
-------------------------
This function works like debug_backtrace(), except that it can fetch the full backtrace in case of fatal errors:
```php
function foo() { fatal(); }
function bar() { foo(); }
function sd() { var_dump(symfony_debug_backtrace()); }
register_shutdown_function('sd');
bar();
/* Will output
Fatal error: Call to undefined function fatal() in foo.php on line 42
array(3) {
[0]=>
array(2) {
["function"]=>
string(2) "sd"
["args"]=>
array(0) {
}
}
[1]=>
array(4) {
["file"]=>
string(7) "foo.php"
["line"]=>
int(1)
["function"]=>
string(3) "foo"
["args"]=>
array(0) {
}
}
[2]=>
array(4) {
["file"]=>
string(102) "foo.php"
["line"]=>
int(2)
["function"]=>
string(3) "bar"
["args"]=>
array(0) {
}
}
}
*/
```
Usage
-----
To enable the extension from source, run:
```
phpize
./configure
make
sudo make install
```

View File

@@ -1,63 +0,0 @@
dnl $Id$
dnl config.m4 for extension symfony_debug
dnl Comments in this file start with the string 'dnl'.
dnl Remove where necessary. This file will not work
dnl without editing.
dnl If your extension references something external, use with:
dnl PHP_ARG_WITH(symfony_debug, for symfony_debug support,
dnl Make sure that the comment is aligned:
dnl [ --with-symfony_debug Include symfony_debug support])
dnl Otherwise use enable:
PHP_ARG_ENABLE(symfony_debug, whether to enable symfony_debug support,
dnl Make sure that the comment is aligned:
[ --enable-symfony_debug Enable symfony_debug support])
if test "$PHP_SYMFONY_DEBUG" != "no"; then
dnl Write more examples of tests here...
dnl # --with-symfony_debug -> check with-path
dnl SEARCH_PATH="/usr/local /usr" # you might want to change this
dnl SEARCH_FOR="/include/symfony_debug.h" # you most likely want to change this
dnl if test -r $PHP_SYMFONY_DEBUG/$SEARCH_FOR; then # path given as parameter
dnl SYMFONY_DEBUG_DIR=$PHP_SYMFONY_DEBUG
dnl else # search default path list
dnl AC_MSG_CHECKING([for symfony_debug files in default path])
dnl for i in $SEARCH_PATH ; do
dnl if test -r $i/$SEARCH_FOR; then
dnl SYMFONY_DEBUG_DIR=$i
dnl AC_MSG_RESULT(found in $i)
dnl fi
dnl done
dnl fi
dnl
dnl if test -z "$SYMFONY_DEBUG_DIR"; then
dnl AC_MSG_RESULT([not found])
dnl AC_MSG_ERROR([Please reinstall the symfony_debug distribution])
dnl fi
dnl # --with-symfony_debug -> add include path
dnl PHP_ADD_INCLUDE($SYMFONY_DEBUG_DIR/include)
dnl # --with-symfony_debug -> check for lib and symbol presence
dnl LIBNAME=symfony_debug # you may want to change this
dnl LIBSYMBOL=symfony_debug # you most likely want to change this
dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
dnl [
dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DEBUG_DIR/lib, SYMFONY_DEBUG_SHARED_LIBADD)
dnl AC_DEFINE(HAVE_SYMFONY_DEBUGLIB,1,[ ])
dnl ],[
dnl AC_MSG_ERROR([wrong symfony_debug lib version or lib not found])
dnl ],[
dnl -L$SYMFONY_DEBUG_DIR/lib -lm
dnl ])
dnl
dnl PHP_SUBST(SYMFONY_DEBUG_SHARED_LIBADD)
PHP_NEW_EXTENSION(symfony_debug, symfony_debug.c, $ext_shared)
fi

View File

@@ -1,13 +0,0 @@
// $Id$
// vim:ft=javascript
// If your extension references something external, use ARG_WITH
// ARG_WITH("symfony_debug", "for symfony_debug support", "no");
// Otherwise, use ARG_ENABLE
// ARG_ENABLE("symfony_debug", "enable symfony_debug support", "no");
if (PHP_SYMFONY_DEBUG != "no") {
EXTENSION("symfony_debug", "symfony_debug.c");
}

View File

@@ -1,60 +0,0 @@
/*
* 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.
*/
#ifndef PHP_SYMFONY_DEBUG_H
#define PHP_SYMFONY_DEBUG_H
extern zend_module_entry symfony_debug_module_entry;
#define phpext_symfony_debug_ptr &symfony_debug_module_entry
#define PHP_SYMFONY_DEBUG_VERSION "2.7"
#ifdef PHP_WIN32
# define PHP_SYMFONY_DEBUG_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
# define PHP_SYMFONY_DEBUG_API __attribute__ ((visibility("default")))
#else
# define PHP_SYMFONY_DEBUG_API
#endif
#ifdef ZTS
#include "TSRM.h"
#endif
ZEND_BEGIN_MODULE_GLOBALS(symfony_debug)
intptr_t req_rand_init;
void (*old_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
zval *debug_bt;
ZEND_END_MODULE_GLOBALS(symfony_debug)
PHP_MINIT_FUNCTION(symfony_debug);
PHP_MSHUTDOWN_FUNCTION(symfony_debug);
PHP_RINIT_FUNCTION(symfony_debug);
PHP_RSHUTDOWN_FUNCTION(symfony_debug);
PHP_MINFO_FUNCTION(symfony_debug);
PHP_GINIT_FUNCTION(symfony_debug);
PHP_GSHUTDOWN_FUNCTION(symfony_debug);
PHP_FUNCTION(symfony_zval_info);
PHP_FUNCTION(symfony_debug_backtrace);
static char *_symfony_debug_memory_address_hash(void * TSRMLS_DC);
static const char *_symfony_debug_zval_type(zval *);
static const char* _symfony_debug_get_resource_type(long TSRMLS_DC);
static int _symfony_debug_get_resource_refcount(long TSRMLS_DC);
void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
#ifdef ZTS
#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v)
#else
#define SYMFONY_DEBUG_G(v) (symfony_debug_globals.v)
#endif
#endif /* PHP_SYMFONY_DEBUG_H */

View File

@@ -1,283 +0,0 @@
/*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#ifdef ZTS
#include "TSRM.h"
#endif
#include "php_ini.h"
#include "ext/standard/info.h"
#include "php_symfony_debug.h"
#include "ext/standard/php_rand.h"
#include "ext/standard/php_lcg.h"
#include "ext/spl/php_spl.h"
#include "Zend/zend_gc.h"
#include "Zend/zend_builtin_functions.h"
#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */
#include "ext/standard/php_array.h"
#include "Zend/zend_interfaces.h"
#include "SAPI.h"
#define IS_PHP_53 ZEND_EXTENSION_API_NO == 220090626
ZEND_DECLARE_MODULE_GLOBALS(symfony_debug)
ZEND_BEGIN_ARG_INFO_EX(symfony_zval_arginfo, 0, 0, 2)
ZEND_ARG_INFO(0, key)
ZEND_ARG_ARRAY_INFO(0, array, 0)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
const zend_function_entry symfony_debug_functions[] = {
PHP_FE(symfony_zval_info, symfony_zval_arginfo)
PHP_FE(symfony_debug_backtrace, NULL)
PHP_FE_END
};
PHP_FUNCTION(symfony_debug_backtrace)
{
if (zend_parse_parameters_none() == FAILURE) {
return;
}
#if IS_PHP_53
zend_fetch_debug_backtrace(return_value, 1, 0 TSRMLS_CC);
#else
zend_fetch_debug_backtrace(return_value, 1, 0, 0 TSRMLS_CC);
#endif
if (!SYMFONY_DEBUG_G(debug_bt)) {
return;
}
php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(SYMFONY_DEBUG_G(debug_bt)), 0 TSRMLS_CC);
}
PHP_FUNCTION(symfony_zval_info)
{
zval *key = NULL, *arg = NULL;
zval **data = NULL;
HashTable *array = NULL;
long options = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zh|l", &key, &array, &options) == FAILURE) {
return;
}
switch (Z_TYPE_P(key)) {
case IS_STRING:
if (zend_symtable_find(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&data) == FAILURE) {
return;
}
break;
case IS_LONG:
if (zend_hash_index_find(array, Z_LVAL_P(key), (void **)&data)) {
return;
}
break;
}
arg = *data;
array_init(return_value);
add_assoc_string(return_value, "type", (char *)_symfony_debug_zval_type(arg), 1);
add_assoc_stringl(return_value, "zval_hash", _symfony_debug_memory_address_hash((void *)arg TSRMLS_CC), 16, 0);
add_assoc_long(return_value, "zval_refcount", Z_REFCOUNT_P(arg));
add_assoc_bool(return_value, "zval_isref", (zend_bool)Z_ISREF_P(arg));
if (Z_TYPE_P(arg) == IS_OBJECT) {
char hash[33] = {0};
php_spl_object_hash(arg, (char *)hash TSRMLS_CC);
add_assoc_stringl(return_value, "object_class", (char *)Z_OBJCE_P(arg)->name, Z_OBJCE_P(arg)->name_length, 1);
add_assoc_long(return_value, "object_refcount", EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(arg)].bucket.obj.refcount);
add_assoc_string(return_value, "object_hash", hash, 1);
add_assoc_long(return_value, "object_handle", Z_OBJ_HANDLE_P(arg));
} else if (Z_TYPE_P(arg) == IS_ARRAY) {
add_assoc_long(return_value, "array_count", zend_hash_num_elements(Z_ARRVAL_P(arg)));
} else if(Z_TYPE_P(arg) == IS_RESOURCE) {
add_assoc_long(return_value, "resource_handle", Z_LVAL_P(arg));
add_assoc_string(return_value, "resource_type", (char *)_symfony_debug_get_resource_type(Z_LVAL_P(arg) TSRMLS_CC), 1);
add_assoc_long(return_value, "resource_refcount", _symfony_debug_get_resource_refcount(Z_LVAL_P(arg) TSRMLS_CC));
} else if (Z_TYPE_P(arg) == IS_STRING) {
add_assoc_long(return_value, "strlen", Z_STRLEN_P(arg));
}
}
void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args)
{
TSRMLS_FETCH();
zval *retval;
switch (type) {
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_CORE_WARNING:
case E_COMPILE_ERROR:
case E_COMPILE_WARNING:
ALLOC_INIT_ZVAL(retval);
#if IS_PHP_53
zend_fetch_debug_backtrace(retval, 1, 0 TSRMLS_CC);
#else
zend_fetch_debug_backtrace(retval, 1, 0, 0 TSRMLS_CC);
#endif
SYMFONY_DEBUG_G(debug_bt) = retval;
}
SYMFONY_DEBUG_G(old_error_cb)(type, error_filename, error_lineno, format, args);
}
static const char* _symfony_debug_get_resource_type(long rsid TSRMLS_DC)
{
const char *res_type;
res_type = zend_rsrc_list_get_rsrc_type(rsid TSRMLS_CC);
if (!res_type) {
return "Unknown";
}
return res_type;
}
static int _symfony_debug_get_resource_refcount(long rsid TSRMLS_DC)
{
zend_rsrc_list_entry *le;
if (zend_hash_index_find(&EG(regular_list), rsid, (void **) &le)==SUCCESS) {
return le->refcount;
}
return 0;
}
static char *_symfony_debug_memory_address_hash(void *address TSRMLS_DC)
{
char *result = NULL;
intptr_t address_rand;
if (!SYMFONY_DEBUG_G(req_rand_init)) {
if (!BG(mt_rand_is_seeded)) {
php_mt_srand(GENERATE_SEED() TSRMLS_CC);
}
SYMFONY_DEBUG_G(req_rand_init) = (intptr_t)php_mt_rand(TSRMLS_C);
}
address_rand = (intptr_t)address ^ SYMFONY_DEBUG_G(req_rand_init);
spprintf(&result, 17, "%016zx", address_rand);
return result;
}
static const char *_symfony_debug_zval_type(zval *zv)
{
switch (Z_TYPE_P(zv)) {
case IS_NULL:
return "NULL";
break;
case IS_BOOL:
return "boolean";
break;
case IS_LONG:
return "integer";
break;
case IS_DOUBLE:
return "double";
break;
case IS_STRING:
return "string";
break;
case IS_ARRAY:
return "array";
break;
case IS_OBJECT:
return "object";
case IS_RESOURCE:
return "resource";
default:
return "unknown type";
}
}
zend_module_entry symfony_debug_module_entry = {
STANDARD_MODULE_HEADER,
"symfony_debug",
symfony_debug_functions,
PHP_MINIT(symfony_debug),
PHP_MSHUTDOWN(symfony_debug),
PHP_RINIT(symfony_debug),
PHP_RSHUTDOWN(symfony_debug),
PHP_MINFO(symfony_debug),
PHP_SYMFONY_DEBUG_VERSION,
PHP_MODULE_GLOBALS(symfony_debug),
PHP_GINIT(symfony_debug),
PHP_GSHUTDOWN(symfony_debug),
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
#ifdef COMPILE_DL_SYMFONY_DEBUG
ZEND_GET_MODULE(symfony_debug)
#endif
PHP_GINIT_FUNCTION(symfony_debug)
{
memset(symfony_debug_globals, 0 , sizeof(*symfony_debug_globals));
}
PHP_GSHUTDOWN_FUNCTION(symfony_debug)
{
}
PHP_MINIT_FUNCTION(symfony_debug)
{
SYMFONY_DEBUG_G(old_error_cb) = zend_error_cb;
zend_error_cb = symfony_debug_error_cb;
return SUCCESS;
}
PHP_MSHUTDOWN_FUNCTION(symfony_debug)
{
zend_error_cb = SYMFONY_DEBUG_G(old_error_cb);
return SUCCESS;
}
PHP_RINIT_FUNCTION(symfony_debug)
{
return SUCCESS;
}
PHP_RSHUTDOWN_FUNCTION(symfony_debug)
{
return SUCCESS;
}
PHP_MINFO_FUNCTION(symfony_debug)
{
php_info_print_table_start();
php_info_print_table_header(2, "Symfony Debug support", "enabled");
php_info_print_table_header(2, "Symfony Debug version", PHP_SYMFONY_DEBUG_VERSION);
php_info_print_table_end();
}

View File

@@ -1,153 +0,0 @@
--TEST--
Test symfony_zval_info API
--SKIPIF--
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
--FILE--
<?php
$int = 42;
$float = 42.42;
$str = 'foobar';
$object = new StdClass();
$array = array('foo', 'bar');
$resource = tmpfile();
$null = null;
$bool = true;
$anotherint = 42;
$refcount2 = &$anotherint;
$var = array(
'int' => $int,
'float' => $float,
'str' => $str,
'object' => $object,
'array' => $array,
'resource' => $resource,
'null' => $null,
'bool' => $bool,
'refcount' => &$refcount2,
);
var_dump(symfony_zval_info('int', $var));
var_dump(symfony_zval_info('float', $var));
var_dump(symfony_zval_info('str', $var));
var_dump(symfony_zval_info('object', $var));
var_dump(symfony_zval_info('array', $var));
var_dump(symfony_zval_info('resource', $var));
var_dump(symfony_zval_info('null', $var));
var_dump(symfony_zval_info('bool', $var));
var_dump(symfony_zval_info('refcount', $var));
var_dump(symfony_zval_info('not-exist', $var));
?>
--EXPECTF--
array(4) {
["type"]=>
string(7) "integer"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
}
array(4) {
["type"]=>
string(6) "double"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
}
array(5) {
["type"]=>
string(6) "string"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
["strlen"]=>
int(6)
}
array(8) {
["type"]=>
string(6) "object"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
["object_class"]=>
string(8) "stdClass"
["object_refcount"]=>
int(1)
["object_hash"]=>
string(32) "%s"
["object_handle"]=>
int(%d)
}
array(5) {
["type"]=>
string(5) "array"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
["array_count"]=>
int(2)
}
array(7) {
["type"]=>
string(8) "resource"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
["resource_handle"]=>
int(%d)
["resource_type"]=>
string(6) "stream"
["resource_refcount"]=>
int(1)
}
array(4) {
["type"]=>
string(4) "NULL"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
}
array(4) {
["type"]=>
string(7) "boolean"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(2)
["zval_isref"]=>
bool(false)
}
array(4) {
["type"]=>
string(7) "integer"
["zval_hash"]=>
string(16) "%s"
["zval_refcount"]=>
int(3)
["zval_isref"]=>
bool(true)
}
NULL

View File

@@ -1,63 +0,0 @@
--TEST--
Test symfony_debug_backtrace in case of fatal error
--SKIPIF--
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
--FILE--
<?php
function bar()
{
foo();
}
function foo()
{
notexist();
}
function bt()
{
print_r(symfony_debug_backtrace());
}
register_shutdown_function('bt');
bar();
?>
--EXPECTF--
Fatal error: Call to undefined function notexist() in %s on line %d
Array
(
[0] => Array
(
[function] => bt
[args] => Array
(
)
)
[1] => Array
(
[file] => %s
[line] => %d
[function] => foo
[args] => Array
(
)
)
[2] => Array
(
[file] => %s
[line] => %d
[function] => bar
[args] => Array
(
)
)
)

View File

@@ -1,46 +0,0 @@
--TEST--
Test symfony_debug_backtrace in case of non fatal error
--SKIPIF--
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
--FILE--
<?php
function bar()
{
bt();
}
function bt()
{
print_r(symfony_debug_backtrace());
}
bar();
?>
--EXPECTF--
Array
(
[0] => Array
(
[file] => %s
[line] => %d
[function] => bt
[args] => Array
(
)
)
[1] => Array
(
[file] => %s
[line] => %d
[function] => bar
[args] => Array
(
)
)
)

View File

@@ -1,85 +0,0 @@
--TEST--
Test ErrorHandler in case of fatal error
--SKIPIF--
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
--FILE--
<?php
namespace Psr\Log;
class LogLevel
{
const EMERGENCY = 'emergency';
const ALERT = 'alert';
const CRITICAL = 'critical';
const ERROR = 'error';
const WARNING = 'warning';
const NOTICE = 'notice';
const INFO = 'info';
const DEBUG = 'debug';
}
namespace Symfony\Component\Debug;
$dir = __DIR__.'/../../../';
require $dir.'ErrorHandler.php';
require $dir.'Exception/FatalErrorException.php';
require $dir.'Exception/UndefinedFunctionException.php';
require $dir.'FatalErrorHandler/FatalErrorHandlerInterface.php';
require $dir.'FatalErrorHandler/ClassNotFoundFatalErrorHandler.php';
require $dir.'FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php';
require $dir.'FatalErrorHandler/UndefinedMethodFatalErrorHandler.php';
function bar()
{
foo();
}
function foo()
{
notexist();
}
$handler = ErrorHandler::register();
$handler->setExceptionHandler('print_r');
if (function_exists('xdebug_disable')) {
xdebug_disable();
}
bar();
?>
--EXPECTF--
Fatal error: Call to undefined function Symfony\Component\Debug\notexist() in %s on line %d
Symfony\Component\Debug\Exception\UndefinedFunctionException Object
(
[message:protected] => Attempted to call function "notexist" from namespace "Symfony\Component\Debug".
[string:Exception:private] =>
[code:protected] => 0
[file:protected] => %s
[line:protected] => %d
[trace:Exception:private] => Array
(
[0] => Array
(
%A [function] => Symfony\Component\Debug\foo
%A [args] => Array
(
)
)
[1] => Array
(
%A [function] => Symfony\Component\Debug\bar
%A [args] => Array
(
)
)
%A
)
[previous:Exception:private] =>
[severity:protected] => 1
)

View File

@@ -13,7 +13,6 @@ namespace Symfony\Component\Debug\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Debug\DebugClassLoader;
use Symfony\Component\Debug\ErrorHandler;
class DebugClassLoaderTest extends TestCase
{
@@ -76,72 +75,8 @@ class DebugClassLoaderTest extends TestCase
class_exists(__NAMESPACE__.'\Fixtures\Throwing');
}
public function testUnsilencing()
{
if (\PHP_VERSION_ID >= 70000) {
$this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.');
}
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('HHVM is not handled in this test case.');
}
ob_start();
$this->iniSet('log_errors', 0);
$this->iniSet('display_errors', 1);
// See below: this will fail with parse error
// but this should not be @-silenced.
@class_exists(__NAMESPACE__.'\TestingUnsilencing', true);
$output = ob_get_clean();
$this->assertStringMatchesFormat('%aParse error%a', $output);
}
public function testStacking()
{
// the ContextErrorException must not be loaded to test the workaround
// for https://bugs.php.net/65322.
if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) {
$this->markTestSkipped('The ContextErrorException class is already loaded.');
}
if (defined('HHVM_VERSION')) {
$this->markTestSkipped('HHVM is not handled in this test case.');
}
ErrorHandler::register();
try {
// Trigger autoloading + E_STRICT at compile time
// which in turn triggers $errorHandler->handle()
// that again triggers autoloading for ContextErrorException.
// Error stacking works around the bug above and everything is fine.
eval('
namespace '.__NAMESPACE__.';
class ChildTestingStacking extends TestingStacking { function foo($bar) {} }
');
$this->fail('ContextErrorException expected');
} catch (\ErrorException $exception) {
// if an exception is thrown, the test passed
$this->assertStringStartsWith(__FILE__, $exception->getFile());
if (\PHP_VERSION_ID < 70000) {
$this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage());
$this->assertEquals(E_STRICT, $exception->getSeverity());
} else {
$this->assertRegExp('/^Warning: Declaration/', $exception->getMessage());
$this->assertEquals(E_WARNING, $exception->getSeverity());
}
} finally {
restore_error_handler();
restore_exception_handler();
}
}
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Case mismatch between loaded and declared class names
*/
public function testNameCaseMismatch()
{
@@ -163,7 +98,6 @@ class DebugClassLoaderTest extends TestCase
/**
* @expectedException \RuntimeException
* @expectedExceptionMessage Case mismatch between loaded and declared class names
*/
public function testPsr4CaseMismatch()
{
@@ -204,7 +138,7 @@ class DebugClassLoaderTest extends TestCase
$xError = array(
'type' => E_USER_DEPRECATED,
'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice',
'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.',
);
$this->assertSame($xError, $lastError);
@@ -262,32 +196,6 @@ class DebugClassLoaderTest extends TestCase
$this->assertSame($xError, $lastError);
}
public function testReservedForPhp7()
{
if (\PHP_VERSION_ID >= 70000) {
$this->markTestSkipped('PHP7 already prevents using reserved names.');
}
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
class_exists('Test\\'.__NAMESPACE__.'\\Float', true);
error_reporting($e);
restore_error_handler();
$lastError = error_get_last();
unset($lastError['file'], $lastError['line']);
$xError = array(
'type' => E_USER_DEPRECATED,
'message' => 'The "Test\Symfony\Component\Debug\Tests\Float" class uses the reserved name "Float", it will break on PHP 7 and higher',
);
$this->assertSame($xError, $lastError);
}
public function testExtendedFinalClass()
{
set_error_handler(function () { return false; });
@@ -331,6 +239,42 @@ class DebugClassLoaderTest extends TestCase
$this->assertSame($xError, $lastError);
}
public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice()
{
set_error_handler(function () { return false; });
$e = error_reporting(0);
trigger_error('', E_USER_NOTICE);
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true);
error_reporting($e);
restore_error_handler();
$lastError = error_get_last();
unset($lastError['file'], $lastError['line']);
$this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError);
}
public function testInternalsUse()
{
$deprecations = array();
set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; });
$e = error_reporting(E_USER_DEPRECATED);
class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true);
error_reporting($e);
restore_error_handler();
$this->assertSame($deprecations, array(
'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".',
'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".',
));
}
}
class ClassLoader
@@ -354,22 +298,12 @@ class ClassLoader
eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }');
} elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) {
eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}');
} elseif (__NAMESPACE__.'\Fixtures\CaseMismatch' === $class) {
return $fixtureDir.'CaseMismatch.php';
} elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) {
return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php';
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) {
return $fixtureDir.'reallyNotPsr0.php';
} elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) {
return $fixtureDir.'notPsr0Bis.php';
} elseif (__NAMESPACE__.'\Fixtures\DeprecatedInterface' === $class) {
return $fixtureDir.'DeprecatedInterface.php';
} elseif (__NAMESPACE__.'\Fixtures\FinalClass' === $class) {
return $fixtureDir.'FinalClass.php';
} elseif (__NAMESPACE__.'\Fixtures\FinalMethod' === $class) {
return $fixtureDir.'FinalMethod.php';
} elseif (__NAMESPACE__.'\Fixtures\ExtendedFinalMethod' === $class) {
return $fixtureDir.'ExtendedFinalMethod.php';
} elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) {
eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}');
} elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) {
@@ -382,6 +316,18 @@ class ClassLoader
eval('namespace Test\\'.__NAMESPACE__.'; class Float {}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass {
public function deprecatedMethod() { }
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent {
use \\'.__NAMESPACE__.'\Fixtures\InternalTrait;
public function internalMethod() { }
}');
} elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) {
eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }');
}
}
}

View File

@@ -98,8 +98,6 @@ class ErrorHandlerTest extends TestCase
// dummy function to test trace in error handler.
private static function triggerNotice($that)
{
// dummy variable to check for in error handler.
$foobar = 123;
$that->assertSame('', $foo.$foo.$bar);
}
@@ -342,35 +340,6 @@ class ErrorHandlerTest extends TestCase
}
}
public function testErrorStacking()
{
try {
$handler = ErrorHandler::register();
$handler->screamAt(E_USER_WARNING);
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$logger
->expects($this->exactly(2))
->method('log')
->withConsecutive(
array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')),
array($this->equalTo(LogLevel::DEBUG), $this->equalTo('User Warning: Silenced warning'))
)
;
$handler->setDefaultLogger($logger, array(E_USER_WARNING => LogLevel::WARNING));
ErrorHandler::stackErrors();
@trigger_error('Silenced warning', E_USER_WARNING);
$logger->log(LogLevel::WARNING, 'Dummy log');
ErrorHandler::unstackErrors();
} finally {
restore_error_handler();
restore_exception_handler();
}
}
public function testBootstrappingLogger()
{
$bootLogger = new BufferingLogger();
@@ -481,9 +450,6 @@ class ErrorHandlerTest extends TestCase
}
}
/**
* @requires PHP 7
*/
public function testHandleErrorException()
{
$exception = new \Error("Class 'Foo' not found");
@@ -498,38 +464,4 @@ class ErrorHandlerTest extends TestCase
$this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]);
$this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage());
}
public function testHandleFatalErrorOnHHVM()
{
try {
$handler = ErrorHandler::register();
$logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$logger
->expects($this->once())
->method('log')
->with(
$this->equalTo(LogLevel::CRITICAL),
$this->equalTo('Fatal Error: foo')
)
;
$handler->setDefaultLogger($logger, E_ERROR);
$error = array(
'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors
'message' => 'foo',
'file' => 'bar',
'line' => 123,
'context' => array(123),
'backtrace' => array(456),
);
call_user_func_array(array($handler, 'handleError'), $error);
$handler->handleFatalError($error);
} finally {
restore_error_handler();
restore_exception_handler();
}
}
}

View File

@@ -138,9 +138,6 @@ class FlattenExceptionTest extends TestCase
$this->assertSame(array($flattened2), $flattened->getAllPrevious());
}
/**
* @requires PHP 7.0
*/
public function testPreviousError()
{
$exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42));
@@ -236,7 +233,7 @@ class FlattenExceptionTest extends TestCase
$this->assertSame(array('object', 'stdClass'), $array[$i++]);
$this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]);
$this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]);
$this->assertSame(array('resource', defined('HHVM_VERSION') ? 'Directory' : 'stream'), $array[$i++]);
$this->assertSame(array('resource', 'stream'), $array[$i++]);
$this->assertSame(array('resource', 'stream'), $array[$i++]);
$args = $array[$i++];

View File

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

View File

@@ -0,0 +1,13 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
class AnnotatedClass
{
/**
* @deprecated since version 3.4.
*/
public function deprecatedMethod()
{
}
}

View File

@@ -0,0 +1,15 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @internal since version 3.4.
*/
class InternalClass
{
use InternalTrait2;
public function usedInInternalClass()
{
}
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @internal
*/
interface InternalInterface
{
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @internal
*/
trait InternalTrait
{
}

View File

@@ -0,0 +1,23 @@
<?php
namespace Symfony\Component\Debug\Tests\Fixtures;
/**
* @internal
*/
trait InternalTrait2
{
/**
* @internal since version 3.4
*/
public function internalMethod()
{
}
/**
* @internal but should not trigger a deprecation
*/
public function usedInInternalClass()
{
}
}

View File

@@ -16,14 +16,14 @@
}
],
"require": {
"php": "^5.5.9|>=7.0.8",
"php": "^7.1.3",
"psr/log": "~1.0"
},
"conflict": {
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
"symfony/http-kernel": "<3.4"
},
"require-dev": {
"symfony/http-kernel": "~2.8|~3.0"
"symfony/http-kernel": "~3.4|~4.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Debug\\": "" },
@@ -34,7 +34,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "3.3-dev"
"dev-master": "4.0-dev"
}
}
}