TYPO3 CMS  TYPO3_8-7
ErrorHandler.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Error;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
21 
28 {
34  protected $exceptionalErrors = 0;
35 
41  protected $debugMode = false;
42 
48  public function __construct($errorHandlerErrors)
49  {
50  $excludedErrors = E_COMPILE_WARNING | E_COMPILE_ERROR | E_CORE_WARNING | E_CORE_ERROR | E_PARSE | E_ERROR;
51  // reduces error types to those a custom error handler can process
52  $errorHandlerErrors = $errorHandlerErrors & ~$excludedErrors;
53  set_error_handler([$this, 'handleError'], $errorHandlerErrors);
54  }
55 
62  {
63  $this->exceptionalErrors = (int)$exceptionalErrors;
64  }
65 
69  public function setDebugMode($debugMode)
70  {
71  $this->debugMode = (bool)$debugMode;
72  }
73 
88  public function handleError($errorLevel, $errorMessage, $errorFile, $errorLine)
89  {
90  // Don't do anything if error_reporting is disabled by an @ sign
91  if (error_reporting() === 0) {
92  return true;
93  }
94  $errorLevels = [
95  E_WARNING => 'PHP Warning',
96  E_NOTICE => 'PHP Notice',
97  E_USER_ERROR => 'PHP User Error',
98  E_USER_WARNING => 'PHP User Warning',
99  E_USER_NOTICE => 'PHP User Notice',
100  E_STRICT => 'PHP Runtime Notice',
101  E_RECOVERABLE_ERROR => 'PHP Catchable Fatal Error',
102  E_USER_DEPRECATED => 'TYPO3 Deprecation Notice',
103  E_DEPRECATED => 'PHP Runtime Deprecation Notice'
104  ];
105  $message = $errorLevels[$errorLevel] . ': ' . $errorMessage . ' in ' . $errorFile . ' line ' . $errorLine;
106  if ($errorLevel & $this->exceptionalErrors) {
107  throw new Exception($message, 1476107295);
108  }
109  switch ($errorLevel) {
110  case E_USER_ERROR:
111  case E_RECOVERABLE_ERROR:
112  // no $flashMessageSeverity, as there will be no flash message for errors
113  $severity = 2;
114  break;
115  case E_USER_WARNING:
116  case E_WARNING:
117  case E_USER_DEPRECATED:
118  $flashMessageSeverity = FlashMessage::WARNING;
119  $severity = 1;
120  break;
121  default:
122  $flashMessageSeverity = FlashMessage::NOTICE;
123  $severity = 0;
124  }
125  $logTitle = 'Core: Error handler (' . TYPO3_MODE . ')';
126  $message = $logTitle . ': ' . $message;
127  // Write error message to the configured syslogs,
128  // see: $TYPO3_CONF_VARS['SYS']['systemLog']
129  if ($errorLevel & $GLOBALS['TYPO3_CONF_VARS']['SYS']['syslogErrorReporting']) {
130  GeneralUtility::sysLog($message, 'core', $severity + 1);
131  }
132  // Write error message to devlog extension(s),
133  GeneralUtility::devLog($message, 'core', $severity + 1);
134 
135  // Write error message to TSlog (admin panel)
136  $timeTracker = $this->getTimeTracker();
137  if (is_object($timeTracker)) {
138  $timeTracker->setTSlogMessage($message, $severity + 1);
139  }
140  // Write error message to sys_log table (ext: belog, Tools->Log)
141  if ($errorLevel & $GLOBALS['TYPO3_CONF_VARS']['SYS']['belogErrorReporting']) {
142  // Silently catch in case an error occurs before a database connection exists,
143  // but DatabaseConnection fails to connect.
144  try {
145  $this->writeLog($message, $severity);
146  } catch (\Exception $e) {
147  }
148  }
149  if ($severity === 2) {
150  // Let the internal handler continue. This will stop the script
151  return false;
152  }
153  if ($this->debugMode) {
155  $flashMessage = GeneralUtility::makeInstance(
156  \TYPO3\CMS\Core\Messaging\FlashMessage::class,
157  $message,
158  $errorLevels[$errorLevel],
159  $flashMessageSeverity
160  );
162  $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
164  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
165  $defaultFlashMessageQueue->enqueue($flashMessage);
166  }
167  // Don't execute PHP internal error handler
168  return true;
169  }
170 
177  protected function writeLog($logMessage, $severity)
178  {
179  $connection = GeneralUtility::makeInstance(ConnectionPool::class)
180  ->getConnectionForTable('sys_log');
181  if ($connection->isConnected()) {
182  $userId = 0;
183  $workspace = 0;
184  $data = [];
185  $backendUser = $this->getBackendUser();
186  if (is_object($backendUser)) {
187  if (isset($backendUser->user['uid'])) {
188  $userId = $backendUser->user['uid'];
189  }
190  if (isset($backendUser->workspace)) {
191  $workspace = $backendUser->workspace;
192  }
193  if (!empty($backendUser->user['ses_backuserid'])) {
194  $data['originalUser'] = $backendUser->user['ses_backuserid'];
195  }
196  }
197 
198  $connection->insert(
199  'sys_log',
200  [
201  'userid' => $userId,
202  'type' => 5,
203  'action' => 0,
204  'error' => $severity,
205  'details_nr' => 0,
206  'details' => str_replace('%', '%%', $logMessage),
207  'log_data' => (empty($data) ? '' : serialize($data)),
208  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
209  'tstamp' => $GLOBALS['EXEC_TIME'],
210  'workspace' => $workspace
211  ]
212  );
213  }
214  }
215 
219  protected function getTimeTracker()
220  {
221  return GeneralUtility::makeInstance(TimeTracker::class);
222  }
223 
227  protected function getBackendUser()
228  {
229  return $GLOBALS['BE_USER'];
230  }
231 }
static devLog($msg, $extKey, $severity=0, $dataVar=false)
handleError($errorLevel, $errorMessage, $errorFile, $errorLine)
writeLog($logMessage, $severity)
setExceptionalErrors($exceptionalErrors)
__construct($errorHandlerErrors)
static makeInstance($className,... $constructorArguments)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']