Current File : //home/strato/chroot/opt/RZphp72/includes/Gtk2/ExceptionDump.php |
<?php
require_once 'Gtk2/ExceptionDump/InfoBox.php';
require_once 'Gtk2/ExceptionDump/Stack.php';
/**
* Displays an Exception in a GtkWindow.
* Supports PHP Exceptions and PEAR_Error objects.
*
* @example
* $error = new PEAR_Error();
* Gtk2_ExceptionDump::display($error);
*
* @example
* Gtk2_ExceptionDump::setupExceptionHandler();
* throw new Exception('Exception!');
*
* @example
* Gtk2_ExceptionDump::setupPearErrorHandler();
* PEAR::raiserError('Error!');
*
* @example
* Gtk2_ExceptionDump::setupPhpErrorHandler();
* trigger_error('Oops! A php error', E_USER_ERROR);
*
* @category Gtk2
* @package Gtk2_ExceptionDump
* @author Christian Weiske <cweiske@php.net>
* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1
* @version CVS: $Id$
* @link http://pear.php.net/package/Gtk2_ExceptionDump
*/
class Gtk2_ExceptionDump extends GtkWindow
{
/**
* The exception that is shown.
* PEAR_Error or Exception.
* @var mixed
*/
protected $exception = null;
/**
* Creates a new ExceptionDump window.
* You still need to show it and run the main loop.
*
* The window can be closed, quitting the main loop and
* continuing running the program OR quitting the script
* with exit status 253
*
* @param mixed $exception Exception or PEAR_Error object
* @param string $title The title for the window
*/
public function __construct($exception, $title = null)
{
parent::__construct();
$this->buildDialog();
if ($exception !== null) {
$this->setException($exception, $title);
}
}//public function __construct($exception, $title = null)
/**
* Creates a new ExceptionDump window, displays it
* and starts its own main loop.
* The window can be closed, quitting the main loop and
* continuing running the program OR quitting the script
* with exit status 253
*
* @param mixed $exception Exception or PEAR_Error object
* @param string $title (optional) The title for the window
*/
public static function display($exception, $title = null)
{
$ed = new Gtk2_ExceptionDump($exception, $title);
$ed->show_all();
Gtk::main();
}//public static function display($exception = null, $title = null)
/**
* Sets up the PHP exception handler to call
* Gtk2_ExceptionDump::display() if an exception occurs.
*
* This is the safest way to handle *all* uncaught exceptions
* with Gtk2_ExceptionDump. It handles "real" exceptions only,
* not PEAR_Errors.
*
* Note that the "continue" button doesn't work anymore, since
* the exceptions are handled out of all user php code.
*/
public static function setupExceptionHandler()
{
set_exception_handler(array('Gtk2_ExceptionDump', 'display'));
}//public static function setupExceptionHandler()
/**
* Sets up the PEAR Exception handler to call
* Gtk2_ExceptionDump::display() if an PEAR_Error occurs.
*
* While this catches *all* PEAR_Errors, it also catches
* the ones that are handled by php scripts.
*/
public static function setupPearErrorHandler()
{
require_once 'PEAR.php';
PEAR::setErrorHandling(PEAR_ERROR_CALLBACK,
array('Gtk2_ExceptionDump', 'display'));
}//public static function setupPearErrorHandler()
/**
* Sets the php error handler to use Gtk2_ExceptionDump.
* All catchable PHP errors are displayed here.
*
* Not all errors are handled, only the ones
* defined by error_reporting.
*/
public static function setupPhpErrorHandler()
{
set_error_handler(array('Gtk2_ExceptionDump', 'handlePhpError'),
error_reporting());
}//public static function setupPhpErrorHandler()
/**
* Sets up that all errors/exceptions are handled with
* Gtk2_ExceptionDump.
* Calls setupExceptionHandler() and setupPearErrorHandler()
* internally.
*/
public static function setupAllHandlers()
{
self::setupExceptionHandler();
self::setupPearErrorHandler();
self::setupPhpErrorHandler();
}//public static function setupAllHandlers()
/**
* Use Gtk2_ExceptionDump to display a PHP error.
*
* @param int $errno Contains the level of the error raised
* @param string $errstr Error message
* @param string $errfile Filename that the error was raised in
* @param int $errline Line number the error was raised at
* @param array $errcontext Array that points to the active symbol
* table at the point the error occurred. In
* other words, errcontext will contain an
* array of every variable that existed in
* the scope the error was triggered in.
*/
public static function handlePhpError($errno, $errstr, $errfile = null,
$errline = null , $errcontext = array())
{
//this occurs when using @ to silence errors
if (error_reporting() == 0) {
return;
}
$errorNames = array(
E_ERROR => 'E_ERROR',
E_WARNING => 'E_WARNING',
E_PARSE => 'E_PARSE',
E_NOTICE => 'E_NOTICE',
E_CORE_ERROR => 'E_CORE_ERROR',
E_CORE_WARNING => 'E_CORE_WARNING',
E_COMPILE_ERROR => 'E_COMPILE_ERROR',
E_COMPILE_WARNING => 'E_COMPILE_WARNING',
E_USER_ERROR => 'E_USER_ERROR',
E_USER_WARNING => 'E_USER_WARNING',
E_USER_NOTICE => 'E_USER_NOTICE',
E_STRICT => 'E_STRICT'
);
Gtk2_ExceptionDump::display(
new Exception($errstr . "\r\n\r\n" . $errfile . '#' . $errline, $errno),
'PHP Error: ' . $errorNames[$errno]
);
}//public static function handlePhpError($errno, $errstr, $errfile = null,
// $errline = null , $errcontext = array())
/**
* Set the exception object.
*
* @param PEAR_Error|Exception $exception Exception to display
* @param mixed $title Window title to use
*/
public function setException($exception, $title = null)
{
if ($exception instanceof PEAR_Error || $exception instanceof Exception) {
$this->exception = $exception;
$this->stack->setException($exception);
$this->infobox->setException($exception);
$this->setTitle($exception, $title);
} else {
$this->buildError($exception);
$this->set_title('No error occured');
}
}//public function setException($exception, $title = null)
/**
* Sets the title of the window.
*
* @param PEAR_Error|Exception $exception Exception to display
* @param string $title Window title to use
*/
protected function setTitle($exception, $title)
{
if ($title === null) {
$class = get_class($exception);
if ($exception instanceof PEAR_Error) {
if ($class == 'PEAR_Error') {
$title = 'A PEAR_Error was thrown';
} else {
$title = 'A "' . $class . '" PEAR_Error was thrown';
}
} else {
if ($class == 'Exception') {
$title = 'An Exception was thrown' ;
} else {
$title = 'An "' . $class . '" exception was thrown' ;
}
}
}
$this->set_title($title);
}//protected function setTitle($exception, $title)
/**
* Creates the dialog widgets.
*/
protected function buildDialog()
{
$this->destroySignal
= $this->connect_simple('destroy', array($this, 'onQuit'));
$this->set_default_size(700, 300);
$this->infobox = new Gtk2_ExceptionDump_InfoBox();
$this->stack = new Gtk2_ExceptionDump_Stack();
$scrStack = new GtkScrolledWindow();
$scrStack->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
$scrStack->add($this->stack);
$vbox = new GtkVBox();
$vbox->pack_start($this->infobox, false);
$vbox->pack_start($scrStack);
$hbox = new GtkHbox();
$vbox->pack_end($hbox, false);
$hbox->pack_start($this->buildActionButtonBox(), false);
$hbox->pack_end($this->buildContinuationButtonBox(), false);
$this->add($vbox);
}//protected function buildDialog($title)
/**
* Returns the box with the Execute/Continue buttons.
*
* @return GtkButtonBox The button box.
*/
protected function buildContinuationButtonBox()
{
$buttons = new GtkHButtonBox();
$buttons->set_layout(Gtk::BUTTONBOX_END);
$quit = GtkButton::new_from_stock(Gtk::STOCK_QUIT);
$quit->connect_simple('clicked', array($this, 'onQuit'));
$quit->set_flags($quit->flags() + Gtk::CAN_DEFAULT);
$buttons->add($quit);
//FIXME: register own stock icon
$continue = GtkButton::new_from_stock(Gtk::STOCK_EXECUTE);
$continue->set_label('Con_tinue');
$continue->connect_simple('clicked', array($this, 'onContinue'));
$buttons->add($continue);
return $buttons;
}//protected function buildContinuationButtonBox()
/**
* Returns the box with the Copy button.
*
* @return GtkButtonBox The button box.
*/
protected function buildActionButtonBox()
{
$buttons = new GtkHButtonBox();
$buttons->set_layout(Gtk::BUTTONBOX_END);
$copy = GtkButton::new_from_stock(Gtk::STOCK_COPY);
$copy->connect_simple('clicked', array($this, 'onCopy'));
$buttons->add($copy);
return $buttons;
}//protected function buildActionButtonBox()
/**
* Creates the error message that the object isn't an
* Exception or a PEAR_Error.
*
* @param mixed $exception Some variable that isn't an Exception
* or a PEAR_Error object
*/
protected function buildError($exception)
{
$this->infobox->setMessage(
'Gtk2_ExceptionDump has been called with'
. ' an variable of type "' . gettype($exception) . '".' . "\n"
. 'It cannot be displayed since it is not'
. ' an Exception or an PEAR_Error object.',
'Usually, this occurs when the programmer didn\'t check' . "\n"
. 'what type of variable is passed to Gtk2_ExceptionDump.' . "\n"
. 'File a bug report'
);
$this->stack->setException(new Exception(), 3);
}//protected function buildError($exception)
/**
* Quits the php script with exit status 253.
*/
public function onQuit()
{
exit(253);
}//public function onQuit()
/**
* Closes the window, quits the main loop
* and continues normal script execution.
*/
public function onContinue()
{
//block the destroy signal, since it would call onQuit()
$this->block($this->destroySignal);
$this->destroy();
//close this level
Gtk::main_quit();
}//public function onContinue()
/**
* Copies the exception/error as string to the clipboard.
*/
public function onCopy()
{
$cb = GtkClipboard::get(Gdk::atom_intern('CLIPBOARD', false));
$cb->set_text(self::getExceptionAsString($this->exception));
}//public function onCopy()
/**
* Generates a string representation of the exception.
*
* @param mixed $exception The exception to convert
*/
protected static function getExceptionAsString($exception)
{
$s = array(
get_class($exception),
'Message:',
' ' . $exception->getMessage()
);
if ($exception instanceof PEAR_Error) {
$s[] = 'User info';
$s[] = ' ' . $exception->getUserInfo();
}
$func = $exception instanceof PEAR_Error ? 'getBacktrace' : 'getTrace';
$trace = $exception->$func();
$s[] = 'Backtrace:';
foreach ($trace as $id => $step) {
if (count($step['args']) == 0) {
$function = $step['function'] . '()';
} else {
$function = $step['function'] . '(...)';
}
if (isset($step['class'])) {
if ($step['class'] == $step['function']) {
$function = 'new ' . $function;
} else {
$function = $step['class'] . $step['type'] . $function;
}
}
if (isset($step['file'])) {
$file = $step['file'] . '#' . $step['line'];
} else {
$file = 'unknown';
}
$s[] = ' ' . $function. ' at ' . $file;
foreach ($step['args'] as $arg) {
if (gettype($arg) == 'object') {
$arg = get_class($arg) . ' - ' . (string)$arg;
} else {
$arg = gettype($arg) . '(' . $arg . ')';
}
$s[] .= ' ' . $arg;
}
}
$s[] = '';//newline
return implode("\r\n", $s);
}//protected static function getExceptionAsString($exception)
}//class Gtk2_ExceptionDump extends GtkWindow
?>