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

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