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.         //this occurs when using @ to silence errors
  157.         if (error_reporting(== 0{
  158.             return;
  159.         }
  160.  
  161.         $errorNames = array(
  162.             E_ERROR             => 'E_ERROR',
  163.             E_WARNING           => 'E_WARNING',
  164.             E_PARSE             => 'E_PARSE',
  165.             E_NOTICE            => 'E_NOTICE',
  166.             E_CORE_ERROR        => 'E_CORE_ERROR',
  167.             E_CORE_WARNING      => 'E_CORE_WARNING',
  168.             E_COMPILE_ERROR     => 'E_COMPILE_ERROR',
  169.             E_COMPILE_WARNING   => 'E_COMPILE_WARNING',
  170.             E_USER_ERROR        => 'E_USER_ERROR',
  171.             E_USER_WARNING      => 'E_USER_WARNING',
  172.             E_USER_NOTICE       => 'E_USER_NOTICE',
  173.             E_STRICT            => 'E_STRICT'
  174.         );
  175.         Gtk2_ExceptionDump::display(
  176.             new Exception($errstr "\r\n\r\n" $errfile '#' $errline$errno),
  177.             'PHP Error: ' $errorNames[$errno]
  178.         );
  179.     }//public static function handlePhpError($errno, $errstr, $errfile = null, $errline = null , $errcontext = array())
  180.  
  181.  
  182.  
  183.     /**
  184.     *   Set the exception object.
  185.     *
  186.     *   @param mixed    $exception  The exception to display
  187.     */
  188.     public function setException($exception$title = null)
  189.     {
  190.         if ($exception instanceof PEAR_Error || $exception instanceof Exception{
  191.             $this->exception $exception;
  192.             $this->stack->setException($exception);
  193.             $this->infobox->setException($exception);
  194.             $this->setTitle($exception$title);
  195.         else {
  196.             $this->buildError($exception);
  197.             $this->set_title('No error occured');
  198.         }
  199.  
  200.     }//public function setException($exception, $title = null)
  201.  
  202.  
  203.  
  204.     /**
  205.     *   Sets the title of the window.
  206.     *
  207.     *   @param string   $title      Window title to use
  208.     */
  209.     protected function setTitle($exception$title)
  210.     {
  211.         if ($title === null{
  212.             $class get_class($exception);
  213.             if ($exception instanceof PEAR_Error{
  214.                 if ($class == 'PEAR_Error'{
  215.                     $title 'A PEAR_Error was thrown';
  216.                 else {
  217.                     $title 'A "' $class '" PEAR_Error was thrown';
  218.                 }
  219.             else {
  220.                 if ($class == 'Exception'{
  221.                     $title 'An Exception was thrown' ;
  222.                 else {
  223.                     $title 'An "' $class '" exception was thrown' ;
  224.                 }
  225.             }
  226.         }
  227.         $this->set_title($title);
  228.     }//protected function setTitle($exception, $title)
  229.  
  230.  
  231.  
  232.     /**
  233.     *   Creates the dialog widgets.
  234.     */
  235.     protected function buildDialog()
  236.     {
  237.         $this->destroySignal $this->connect_simple('destroy'array($this'onQuit'));
  238.         $this->set_default_size(700300);
  239.  
  240.         $this->infobox = new Gtk2_ExceptionDump_InfoBox();
  241.  
  242.         $this->stack = new Gtk2_ExceptionDump_Stack();
  243.         $scrStack = new GtkScrolledWindow();
  244.         $scrStack->set_policy(Gtk::POLICY_AUTOMATICGtk::POLICY_AUTOMATIC);
  245.         $scrStack->add($this->stack);
  246.  
  247.         $vbox = new GtkVBox();
  248.         $vbox->pack_start($this->infoboxfalse);
  249.         $vbox->pack_start($scrStack);
  250.  
  251.         $hbox = new GtkHbox();
  252.         $vbox->pack_end($hboxfalse);
  253.  
  254.         $hbox->pack_start($this->buildActionButtonBox()false);
  255.         $hbox->pack_end($this->buildContinuationButtonBox()false);
  256.  
  257.         $this->add($vbox);
  258.     }//protected function buildDialog($title)
  259.  
  260.  
  261.  
  262.     /**
  263.     *   Returns the box with the Execute/Continue buttons.
  264.     *
  265.     *   @return GtkButtonBox    The button box.
  266.     */
  267.     protected function buildContinuationButtonBox()
  268.     {
  269.         $buttons = new GtkHButtonBox();
  270.         $buttons->set_layout(Gtk::BUTTONBOX_END);
  271.  
  272.         $quit     = GtkButton::new_from_stock(Gtk::STOCK_QUIT);
  273.         $quit->connect_simple('clicked'array($this'onQuit'));
  274.         $quit->set_flags($quit->flags(+ Gtk::CAN_DEFAULT);
  275.         $buttons->add($quit);
  276.  
  277.         //FIXME: register own stock icon
  278.         $continue = GtkButton::new_from_stock(Gtk::STOCK_EXECUTE);
  279.         $continue->set_label('Con_tinue');
  280.         $continue->connect_simple('clicked'array($this'onContinue'));
  281.         $buttons->add($continue);
  282.  
  283.         return $buttons;
  284.     }//protected function buildContinuationButtonBox()
  285.  
  286.  
  287.  
  288.     /**
  289.     *   Returns the box with the Copy button.
  290.     *
  291.     *   @return GtkButtonBox    The button box.
  292.     */
  293.     protected function buildActionButtonBox()
  294.     {
  295.         $buttons = new GtkHButtonBox();
  296.         $buttons->set_layout(Gtk::BUTTONBOX_END);
  297.  
  298.         $copy    = GtkButton::new_from_stock(Gtk::STOCK_COPY);
  299.         $copy->connect_simple('clicked'array($this'onCopy'));
  300.         $buttons->add($copy);
  301.  
  302.         return $buttons;
  303.     }//protected function buildActionButtonBox()
  304.  
  305.  
  306.  
  307.     /**
  308.     *   Creates the error message that the object isn't an
  309.     *   Exception or a PEAR_Error.
  310.     *
  311.     *   @param mixed    $exception  Some variable that isn't an Exception
  312.     *                                 or a PEAR_Error object
  313.     */
  314.     protected function buildError($exception)
  315.     {
  316.         $this->infobox->setMessage(
  317.             'Gtk2_ExceptionDump has been called with'
  318.             . ' an variable of type "' gettype($exception'".' "\n"
  319.             . 'It cannot be displayed since it is not'
  320.             . ' an Exception or an PEAR_Error object.',
  321.  
  322.             'Usually, this occurs when the programmer didn\'t check' "\n"
  323.             . 'what type of variable is passed to Gtk2_ExceptionDump.' "\n"
  324.             . 'File a bug report'
  325.         );
  326.  
  327.         $this->stack->setException(new Exception()3);
  328.     }//protected function buildError($exception)
  329.  
  330.  
  331.  
  332.     /**
  333.     *   Quits the php script with exit status 253.
  334.     */
  335.     public function onQuit()
  336.     {
  337.         exit(253);
  338.     }//public function onQuit()
  339.  
  340.  
  341.  
  342.     /**
  343.     *   Closes the window, quits the main loop
  344.     *   and continues normal script execution.
  345.     */
  346.     public function onContinue()
  347.     {
  348.         //block the destroy signal, since it would call onQuit()
  349.         $this->block($this->destroySignal);
  350.         $this->destroy();
  351.         //close this level
  352.         Gtk::main_quit();
  353.     }//public function onContinue()
  354.  
  355.  
  356.  
  357.     /**
  358.     *   Copies the exception/error as string to the clipboard.
  359.     */
  360.     public function onCopy()
  361.     {
  362.         $cb = GtkClipboard::get(Gdk::atom_intern('CLIPBOARD'false));
  363.         $cb->set_text(self::getExceptionAsString($this->exception));
  364.     }//public function onCopy()
  365.  
  366.  
  367.  
  368.     /**
  369.     *   Generates a string representation of the exception.
  370.     *
  371.     *   @param mixed    $exception  The exception to convert
  372.     */
  373.     protected static function getExceptionAsString($exception)
  374.     {
  375.         $s = array(
  376.             get_class($exception),
  377.             'Message:',
  378.             ' ' $exception->getMessage()
  379.         );
  380.         if ($exception instanceof PEAR_Error{
  381.             $s['User info';
  382.             $s[' ' $exception->getUserInfo();
  383.         }
  384.  
  385.         $func $exception instanceof PEAR_Error ? 'getBacktrace' 'getTrace';
  386.         $trace $exception->$func();
  387.         $s['Backtrace:';
  388.         foreach ($trace as $id => $step{
  389.             if (count($step['args']== 0{
  390.                 $function $step['function''()';
  391.             else {
  392.                 $function $step['function''(...)';
  393.             }
  394.  
  395.             if (isset($step['class'])) {
  396.                 if ($step['class'== $step['function']{
  397.                     $function 'new ' $function;
  398.                 else {
  399.                     $function $step['class'$step['type'$function;
  400.                 }
  401.             }
  402.  
  403.             if (isset($step['file'])) {
  404.                 $file $step['file''#' $step['line'];
  405.             else {
  406.                 $file 'unknown';
  407.             }
  408.  
  409.             $s[' ' $function' at ' $file;
  410.  
  411.  
  412.             foreach ($step['args'as $arg{
  413.                 if (gettype($arg== 'object'{
  414.                     $arg get_class($arg' - ' . (string)$arg;
  415.                 else {
  416.                     $arg gettype($arg'(' $arg ')';
  417.                 }
  418.                 $s[.= '  ' $arg;
  419.             }
  420.         }
  421.  
  422.         $s['';//newline
  423.  
  424.         return implode("\r\n"$s);
  425.     }//protected static function getExceptionAsString($exception)
  426.  
  427. }//class Gtk2_ExceptionDump extends GtkWindow
  428. ?>

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