Gtk2_ExceptionDump
[ class tree: Gtk2_ExceptionDump ] [ index: Gtk2_ExceptionDump ] [ all elements ]

Source for file ExceptionDump.php

Documentation is available at ExceptionDump.php

  1. <?php
  2. require_once 'Gtk2/ExceptionDump/InfoBox.php';
  3. require_once 'Gtk2/ExceptionDump/Stack.php';
  4.  
  5. /**
  6. * Displays an Exception in a GtkWindow.
  7. * Supports PHP Exceptions and PEAR_Error objects.
  8. *
  9. @example
  10. *  $error = new PEAR_Error();
  11. *  Gtk2_ExceptionDump::display($error);
  12. *
  13. @example
  14. *  Gtk2_ExceptionDump::setupExceptionHandler();
  15. *  throw new Exception('Exception!');
  16. *
  17. @example
  18. *  Gtk2_ExceptionDump::setupPearErrorHandler();
  19. *  PEAR::raiserError('Error!');
  20. *
  21. @example
  22. *  Gtk2_ExceptionDump::setupPhpErrorHandler();
  23. *  trigger_error('Oops! A php error', E_USER_ERROR);
  24. *
  25. @category Gtk2
  26. @package  Gtk2_ExceptionDump
  27. @author   Christian Weiske <cweiske@php.net>
  28. @license  http://www.gnu.org/copyleft/lesser.html  LGPL License 2.1
  29. @version  CVS: $Id$
  30. @link     http://pear.php.net/package/Gtk2_ExceptionDump
  31. */
  32. class Gtk2_ExceptionDump extends GtkWindow
  33. {
  34.     /**
  35.     * The exception that is shown.
  36.     * PEAR_Error or Exception.
  37.     * @var mixed 
  38.     */
  39.     protected $exception = null;
  40.  
  41.  
  42.  
  43.     /**
  44.     * Creates a new ExceptionDump window.
  45.     * You still need to show it and run the main loop.
  46.     *
  47.     * The window can be closed, quitting the main loop and
  48.     * continuing running the program OR quitting the script
  49.     * with exit status 253
  50.     *
  51.     * @param mixed  $exception Exception or PEAR_Error object
  52.     * @param string $title     The title for the window
  53.     */
  54.     public function __construct($exception$title = null)
  55.     {
  56.         parent::__construct();
  57.         $this->buildDialog();
  58.         if ($exception !== null{
  59.             $this->setException($exception$title);
  60.         }
  61.     }//public function __construct($exception, $title = null)
  62.  
  63.  
  64.  
  65.     /**
  66.     * Creates a new ExceptionDump window, displays it
  67.     * and starts its own main loop.
  68.     * The window can be closed, quitting the main loop and
  69.     * continuing running the program OR quitting the script
  70.     * with exit status 253
  71.     *
  72.     * @param mixed  $exception Exception or PEAR_Error object
  73.     * @param string $title     (optional) The title for the window
  74.     */
  75.     public static function display($exception$title = null)
  76.     {
  77.         $ed = new Gtk2_ExceptionDump($exception$title);
  78.         $ed->show_all();
  79.         Gtk::main();
  80.     }//public static function display($exception = null, $title = null)
  81.  
  82.  
  83.  
  84.     /**
  85.     * Sets up the PHP exception handler to call
  86.     * Gtk2_ExceptionDump::display() if an exception occurs.
  87.     *
  88.     * This is the safest way to handle *all* uncaught exceptions
  89.     * with Gtk2_ExceptionDump. It handles "real" exceptions only,
  90.     * not PEAR_Errors.
  91.     *
  92.     * Note that the "continue" button doesn't work anymore, since
  93.     * the exceptions are handled out of all user php code.
  94.     */
  95.     public static function setupExceptionHandler()
  96.     {
  97.         set_exception_handler(array('Gtk2_ExceptionDump''display'));
  98.     }//public static function setupExceptionHandler()
  99.  
  100.  
  101.  
  102.     /**
  103.     * Sets up the PEAR Exception handler to call
  104.     * Gtk2_ExceptionDump::display() if an PEAR_Error occurs.
  105.     *
  106.     * While this catches *all* PEAR_Errors, it also catches
  107.     * the ones that are handled by php scripts.
  108.     */
  109.     public static function setupPearErrorHandler()
  110.     {
  111.         require_once 'PEAR.php';
  112.         PEAR::setErrorHandling(PEAR_ERROR_CALLBACK,
  113.             array('Gtk2_ExceptionDump''display'));
  114.     }//public static function setupPearErrorHandler()
  115.  
  116.  
  117.  
  118.     /**
  119.     * Sets the php error handler to use Gtk2_ExceptionDump.
  120.     * All catchable PHP errors are displayed here.
  121.     *
  122.     * Not all errors are handled, only the ones
  123.     * defined by error_reporting.
  124.     */
  125.     public static function setupPhpErrorHandler()
  126.     {
  127.         set_error_handler(array('Gtk2_ExceptionDump''handlePhpError'),
  128.             error_reporting());
  129.     }//public static function setupPhpErrorHandler()
  130.  
  131.  
  132.  
  133.     /**
  134.     * Sets up that all errors/exceptions are handled with
  135.     * Gtk2_ExceptionDump.
  136.     * Calls setupExceptionHandler() and setupPearErrorHandler()
  137.     * internally.
  138.     */
  139.     public static function setupAllHandlers()
  140.     {
  141.         self::setupExceptionHandler();
  142.         self::setupPearErrorHandler();
  143.         self::setupPhpErrorHandler();
  144.     }//public static function setupAllHandlers()
  145.  
  146.  
  147.  
  148.     /**
  149.     * Use Gtk2_ExceptionDump to display a PHP error.
  150.     *
  151.     * @param int    $errno      Contains the level of the error raised
  152.     * @param string $errstr     Error message
  153.     * @param string $errfile    Filename that the error was raised in
  154.     * @param int    $errline    Line number the error was raised at
  155.     * @param array  $errcontext Array that points to the active symbol
  156.     *                            table at the point the error occurred. In
  157.     *                            other words, errcontext will contain an
  158.     *                            array of every variable that existed in
  159.     *                            the scope the error was triggered in.
  160.     */
  161.     public static function handlePhpError($errno$errstr$errfile = null,
  162.                                      $errline = null $errcontext = array())
  163.     {
  164.         //this occurs when using @ to silence errors
  165.         if (error_reporting(== 0{
  166.             return;
  167.         }
  168.  
  169.         $errorNames = array(
  170.             E_ERROR             => 'E_ERROR',
  171.             E_WARNING           => 'E_WARNING',
  172.             E_PARSE             => 'E_PARSE',
  173.             E_NOTICE            => 'E_NOTICE',
  174.             E_CORE_ERROR        => 'E_CORE_ERROR',
  175.             E_CORE_WARNING      => 'E_CORE_WARNING',
  176.             E_COMPILE_ERROR     => 'E_COMPILE_ERROR',
  177.             E_COMPILE_WARNING   => 'E_COMPILE_WARNING',
  178.             E_USER_ERROR        => 'E_USER_ERROR',
  179.             E_USER_WARNING      => 'E_USER_WARNING',
  180.             E_USER_NOTICE       => 'E_USER_NOTICE',
  181.             E_STRICT            => 'E_STRICT'
  182.         );
  183.         Gtk2_ExceptionDump::display(
  184.             new Exception($errstr "\r\n\r\n" $errfile '#' $errline$errno),
  185.             'PHP Error: ' $errorNames[$errno]
  186.         );
  187.     }//public static function handlePhpError($errno, $errstr, $errfile = null,
  188.      // $errline = null , $errcontext = array())
  189.  
  190.  
  191.  
  192.     /**
  193.     * Set the exception object.
  194.     *
  195.     * @param PEAR_Error|Exception$exception Exception to display
  196.     * @param mixed                $title     Window title to use
  197.     */
  198.     public function setException($exception$title = null)
  199.     {
  200.         if ($exception instanceof PEAR_Error || $exception instanceof Exception{
  201.             $this->exception = $exception;
  202.             $this->stack->setException($exception);
  203.             $this->infobox->setException($exception);
  204.             $this->setTitle($exception$title);
  205.         else {
  206.             $this->buildError($exception);
  207.             $this->set_title('No error occured');
  208.         }
  209.  
  210.     }//public function setException($exception, $title = null)
  211.  
  212.  
  213.  
  214.     /**
  215.     * Sets the title of the window.
  216.     *
  217.     * @param PEAR_Error|Exception$exception Exception to display
  218.     * @param string               $title     Window title to use
  219.     */
  220.     protected function setTitle($exception$title)
  221.     {
  222.         if ($title === null{
  223.             $class get_class($exception);
  224.             if ($exception instanceof PEAR_Error{
  225.                 if ($class == 'PEAR_Error'{
  226.                     $title 'A PEAR_Error was thrown';
  227.                 else {
  228.                     $title 'A "' $class '" PEAR_Error was thrown';
  229.                 }
  230.             else {
  231.                 if ($class == 'Exception'{
  232.                     $title 'An Exception was thrown' ;
  233.                 else {
  234.                     $title 'An "' $class '" exception was thrown' ;
  235.                 }
  236.             }
  237.         }
  238.         $this->set_title($title);
  239.     }//protected function setTitle($exception, $title)
  240.  
  241.  
  242.  
  243.     /**
  244.     * Creates the dialog widgets.
  245.     */
  246.     protected function buildDialog()
  247.     {
  248.         $this->destroySignal
  249.             = $this->connect_simple('destroy'array($this'onQuit'));
  250.         $this->set_default_size(700300);
  251.  
  252.         $this->infobox = new Gtk2_ExceptionDump_InfoBox();
  253.  
  254.         $this->stack = new Gtk2_ExceptionDump_Stack();
  255.         $scrStack    = new GtkScrolledWindow();
  256.         $scrStack->set_policy(Gtk::POLICY_AUTOMATICGtk::POLICY_AUTOMATIC);
  257.         $scrStack->add($this->stack);
  258.  
  259.         $vbox = new GtkVBox();
  260.         $vbox->pack_start($this->infoboxfalse);
  261.         $vbox->pack_start($scrStack);
  262.  
  263.         $hbox = new GtkHbox();
  264.         $vbox->pack_end($hboxfalse);
  265.  
  266.         $hbox->pack_start($this->buildActionButtonBox()false);
  267.         $hbox->pack_end($this->buildContinuationButtonBox()false);
  268.  
  269.         $this->add($vbox);
  270.     }//protected function buildDialog($title)
  271.  
  272.  
  273.  
  274.     /**
  275.     * Returns the box with the Execute/Continue buttons.
  276.     *
  277.     * @return GtkButtonBox The button box.
  278.     */
  279.     protected function buildContinuationButtonBox()
  280.     {
  281.         $buttons = new GtkHButtonBox();
  282.         $buttons->set_layout(Gtk::BUTTONBOX_END);
  283.  
  284.         $quit = GtkButton::new_from_stock(Gtk::STOCK_QUIT);
  285.         $quit->connect_simple('clicked'array($this'onQuit'));
  286.         $quit->set_flags($quit->flags(+ Gtk::CAN_DEFAULT);
  287.         $buttons->add($quit);
  288.  
  289.         //FIXME: register own stock icon
  290.         $continue = GtkButton::new_from_stock(Gtk::STOCK_EXECUTE);
  291.         $continue->set_label('Con_tinue');
  292.         $continue->connect_simple('clicked'array($this'onContinue'));
  293.         $buttons->add($continue);
  294.  
  295.         return $buttons;
  296.     }//protected function buildContinuationButtonBox()
  297.  
  298.  
  299.  
  300.     /**
  301.     * Returns the box with the Copy button.
  302.     *
  303.     * @return GtkButtonBox The button box.
  304.     */
  305.     protected function buildActionButtonBox()
  306.     {
  307.         $buttons = new GtkHButtonBox();
  308.         $buttons->set_layout(Gtk::BUTTONBOX_END);
  309.  
  310.         $copy = GtkButton::new_from_stock(Gtk::STOCK_COPY);
  311.         $copy->connect_simple('clicked'array($this'onCopy'));
  312.         $buttons->add($copy);
  313.  
  314.         return $buttons;
  315.     }//protected function buildActionButtonBox()
  316.  
  317.  
  318.  
  319.     /**
  320.     * Creates the error message that the object isn't an
  321.     * Exception or a PEAR_Error.
  322.     *
  323.     * @param mixed $exception Some variable that isn't an Exception
  324.     *                          or a PEAR_Error object
  325.     */
  326.     protected function buildError($exception)
  327.     {
  328.         $this->infobox->setMessage(
  329.             'Gtk2_ExceptionDump has been called with'
  330.             . ' an variable of type "' gettype($exception'".' "\n"
  331.             . 'It cannot be displayed since it is not'
  332.             . ' an Exception or an PEAR_Error object.',
  333.  
  334.             'Usually, this occurs when the programmer didn\'t check' "\n"
  335.             . 'what type of variable is passed to Gtk2_ExceptionDump.' "\n"
  336.             . 'File a bug report'
  337.         );
  338.  
  339.         $this->stack->setException(new Exception()3);
  340.     }//protected function buildError($exception)
  341.  
  342.  
  343.  
  344.     /**
  345.     * Quits the php script with exit status 253.
  346.     */
  347.     public function onQuit()
  348.     {
  349.         exit(253);
  350.     }//public function onQuit()
  351.  
  352.  
  353.  
  354.     /**
  355.     * Closes the window, quits the main loop
  356.     * and continues normal script execution.
  357.     */
  358.     public function onContinue()
  359.     {
  360.         //block the destroy signal, since it would call onQuit()
  361.         $this->block($this->destroySignal);
  362.         $this->destroy();
  363.         //close this level
  364.         Gtk::main_quit();
  365.     }//public function onContinue()
  366.  
  367.  
  368.  
  369.     /**
  370.     * Copies the exception/error as string to the clipboard.
  371.     */
  372.     public function onCopy()
  373.     {
  374.         $cb = GtkClipboard::get(Gdk::atom_intern('CLIPBOARD'false));
  375.         $cb->set_text(self::getExceptionAsString($this->exception));
  376.     }//public function onCopy()
  377.  
  378.  
  379.  
  380.     /**
  381.     * Generates a string representation of the exception.
  382.     *
  383.     * @param mixed $exception The exception to convert
  384.     */
  385.     protected static function getExceptionAsString($exception)
  386.     {
  387.         $s = array(
  388.             get_class($exception),
  389.             'Message:',
  390.             ' ' $exception->getMessage()
  391.         );
  392.         if ($exception instanceof PEAR_Error{
  393.             $s['User info';
  394.             $s[' ' $exception->getUserInfo();
  395.         }
  396.  
  397.         $func  $exception instanceof PEAR_Error ? 'getBacktrace' 'getTrace';
  398.         $trace $exception->$func();
  399.         $s[]   'Backtrace:';
  400.         foreach ($trace as $id => $step{
  401.             if (count($step['args']== 0{
  402.                 $function $step['function''()';
  403.             else {
  404.                 $function $step['function''(...)';
  405.             }
  406.  
  407.             if (isset($step['class'])) {
  408.                 if ($step['class'== $step['function']{
  409.                     $function 'new ' $function;
  410.                 else {
  411.                     $function $step['class'$step['type'$function;
  412.                 }
  413.             }
  414.  
  415.             if (isset($step['file'])) {
  416.                 $file $step['file''#' $step['line'];
  417.             else {
  418.                 $file 'unknown';
  419.             }
  420.  
  421.             $s[' ' $function' at ' $file;
  422.  
  423.  
  424.             foreach ($step['args'as $arg{
  425.                 if (gettype($arg== 'object'{
  426.                     $arg get_class($arg' - ' . (string)$arg;
  427.                 else {
  428.                     $arg gettype($arg'(' $arg ')';
  429.                 }
  430.                 $s[.= '  ' $arg;
  431.             }
  432.         }
  433.  
  434.         $s['';//newline
  435.  
  436.         return implode("\r\n"$s);
  437.     }//protected static function getExceptionAsString($exception)
  438.  
  439. }//class Gtk2_ExceptionDump extends GtkWindow
  440. ?>

Documentation generated on Mon, 11 Mar 2019 15:55:05 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.