‪TYPO3CMS  10.4
ErrorHandler.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
16 namespace ‪TYPO3\CMS\Core\Error;
17 
18 use Psr\Log\LoggerAwareInterface;
19 use Psr\Log\LoggerAwareTrait;
26 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
27 use ‪TYPO3\CMS\Core\SysLog\Type as SystemLogType;
30 
36 class ‪ErrorHandler implements ‪ErrorHandlerInterface, LoggerAwareInterface
37 {
38  use LoggerAwareTrait;
39 
45  protected ‪$exceptionalErrors = 0;
46 
52  protected ‪$errorHandlerErrors = 0;
53 
59  protected ‪$debugMode = false;
60 
66  public function ‪__construct(‪$errorHandlerErrors)
67  {
68  $excludedErrors = E_COMPILE_WARNING | E_COMPILE_ERROR | E_CORE_WARNING | E_CORE_ERROR | E_PARSE | E_ERROR;
69  // reduces error types to those a custom error handler can process
70  $this->errorHandlerErrors = (int)‪$errorHandlerErrors & ~$excludedErrors;
71  }
72 
79  {
81  // We always disallow E_USER_DEPRECATED to generate exceptions as this may cause
82  // bad user experience specifically during upgrades.
83  $this->exceptionalErrors = ‪$exceptionalErrors & ~E_USER_DEPRECATED;
84  }
85 
89  public function ‪setDebugMode(‪$debugMode)
90  {
91  $this->debugMode = (bool)‪$debugMode;
92  }
93 
94  public function ‪registerErrorHandler()
95  {
96  set_error_handler([$this, 'handleError'], $this->errorHandlerErrors);
97  }
98 
113  public function ‪handleError($errorLevel, $errorMessage, $errorFile, $errorLine)
114  {
115  $flashMessageSeverity = ‪FlashMessage::OK;
116  // Don't do anything if error_reporting is disabled by an @ sign or $errorLevel is something we won't handle
117  $shouldHandleErrorLevel = (bool)($this->errorHandlerErrors & $errorLevel);
118  if (error_reporting() === 0 || !$shouldHandleErrorLevel) {
119  return true;
120  }
121  $errorLevels = [
122  E_WARNING => 'PHP Warning',
123  E_NOTICE => 'PHP Notice',
124  E_USER_ERROR => 'PHP User Error',
125  E_USER_WARNING => 'PHP User Warning',
126  E_USER_NOTICE => 'PHP User Notice',
127  E_STRICT => 'PHP Runtime Notice',
128  E_RECOVERABLE_ERROR => 'PHP Catchable Fatal Error',
129  E_USER_DEPRECATED => 'TYPO3 Deprecation Notice',
130  E_DEPRECATED => 'PHP Runtime Deprecation Notice'
131  ];
132  $message = $errorLevels[$errorLevel] . ': ' . $errorMessage . ' in ' . $errorFile . ' line ' . $errorLine;
133  if ($errorLevel & $this->exceptionalErrors) {
134  throw new Exception($message, 1476107295);
135  }
136  switch ($errorLevel) {
137  case E_USER_ERROR:
138  case E_RECOVERABLE_ERROR:
139  // no $flashMessageSeverity, as there will be no flash message for errors
140  $severity = 2;
141  break;
142  case E_USER_WARNING:
143  case E_WARNING:
144  $flashMessageSeverity = ‪FlashMessage::WARNING;
145  $severity = 1;
146  break;
147  default:
148  $flashMessageSeverity = ‪FlashMessage::NOTICE;
149  $severity = 0;
150  }
151  $logTitle = 'Core: Error handler (' . TYPO3_MODE . ')';
152  $message = $logTitle . ': ' . $message;
153 
154  if ($errorLevel === E_USER_DEPRECATED) {
155  $logger = GeneralUtility::makeInstance(LogManager::class)->getLogger('TYPO3.CMS.deprecations');
156  $logger->notice($message);
157  return true;
158  }
159  if ($this->logger) {
160  $this->logger->log(‪LogLevel::normalizeLevel(LogLevel::NOTICE) - $severity, $message);
161  }
162 
163  try {
164  // Write error message to TSlog (admin panel)
165  $this->‪getTimeTracker()->‪setTSlogMessage($message, $severity + 1);
166  } catch (\Throwable $e) {
167  // Silently catch in case an error occurs before the DI container is in place
168  }
169  // Write error message to sys_log table (ext: belog, Tools->Log)
170  if ($errorLevel & ‪$GLOBALS['TYPO3_CONF_VARS']['SYS']['belogErrorReporting']) {
171  // Silently catch in case an error occurs before a database connection exists.
172  try {
173  $this->‪writeLog($message, $severity);
174  } catch (\Exception $e) {
175  }
176  }
177  if ($severity === 2) {
178  // Let the internal handler continue. This will stop the script
179  return false;
180  }
181  if ($this->debugMode) {
183  $flashMessage = GeneralUtility::makeInstance(
184  FlashMessage::class,
185  $message,
186  $errorLevels[$errorLevel],
187  $flashMessageSeverity
188  );
190  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
192  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
193  $defaultFlashMessageQueue->enqueue($flashMessage);
194  }
195  // Don't execute PHP internal error handler
196  return true;
197  }
198 
205  protected function ‪writeLog($logMessage, $severity)
206  {
207  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
208  ->getConnectionForTable('sys_log');
209  if ($connection->isConnected()) {
210  $userId = 0;
211  $workspace = 0;
212  $data = [];
213  $backendUser = $this->‪getBackendUser();
214  if (is_object($backendUser)) {
215  if (isset($backendUser->user['uid'])) {
216  $userId = $backendUser->user['uid'];
217  }
218  if (isset($backendUser->workspace)) {
219  $workspace = $backendUser->workspace;
220  }
221  if (!empty($backendUser->user['ses_backuserid'])) {
222  $data['originalUser'] = $backendUser->user['ses_backuserid'];
223  }
224  }
225 
226  $connection->insert(
227  'sys_log',
228  [
229  'userid' => $userId,
230  'type' => SystemLogType::ERROR,
231  'action' => SystemLogGenericAction::UNDEFINED,
232  'error' => SystemLogErrorClassification::SYSTEM_ERROR,
233  'level' => $severity,
234  'details_nr' => 0,
235  'details' => str_replace('%', '%%', $logMessage),
236  'log_data' => empty($data) ? '' : serialize($data),
237  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
238  'tstamp' => ‪$GLOBALS['EXEC_TIME'],
239  'workspace' => $workspace
240  ]
241  );
242  }
243  }
244 
248  protected function ‪getTimeTracker()
249  {
250  return GeneralUtility::makeInstance(TimeTracker::class);
251  }
252 
256  protected function ‪getBackendUser()
257  {
258  return ‪$GLOBALS['BE_USER'];
259  }
260 }
‪TYPO3\CMS\Core\Error\ErrorHandler\writeLog
‪writeLog($logMessage, $severity)
Definition: ErrorHandler.php:202
‪TYPO3\CMS\Core\SysLog\Action
Definition: Cache.php:18
‪TYPO3\CMS\Core\Error\ErrorHandler\$debugMode
‪bool $debugMode
Definition: ErrorHandler.php:56
‪TYPO3\CMS\Core\Error\ErrorHandler\$errorHandlerErrors
‪int $errorHandlerErrors
Definition: ErrorHandler.php:50
‪TYPO3\CMS\Core\Error\ErrorHandler\$exceptionalErrors
‪int $exceptionalErrors
Definition: ErrorHandler.php:44
‪TYPO3\CMS\Core\Error\ErrorHandler\setExceptionalErrors
‪setExceptionalErrors($exceptionalErrors)
Definition: ErrorHandler.php:75
‪TYPO3\CMS\Core\TimeTracker\TimeTracker\setTSlogMessage
‪setTSlogMessage($content, $num=0)
Definition: TimeTracker.php:215
‪TYPO3\CMS\Core\Messaging\AbstractMessage\WARNING
‪const WARNING
Definition: AbstractMessage.php:30
‪TYPO3\CMS\Core\Error\ErrorHandlerInterface
Definition: ErrorHandlerInterface.php:24
‪TYPO3\CMS\Core\Error\ErrorHandler\__construct
‪__construct($errorHandlerErrors)
Definition: ErrorHandler.php:63
‪TYPO3\CMS\Core\Error\ErrorHandler\setDebugMode
‪setDebugMode($debugMode)
Definition: ErrorHandler.php:86
‪TYPO3\CMS\Core\Error\ErrorHandler\getTimeTracker
‪TimeTracker getTimeTracker()
Definition: ErrorHandler.php:245
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\Error\ErrorHandler\registerErrorHandler
‪registerErrorHandler()
Definition: ErrorHandler.php:91
‪TYPO3\CMS\Core\Error\ErrorHandler\handleError
‪bool handleError($errorLevel, $errorMessage, $errorFile, $errorLine)
Definition: ErrorHandler.php:110
‪TYPO3\CMS\Core\Error\Exception
Definition: Exception.php:22
‪TYPO3\CMS\Core\Messaging\AbstractMessage\OK
‪const OK
Definition: AbstractMessage.php:29
‪TYPO3\CMS\Core\Messaging\FlashMessage
Definition: FlashMessage.php:24
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Log\LogManager
Definition: LogManager.php:30
‪TYPO3\CMS\Core\Error
Definition: AbstractExceptionHandler.php:16
‪TYPO3\CMS\Core\Messaging\AbstractMessage\NOTICE
‪const NOTICE
Definition: AbstractMessage.php:27
‪TYPO3\CMS\Core\Error\ErrorHandler\getBackendUser
‪TYPO3 CMS Core Authentication BackendUserAuthentication getBackendUser()
Definition: ErrorHandler.php:253
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:46
‪TYPO3\CMS\Core\Log\LogLevel\normalizeLevel
‪static int normalizeLevel($level)
Definition: LogLevel.php:94
‪TYPO3\CMS\Core\TimeTracker\TimeTracker
Definition: TimeTracker.php:30
‪TYPO3\CMS\Core\Messaging\FlashMessageService
Definition: FlashMessageService.php:27
‪TYPO3\CMS\Core\Log\LogLevel
Definition: LogLevel.php:24
‪TYPO3\CMS\Core\SysLog\Type
Definition: Type.php:24
‪TYPO3\CMS\Core\Error\ErrorHandler
Definition: ErrorHandler.php:37