[CLEANUP] Error handling classes
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Error / ErrorHandler.php
1 <?php
2 namespace TYPO3\CMS\Core\Error;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2009-2013 Ingo Renner <ingo@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 *
19 * This script is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * This copyright notice MUST APPEAR in all copies of the script!
25 ***************************************************************/
26 use TYPO3\CMS\Core\Utility\GeneralUtility;
27
28 /**
29 * Global error handler for TYPO3
30 *
31 * This file is a backport from FLOW3
32 *
33 * @author Rupert Germann <rupi@gmx.li>
34 */
35 class ErrorHandler implements \TYPO3\CMS\Core\Error\ErrorHandlerInterface {
36
37 /**
38 * Error levels which should result in an exception thrown.
39 *
40 * @var array
41 */
42 protected $exceptionalErrors = array();
43
44 /**
45 * Registers this class as default error handler
46 *
47 * @param int $errorHandlerErrors The integer representing the E_* error level which should be
48 */
49 public function __construct($errorHandlerErrors) {
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(array($this, 'handleError'), $errorHandlerErrors);
54 }
55
56 /**
57 * Defines which error levels should result in an exception thrown.
58 *
59 * @param int $exceptionalErrors The integer representing the E_* error level to handle as exceptions
60 * @return void
61 */
62 public function setExceptionalErrors($exceptionalErrors) {
63 $this->exceptionalErrors = (int)$exceptionalErrors;
64 }
65
66 /**
67 * Handles an error.
68 * If the error is registered as exceptionalError it will by converted into an exception, to be handled
69 * by the configured exceptionhandler. Additionall the error message is written to the configured logs.
70 * If TYPO3_MODE is 'BE' the error message is also added to the flashMessageQueue, in FE the error message
71 * is displayed in the admin panel (as TsLog message)
72 *
73 * @param int $errorLevel The error level - one of the E_* constants
74 * @param string $errorMessage The error message
75 * @param string $errorFile Name of the file the error occurred in
76 * @param int $errorLine Line number where the error occurred
77 * @return bool
78 * @throws \TYPO3\CMS\Core\Error\Exception with the data passed to this method if the error is registered as exceptionalError
79 */
80 public function handleError($errorLevel, $errorMessage, $errorFile, $errorLine) {
81 // Don't do anything if error_reporting is disabled by an @ sign
82 if (error_reporting() == 0) {
83 return TRUE;
84 }
85 $errorLevels = array(
86 E_WARNING => 'Warning',
87 E_NOTICE => 'Notice',
88 E_USER_ERROR => 'User Error',
89 E_USER_WARNING => 'User Warning',
90 E_USER_NOTICE => 'User Notice',
91 E_STRICT => 'Runtime Notice',
92 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
93 E_DEPRECATED => 'Runtime Deprecation Notice'
94 );
95 $message = 'PHP ' . $errorLevels[$errorLevel] . ': ' . $errorMessage . ' in ' . $errorFile . ' line ' . $errorLine;
96 if ($errorLevel & $this->exceptionalErrors) {
97 // handle error raised at early parse time
98 // autoloader not available & built-in classes not resolvable
99 if (!class_exists('stdClass', FALSE)) {
100 $message = 'PHP ' . $errorLevels[$errorLevel] . ': ' . $errorMessage . ' in ' . basename($errorFile) .
101 'line ' . $errorLine;
102 die($message);
103 }
104 // We need to manually require the exception classes in case
105 // the autoloader is not available at this point yet.
106 // @see http://forge.typo3.org/issues/23444
107 if (!class_exists('TYPO3\\CMS\\Core\\Error\\Exception', FALSE)) {
108 require_once PATH_site . 'typo3/sysext/core/Classes/Exception.php';
109 require_once PATH_site . 'typo3/sysext/core/Classes/Error/Exception.php';
110 }
111 throw new \TYPO3\CMS\Core\Error\Exception($message, 1);
112 } else {
113 switch ($errorLevel) {
114 case E_USER_ERROR:
115
116 case E_RECOVERABLE_ERROR:
117 $severity = 2;
118 break;
119 case E_USER_WARNING:
120
121 case E_WARNING:
122 $severity = 1;
123 break;
124 default:
125 $severity = 0;
126 }
127 $logTitle = 'Core: Error handler (' . TYPO3_MODE . ')';
128 // Write error message to the configured syslogs,
129 // see: $TYPO3_CONF_VARS['SYS']['systemLog']
130 if ($errorLevel & $GLOBALS['TYPO3_CONF_VARS']['SYS']['syslogErrorReporting']) {
131 GeneralUtility::sysLog($message, $logTitle, $severity);
132 }
133 // Write error message to devlog extension(s),
134 // see: $TYPO3_CONF_VARS['SYS']['enable_errorDLOG']
135 if (TYPO3_ERROR_DLOG) {
136 GeneralUtility::devLog($message, $logTitle, $severity + 1);
137 }
138 // Write error message to TSlog (admin panel)
139 if (is_object($GLOBALS['TT'])) {
140 $GLOBALS['TT']->setTSlogMessage($logTitle . ': ' . $message, $severity + 1);
141 }
142 // Write error message to sys_log table (ext: belog, Tools->Log)
143 if ($errorLevel & $GLOBALS['TYPO3_CONF_VARS']['SYS']['belogErrorReporting']) {
144 // Silently catch in case an error occurs before a database connection exists,
145 // but DatabaseConnection fails to connect.
146 try {
147 $this->writeLog($logTitle . ': ' . $message, $severity);
148 } catch (\Exception $e) {
149 }
150 }
151 // Add error message to the flashmessageQueue
152 if (defined('TYPO3_ERRORHANDLER_MODE') && TYPO3_ERRORHANDLER_MODE == 'debug') {
153 $flashMessage = GeneralUtility::makeInstance(
154 'TYPO3\\CMS\\Core\\Messaging\\FlashMessage',
155 $message,
156 'PHP ' . $errorLevels[$errorLevel],
157 $severity
158 );
159 /** @var $flashMessageService \TYPO3\CMS\Core\Messaging\FlashMessageService */
160 $flashMessageService = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Messaging\\FlashMessageService');
161 /** @var $defaultFlashMessageQueue \TYPO3\CMS\Core\Messaging\FlashMessageQueue */
162 $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
163 $defaultFlashMessageQueue->enqueue($flashMessage);
164 }
165 }
166 // Don't execute PHP internal error handler
167 return TRUE;
168 }
169
170 /**
171 * Writes an error in the sys_log table
172 *
173 * @param string $logMessage Default text that follows the message (in english!).
174 * @param int $severity The eror level of the message (0 = OK, 1 = warning, 2 = error)
175 * @return void
176 */
177 protected function writeLog($logMessage, $severity) {
178 if (is_object($GLOBALS['TYPO3_DB']) && $GLOBALS['TYPO3_DB']->isConnected()) {
179 $userId = 0;
180 $workspace = 0;
181 if (is_object($GLOBALS['BE_USER'])) {
182 if (isset($GLOBALS['BE_USER']->user['uid'])) {
183 $userId = $GLOBALS['BE_USER']->user['uid'];
184 }
185 if (isset($GLOBALS['BE_USER']->workspace)) {
186 $workspace = $GLOBALS['BE_USER']->workspace;
187 }
188 }
189 $fields_values = array(
190 'userid' => $userId,
191 'type' => 5,
192 'action' => 0,
193 'error' => $severity,
194 'details_nr' => 0,
195 'details' => $logMessage,
196 'IP' => GeneralUtility::getIndpEnv('REMOTE_ADDR'),
197 'tstamp' => $GLOBALS['EXEC_TIME'],
198 'workspace' => $workspace
199 );
200 $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_log', $fields_values);
201 }
202 }
203
204 }