TYPO3  7.6
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 
18 
25 {
31  protected $exceptionalErrors = array();
32 
38  protected $debugMode = false;
39 
45  public function __construct($errorHandlerErrors)
46  {
47  $excludedErrors = E_COMPILE_WARNING | E_COMPILE_ERROR | E_CORE_WARNING | E_CORE_ERROR | E_PARSE | E_ERROR;
48  // reduces error types to those a custom error handler can process
49  $errorHandlerErrors = $errorHandlerErrors & ~$excludedErrors;
50  set_error_handler(array($this, 'handleError'), $errorHandlerErrors);
51  }
52 
60  {
61  $this->exceptionalErrors = (int)$exceptionalErrors;
62  }
63 
67  public function setDebugMode($debugMode)
68  {
69  $this->debugMode = (bool)$debugMode;
70  }
71 
86  public function handleError($errorLevel, $errorMessage, $errorFile, $errorLine)
87  {
88  // Don't do anything if error_reporting is disabled by an @ sign
89  if (error_reporting() === 0) {
90  return true;
91  }
92  $errorLevels = array(
93  E_WARNING => 'Warning',
94  E_NOTICE => 'Notice',
95  E_USER_ERROR => 'User Error',
96  E_USER_WARNING => 'User Warning',
97  E_USER_NOTICE => 'User Notice',
98  E_STRICT => 'Runtime Notice',
99  E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
100  E_DEPRECATED => 'Runtime Deprecation Notice'
101  );
102  $message = 'PHP ' . $errorLevels[$errorLevel] . ': ' . $errorMessage . ' in ' . $errorFile . ' line ' . $errorLine;
103  if ($errorLevel & $this->exceptionalErrors) {
104  // handle error raised at early parse time
105  // autoloader not available & built-in classes not resolvable
106  if (!class_exists('stdClass', false)) {
107  $message = 'PHP ' . $errorLevels[$errorLevel] . ': ' . $errorMessage . ' in ' . basename($errorFile) .
108  'line ' . $errorLine;
109  die($message);
110  }
111  throw new Exception($message, 1);
112  } else {
113  switch ($errorLevel) {
114  case E_USER_ERROR:
115  case E_RECOVERABLE_ERROR:
116  $severity = 2;
117  break;
118  case E_USER_WARNING:
119  case E_WARNING:
120  $severity = 1;
121  break;
122  default:
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  // see: $TYPO3_CONF_VARS['SYS']['enable_errorDLOG']
134  if (TYPO3_ERROR_DLOG) {
135  GeneralUtility::devLog($message, 'core', $severity + 1);
136  }
137  // Write error message to TSlog (admin panel)
138  if (is_object($GLOBALS['TT'])) {
139  $GLOBALS['TT']->setTSlogMessage($message, $severity + 1);
140  }
141  // Write error message to sys_log table (ext: belog, Tools->Log)
142  if ($errorLevel & $GLOBALS['TYPO3_CONF_VARS']['SYS']['belogErrorReporting']) {
143  // Silently catch in case an error occurs before a database connection exists,
144  // but DatabaseConnection fails to connect.
145  try {
146  $this->writeLog($message, $severity);
147  } catch (\Exception $e) {
148  }
149  }
150  if ($severity === 2) {
151  // Let the internal handler continue. This will stop the script
152  return false;
153  } else {
154  if ($this->debugMode) {
156  $flashMessage = GeneralUtility::makeInstance(
157  \TYPO3\CMS\Core\Messaging\FlashMessage::class,
158  $message,
159  'PHP ' . $errorLevels[$errorLevel],
160  $severity
161  );
163  $flashMessageService = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
165  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
166  $defaultFlashMessageQueue->enqueue($flashMessage);
167  }
168  // Don't execute PHP internal error handler
169  return true;
170  }
171  }
172  }
173 
181  protected function writeLog($logMessage, $severity)
182  {
183  if (is_object($GLOBALS['TYPO3_DB']) && $GLOBALS['TYPO3_DB']->isConnected()) {
184  $userId = 0;
185  $workspace = 0;
186  if (is_object($GLOBALS['BE_USER'])) {
187  if (isset($GLOBALS['BE_USER']->user['uid'])) {
188  $userId = $GLOBALS['BE_USER']->user['uid'];
189  }
190  if (isset($GLOBALS['BE_USER']->workspace)) {
191  $workspace = $GLOBALS['BE_USER']->workspace;
192  }
193  }
194  $fields_values = array(
195  'userid' => $userId,
196  'type' => 5,
197  'action' => 0,
198  'error' => $severity,
199  'details_nr' => 0,
200  'details' => str_replace('%', '%%', $logMessage),
201  'IP' => (string)GeneralUtility::getIndpEnv('REMOTE_ADDR'),
202  'tstamp' => $GLOBALS['EXEC_TIME'],
203  'workspace' => $workspace
204  );
205  $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_log', $fields_values);
206  }
207  }
208 }