/laravel_tintuc/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php

https://gitlab.com/nmhieucoder/laravel_tintuc · PHP · 188 lines · 142 code · 18 blank · 28 comment · 33 complexity · df4516df24aaf19b083ddadd03b8db24 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of the Symfony package.
  4. *
  5. * (c) Fabien Potencier <fabien@symfony.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Symfony\Component\HttpKernel\EventListener;
  11. use Psr\Log\LoggerInterface;
  12. use Symfony\Component\Console\ConsoleEvents;
  13. use Symfony\Component\Console\Event\ConsoleEvent;
  14. use Symfony\Component\Console\Output\ConsoleOutputInterface;
  15. use Symfony\Component\ErrorHandler\ErrorHandler;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
  18. use Symfony\Component\HttpKernel\Event\KernelEvent;
  19. use Symfony\Component\HttpKernel\KernelEvents;
  20. /**
  21. * Configures errors and exceptions handlers.
  22. *
  23. * @author Nicolas Grekas <p@tchwork.com>
  24. *
  25. * @final
  26. *
  27. * @internal since Symfony 5.3
  28. */
  29. class DebugHandlersListener implements EventSubscriberInterface
  30. {
  31. private $earlyHandler;
  32. private $exceptionHandler;
  33. private $logger;
  34. private $deprecationLogger;
  35. private $levels;
  36. private $throwAt;
  37. private $scream;
  38. private $fileLinkFormat;
  39. private $scope;
  40. private $firstCall = true;
  41. private $hasTerminatedWithException;
  42. /**
  43. * @param callable|null $exceptionHandler A handler that must support \Throwable instances that will be called on Exception
  44. * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
  45. * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value
  46. * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged
  47. * @param string|FileLinkFormatter|null $fileLinkFormat The format for links to source files
  48. * @param bool $scope Enables/disables scoping mode
  49. */
  50. public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = \E_ALL, ?int $throwAt = \E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true, LoggerInterface $deprecationLogger = null)
  51. {
  52. $handler = set_exception_handler('var_dump');
  53. $this->earlyHandler = \is_array($handler) ? $handler[0] : null;
  54. restore_exception_handler();
  55. $this->exceptionHandler = $exceptionHandler;
  56. $this->logger = $logger;
  57. $this->levels = null === $levels ? \E_ALL : $levels;
  58. $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? \E_ALL : null));
  59. $this->scream = $scream;
  60. $this->fileLinkFormat = $fileLinkFormat;
  61. $this->scope = $scope;
  62. $this->deprecationLogger = $deprecationLogger;
  63. }
  64. /**
  65. * Configures the error handler.
  66. */
  67. public function configure(object $event = null)
  68. {
  69. if ($event instanceof ConsoleEvent && !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
  70. return;
  71. }
  72. if (!$event instanceof KernelEvent ? !$this->firstCall : !$event->isMainRequest()) {
  73. return;
  74. }
  75. $this->firstCall = $this->hasTerminatedWithException = false;
  76. $handler = set_exception_handler('var_dump');
  77. $handler = \is_array($handler) ? $handler[0] : null;
  78. restore_exception_handler();
  79. if (!$handler instanceof ErrorHandler) {
  80. $handler = $this->earlyHandler;
  81. }
  82. if ($handler instanceof ErrorHandler) {
  83. if ($this->logger || $this->deprecationLogger) {
  84. $this->setDefaultLoggers($handler);
  85. if (\is_array($this->levels)) {
  86. $levels = 0;
  87. foreach ($this->levels as $type => $log) {
  88. $levels |= $type;
  89. }
  90. } else {
  91. $levels = $this->levels;
  92. }
  93. if ($this->scream) {
  94. $handler->screamAt($levels);
  95. }
  96. if ($this->scope) {
  97. $handler->scopeAt($levels & ~\E_USER_DEPRECATED & ~\E_DEPRECATED);
  98. } else {
  99. $handler->scopeAt(0, true);
  100. }
  101. $this->logger = $this->deprecationLogger = $this->levels = null;
  102. }
  103. if (null !== $this->throwAt) {
  104. $handler->throwAt($this->throwAt, true);
  105. }
  106. }
  107. if (!$this->exceptionHandler) {
  108. if ($event instanceof KernelEvent) {
  109. if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) {
  110. $request = $event->getRequest();
  111. $hasRun = &$this->hasTerminatedWithException;
  112. $this->exceptionHandler = static function (\Throwable $e) use ($kernel, $request, &$hasRun) {
  113. if ($hasRun) {
  114. throw $e;
  115. }
  116. $hasRun = true;
  117. $kernel->terminateWithException($e, $request);
  118. };
  119. }
  120. } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
  121. $output = $event->getOutput();
  122. if ($output instanceof ConsoleOutputInterface) {
  123. $output = $output->getErrorOutput();
  124. }
  125. $this->exceptionHandler = static function (\Throwable $e) use ($app, $output) {
  126. $app->renderThrowable($e, $output);
  127. };
  128. }
  129. }
  130. if ($this->exceptionHandler) {
  131. if ($handler instanceof ErrorHandler) {
  132. $handler->setExceptionHandler($this->exceptionHandler);
  133. }
  134. $this->exceptionHandler = null;
  135. }
  136. }
  137. private function setDefaultLoggers(ErrorHandler $handler): void
  138. {
  139. if (\is_array($this->levels)) {
  140. $levelsDeprecatedOnly = [];
  141. $levelsWithoutDeprecated = [];
  142. foreach ($this->levels as $type => $log) {
  143. if (\E_DEPRECATED == $type || \E_USER_DEPRECATED == $type) {
  144. $levelsDeprecatedOnly[$type] = $log;
  145. } else {
  146. $levelsWithoutDeprecated[$type] = $log;
  147. }
  148. }
  149. } else {
  150. $levelsDeprecatedOnly = $this->levels & (\E_DEPRECATED | \E_USER_DEPRECATED);
  151. $levelsWithoutDeprecated = $this->levels & ~\E_DEPRECATED & ~\E_USER_DEPRECATED;
  152. }
  153. $defaultLoggerLevels = $this->levels;
  154. if ($this->deprecationLogger && $levelsDeprecatedOnly) {
  155. $handler->setDefaultLogger($this->deprecationLogger, $levelsDeprecatedOnly);
  156. $defaultLoggerLevels = $levelsWithoutDeprecated;
  157. }
  158. if ($this->logger && $defaultLoggerLevels) {
  159. $handler->setDefaultLogger($this->logger, $defaultLoggerLevels);
  160. }
  161. }
  162. public static function getSubscribedEvents(): array
  163. {
  164. $events = [KernelEvents::REQUEST => ['configure', 2048]];
  165. if (\defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
  166. $events[ConsoleEvents::COMMAND] = ['configure', 2048];
  167. }
  168. return $events;
  169. }
  170. }