Your IP : 3.149.243.136
<?php
namespace Bitrix\Main\Diag;
use Bitrix\Main;
class ExceptionHandler
{
private $debug = false;
private $handledErrorsTypes;
private $exceptionErrorsTypes;
private $catchOverflowMemory = false;
private $memoryReserveLimit = 65536;
private $memoryReserve;
private $ignoreSilence = false;
private $assertionThrowsException = true;
private $assertionErrorType = E_USER_ERROR;
/**
* @var ExceptionHandlerLog
*/
private $handlerLog = null;
private $handlerLogCreator = null;
/**
* @var IExceptionHandlerOutput
*/
private $handlerOutput = null;
private $handlerOutputCreator = null;
private $isInitialized = false;
/**
* ExceptionHandler constructor.
*/
public function __construct()
{
$this->handledErrorsTypes = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR;
$this->exceptionErrorsTypes = E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR;
}
/**
* Sets debug mode.
* Should be used for development install.
*
* @param boolean $debug If true errors will be displayed in html output. If false most errors will be suppressed.
*
* @return void
*/
public function setDebugMode($debug)
{
$this->debug = $debug;
}
/**
* Whenever to try catch and report memory overflows errors or not.
*
* @param boolean $catchOverflowMemory If true memory overflow errors will be handled.
*
* @return void
*/
public function setOverflowMemoryCatching($catchOverflowMemory)
{
$this->catchOverflowMemory = $catchOverflowMemory;
}
/**
* Sets error types to be handled.
*
* @param integer $handledErrorsTypes Bitmask of error types.
*
* @return void
* @see http://php.net/manual/en/errorfunc.constants.php
*/
public function setHandledErrorsTypes($handledErrorsTypes)
{
$this->handledErrorsTypes = $handledErrorsTypes;
}
/**
* Sets assertion types to be handled.
*
* @param integer $assertionErrorType Bitmask of assertion types.
*
* @return void
* @see http://php.net/manual/en/errorfunc.constants.php
*/
public function setAssertionErrorType($assertionErrorType)
{
$this->assertionErrorType = $assertionErrorType;
}
/**
* Whenever to throw an exception on assertion or not.
*
* @param boolean $assertionThrowsException If true an assertion will throw exception.
*
* @return void
*/
public function setAssertionThrowsException($assertionThrowsException)
{
$this->assertionThrowsException = $assertionThrowsException;
}
/**
* Sets which errors will raise an exception.
*
* @param integer $errorTypesException Bitmask of error types.
*
* @return void
* @see http://php.net/manual/en/errorfunc.constants.php
*/
public function setExceptionErrorsTypes($errorTypesException)
{
$this->exceptionErrorsTypes = $errorTypesException;
}
/**
* Whenever to ignore error_reporting() == 0 or not.
*
* @param boolean $ignoreSilence If true then error_reporting()==0 will be ignored.
*
* @return void
*/
public function setIgnoreSilence($ignoreSilence)
{
$this->ignoreSilence = $ignoreSilence;
}
/**
* Sets logger object to use for log writing.
*
* @param \Bitrix\Main\Diag\ExceptionHandlerLog $handlerLog Logger object.
*
* @return void
*/
public function setHandlerLog(\Bitrix\Main\Diag\ExceptionHandlerLog $handlerLog = null)
{
$this->handlerLog = $handlerLog;
}
/**
* Sets an object used for error message display to user.
*
* @param \Bitrix\Main\Diag\IExceptionHandlerOutput $handlerOutput Object will display errors to user.
*
* @return void
*/
public function setHandlerOutput(\Bitrix\Main\Diag\IExceptionHandlerOutput $handlerOutput)
{
$this->handlerOutput = $handlerOutput;
}
/**
* Adjusts PHP for error handling.
*
* @return void
*/
protected function initializeEnvironment()
{
if ($this->debug)
{
error_reporting($this->handledErrorsTypes);
@ini_set('display_errors', 'On');
@ini_set('display_startup_errors', 'On');
@ini_set('report_memleaks', 'On');
}
else
{
error_reporting(E_ERROR | E_PARSE);
}
}
/**
* Returns an object used for error message display to user.
*
* @return IExceptionHandlerOutput|null
*/
protected function getHandlerOutput()
{
if ($this->handlerOutput === null)
{
$h = $this->handlerOutputCreator;
if (is_callable($h))
$this->handlerOutput = call_user_func_array($h, array());
}
return $this->handlerOutput;
}
/**
* Returns an object for error message writing to log.
*
* @return ExceptionHandlerLog|null
*/
protected function getHandlerLog()
{
if ($this->handlerLog === null)
{
$h = $this->handlerLogCreator;
if (is_callable($h))
$this->handlerLog = call_user_func_array($h, array());
}
return $this->handlerLog;
}
/**
* Initializes error handling.
* Must be called after the object creation.
*
* @param callable $exceptionHandlerOutputCreator Function to return an object for error message formatting.
* @param callable|null $exceptionHandlerLogCreator Function to return an object for log writing.
*
* @return void
*/
public function initialize($exceptionHandlerOutputCreator, $exceptionHandlerLogCreator = null)
{
if ($this->isInitialized)
return;
$this->initializeEnvironment();
$this->handlerOutputCreator = $exceptionHandlerOutputCreator;
$this->handlerLogCreator = $exceptionHandlerLogCreator;
if ($this->catchOverflowMemory)
{
$this->memoryReserve = str_repeat('b', $this->memoryReserveLimit);
}
set_error_handler(array($this, "handleError"), $this->handledErrorsTypes);
set_exception_handler(array($this, "handleException"));
register_shutdown_function(array($this, "handleFatalError"));
if ($this->debug)
{
assert_options(ASSERT_ACTIVE, 1);
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_BAIL, 0);
assert_options(ASSERT_QUIET_EVAL, 0);
assert_options(ASSERT_CALLBACK, array($this, "handleAssertion"));
}
else
{
assert_options(ASSERT_ACTIVE, 0);
}
$this->isInitialized = true;
}
/**
* Writes exception information into log, displays it to user and terminates with die().
*
* @param \Exception|\Error $exception Exception object.
*
* @return void
* @see \Bitrix\Main\Diag\ExceptionHandler::writeToLog
* @see \Bitrix\Main\Diag\ExceptionHandler::initialize
*/
public function handleException($exception)
{
$this->writeToLog($exception, ExceptionHandlerLog::UNCAUGHT_EXCEPTION);
$out = $this->getHandlerOutput();
$out->renderExceptionMessage($exception, $this->debug);
die();
}
/**
* Creates and exception object from its arguments.
* Throws it if $code matches exception mask or writes it into log.
*
* @param integer $code Error code.
* @param string $message Error message.
* @param string $file File where error has occurred.
* @param integer $line File line number where error has occurred.
*
* @return true
* @throws \ErrorException
* @see \Bitrix\Main\Diag\ExceptionHandler::setExceptionErrorsTypes
*/
public function handleError($code, $message, $file, $line)
{
$exception = new \ErrorException($message, 0, $code, $file, $line);
if ((error_reporting() === 0) && !$this->ignoreSilence)
{
return true;
}
if ($code & $this->exceptionErrorsTypes)
{
throw $exception;
}
else
{
$this->writeToLog($exception, ExceptionHandlerLog::LOW_PRIORITY_ERROR);
return true;
}
}
/**
* Creates and exception object from its arguments.
* Throws it if assertion set to raise exception (which is by default) or writes it to log.
*
* @param string $file File where error has occurred.
* @param integer $line File line number where error has occurred.
* @param string $message Error message.
*
* @return void
* @throws \ErrorException
* @see \Bitrix\Main\Diag\ExceptionHandler::setAssertionThrowsException
*/
public function handleAssertion($file, $line, $message)
{
$exception = new \ErrorException($message, 0, $this->assertionErrorType, $file, $line);
if ($this->assertionThrowsException)
{
throw $exception;
}
else
{
$this->writeToLog($exception, ExceptionHandlerLog::ASSERTION);
return;
}
}
/**
* Gets error information from error_get_last() function.
* Checks if type for certain error types and writes it to log.
*
* @return void
* @see error_get_last
* @see \Bitrix\Main\Diag\ExceptionHandler::setHandledErrorsTypes
*/
public function handleFatalError()
{
unset($this->memoryReserve);
if ($error = error_get_last())
{
if (($error['type'] & (E_ERROR | E_USER_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_RECOVERABLE_ERROR)))
{
if(($error['type'] & $this->handledErrorsTypes))
{
$exception = new \ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']);
$this->writeToLog($exception, ExceptionHandlerLog::FATAL);
}
}
}
}
/**
* Writes an exception information to log.
*
* @param \Exception $exception Exception object.
* @param integer|null $logType See ExceptionHandlerLog class constants.
*
* @return void
* @see \Bitrix\Main\Diag\ExceptionHandler::initialize
*/
public function writeToLog($exception, $logType = null)
{
$log = $this->getHandlerLog();
if ($log !== null)
$log->write($exception, $logType);
}
}