Manage site errors using exceptions.
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Fri, 2 Jul 2010 13:48:06 +0000 (15:48 +0200)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Fri, 2 Jul 2010 13:51:19 +0000 (15:51 +0200)
This has 3 main avantages:
 - Error may not be fatal (e.g. a SQL error must not be fatal during the
   execution of the unit tests)
 - We can have the backtrace
 - The same code handle all the kind of errors.

Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
classes/platal.php
classes/plexception.php [new file with mode: 0644]
classes/xdb.php
include/test.inc.php
modules/core.php
templates/site_errors.tpl [moved from templates/assert_errors.tpl with 94% similarity]
templates/sql_errors.tpl [deleted file]

index 06002ed..b911828 100644 (file)
@@ -360,18 +360,35 @@ abstract class Platal
             $this->path = 'index';
         }
 
-        $page->assign('platal', $this);
-        switch ($this->call_hook($page)) {
-          case PL_FORBIDDEN:
-            $this->mods['core']->handler_403($page);
-            break;
+        try {
+            $page->assign('platal', $this);
+            switch ($this->call_hook($page)) {
+              case PL_FORBIDDEN:
+                $this->mods['core']->handler_403($page);
+                break;
+
+              case PL_NOT_FOUND:
+                $this->mods['core']->handler_404($page);
+                break;
+
+              case PL_WIKI:
+                return PL_WIKI;
+            }
+        } catch (Exception $e) {
+            header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error');
 
-          case PL_NOT_FOUND:
-            $this->mods['core']->handler_404($page);
-            break;
+            $file = fopen(self::globals()->spoolroot . '/spool/tmp/site_errors', 'a');
+            fwrite($file, '<pre>' . date('Y-m-d G:i:s') . '</pre>'
+                        . '<pre>' . pl_entities("" . $e) . '</pre>'
+                        . '------------------------------------------------------------------' . "\n");
+            fclose($file);
 
-          case PL_WIKI:
-            return PL_WIKI;
+            if (self::globals()->debug) {
+                $page->kill(pl_entities($e->getMessage())
+                            . '<pre>' . pl_entities("" . $e) . '</pre>');
+            } else {
+                $page->kill(pl_entities($e->getMessage()));
+            }
         }
 
         $page->assign('platal', $this);
@@ -426,19 +443,13 @@ abstract class Platal
 
     public static function assert($cond, $error, $userfriendly = null)
     {
-        global $globals;
         if ($cond === false) {
-            header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error');
-            $file = fopen($globals->spoolroot . '/spool/tmp/assert_erros', 'a');
-            fwrite($file, '<pre>' . pl_entities($error) . '</pre>\n');
-            fclose($file);
-
             if ($userfriendly == null) {
                 $userfriendly = "Une erreur interne s'est produite.
                     Merci de réessayer la manipulation qui a déclenché l'erreur ;
                     si cela ne fonctionne toujours pas, merci de nous signaler le problème rencontré.";
             }
-            Platal::page()->kill($userfriendly);
+            throw new PlException($userfriendly, $error);
         }
     }
 
diff --git a/classes/plexception.php b/classes/plexception.php
new file mode 100644 (file)
index 0000000..b819fc1
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2010 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ **************************************************************************/
+
+class PlException extends Exception {
+    private $internalMessage;
+
+    public function __construct($publicMessage, $internalMessage) {
+        parent::__construct($publicMessage);
+        $this->internalMessage = $internalMessage;
+    }
+
+    public function __toString() {
+        return $this->internalMessage . "\n\n" . parent::__toString();
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
index 6a15660..6ceb911 100644 (file)
  *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
  **************************************************************************/
 
+class XDBException extends PlException {
+    public function __construct($query, $error) {
+        if (strpos($query, 'INSERT') === false && strpos($query, 'UPDATE') === false
+            && strpos($query, 'REPLACE') === false && strpos($query, 'DELETE') === false) {
+            $text = 'Erreur lors de l\'interrogation de la base de données';
+        } else {
+            $text = 'Erreur lors de l\'écriture dans la base de données';
+        }
+        parent::__construct($text, $query . "\n" . $error);
+    }
+}
+
 class XDB
 {
     private static $mysqli = null;
-    private static $fatalErrors = true;
 
     public static function connect()
     {
@@ -40,11 +51,6 @@ class XDB
         return true;
     }
 
-    public static function setNonFatalError()
-    {
-        self::$fatalErrors = false;
-    }
-
     public static function _prepare($args)
     {
         global $globals;
@@ -113,32 +119,7 @@ class XDB
         }
 
         if ($res === false) {
-            header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error');
-            if (strpos($query, 'INSERT') === false && strpos($query, 'UPDATE') === false
-                && strpos($query, 'REPLACE') === false && strpos($query, 'DELETE') === false) {
-                $text = 'Erreur lors de l\'interrogation de la base de données';
-            } else {
-                $text = 'Erreur lors de l\'écriture dans la base de données';
-            }
-            if (php_sapi_name() == 'cli') {
-                $text .= "\n" . XDB::_reformatQuery($query)
-                       . "\n" . XDB::$mysqli->error;
-            } else if ($globals->debug) {
-                $text .= '<pre>' . pl_entities(XDB::_reformatQuery($query)) . '</pre>';
-            } else {
-                $file = fopen($globals->spoolroot . '/spool/tmp/query_errors', 'a');
-                fwrite($file, '<pre>' . date("Y-m-d G:i:s") . '</pre>'
-                            . '<pre>' . pl_entities(XDB::_reformatQuery($query)) . '</pre>'
-                            . '<pre>' . XDB::$mysqli->error . '</pre>'
-                            . "--------------------------------------------------------------------------------\n");
-                fclose($file);
-            }
-            if (self::$fatalErrors) {
-                Platal::page()->kill($text);
-                exit;
-            } else {
-                throw new Exception($text . " :\n" . $query);
-            }
+            throw new XDBException(XDB::_reformatQuery($query), XDB::$mysqli->error);
         }
         return $res;
     }
index c5dc418..2a7048e 100644 (file)
@@ -31,7 +31,6 @@ if (file_exists($testinclude)) {
         pl_autoload($class);
     }
 }
-XDB::setNonFatalError();
 
 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
 ?>
index adbcf38..6d43027 100644 (file)
@@ -30,8 +30,9 @@ class CoreModule extends PLModule
             'send_bug'      => $this->make_hook('bug',           AUTH_COOKIE),
             'purge_cache'   => $this->make_hook('purge_cache',   AUTH_COOKIE, 'admin'),
             'kill_sessions' => $this->make_hook('kill_sessions', AUTH_COOKIE, 'admin'),
-            'sql_errors'    => $this->make_hook('sqlerror',      AUTH_COOKIE, 'admin'),
-            'assert_errors' => $this->make_hook('asserterror',      AUTH_COOKIE, 'admin'),
+            'sql_errors'    => $this->make_hook('siteerror',     AUTH_COOKIE, 'admin'),
+            'assert_errors' => $this->make_hook('siteerror',     AUTH_COOKIE, 'admin'),
+            'site_errors'   => $this->make_hook('siteerror',     AUTH_COOKIE, 'admin'),
 
             'wiki_help'     => $this->make_hook('wiki_help',     AUTH_PUBLIC),
             'wiki_preview'  => $this->make_hook('wiki_preview',  AUTH_COOKIE, 'user', NO_AUTH),
@@ -177,29 +178,16 @@ class CoreModule extends PLModule
         exit;
     }
 
-    function handler_sqlerror(&$page) {
+    function handler_siteerror(&$page) {
         global $globals;
-        $page->coreTpl('sql_errors.tpl');
-        $file = @file_get_contents($globals->spoolroot . '/spool/tmp/query_errors');
+        $page->coreTpl('site_errors.tpl');
+        $file = @file_get_contents($globals->spoolroot . '/spool/tmp/site_errors');
         if ($file !== false) {
             $page->assign('errors', utf8_encode($file));
         }
         if (Post::has('clear')) {
-            @unlink($globals->spoolroot . '/spool/tmp/query_errors');
-            $page->trigSuccess("Erreurs MySQL effacées.");
-        }
-    }
-
-    function handler_asserterror(&$page) {
-        global $globals;
-        $page->coreTpl('assert_errors.tpl');
-        $file = @file_get_contents($globals->spoolroot . '/spool/tmp/assert_errors');
-        if ($file !== false) {
-            $page->assign('errors', utf8_encode($file));
-        }
-        if (Post::has('clear')) {
-            @unlink($globals->spoolroot . '/spool/tmp/assert_errors');
-            $page->trigSuccess("Erreurs d'assertion effacées.");
+            @unlink($globals->spoolroot . '/spool/tmp/site_errors');
+            $page->trigSuccess("Erreurs effacées.");
         }
     }
 }
similarity index 94%
rename from templates/assert_errors.tpl
rename to templates/site_errors.tpl
index 058a5cf..ffdf1e5 100644 (file)
@@ -1,38 +1,38 @@
-{**************************************************************************}
-{*                                                                        *}
-{*  Copyright (C) 2003-2010 Polytechnique.org                             *}
-{*  http://opensource.polytechnique.org/                                  *}
-{*                                                                        *}
-{*  This program is free software; you can redistribute it and/or modify  *}
-{*  it under the terms of the GNU General Public License as published by  *}
-{*  the Free Software Foundation; either version 2 of the License, or     *}
-{*  (at your option) any later version.                                   *}
-{*                                                                        *}
-{*  This program is distributed in the hope that it will be useful,       *}
-{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
-{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
-{*  GNU General Public License for more details.                          *}
-{*                                                                        *}
-{*  You should have received a copy of the GNU General Public License     *}
-{*  along with this program; if not, write to the Free Software           *}
-{*  Foundation, Inc.,                                                     *}
-{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
-{*                                                                        *}
-{**************************************************************************}
-
-<h1>Erreurs d'assertions</h1>
-<p>
-  {if $errors}
-    {$errors|smarty:nodefaults}
-  {else}
-    Il n'y a pas d'erreurs actuellement recensées.
-  {/if}
-</p>
-<form action="assert_errors" method="post">
-  <div>
-    <input type="submit" name="clear" value="Effacer les erreurs" />
-  </div>
-</form>
-
-
-{* vim:set et sws=2 sts=2 sw=2 enc=utf-8: *}
+{**************************************************************************}\r
+{*                                                                        *}\r
+{*  Copyright (C) 2003-2010 Polytechnique.org                             *}\r
+{*  http://opensource.polytechnique.org/                                  *}\r
+{*                                                                        *}\r
+{*  This program is free software; you can redistribute it and/or modify  *}\r
+{*  it under the terms of the GNU General Public License as published by  *}\r
+{*  the Free Software Foundation; either version 2 of the License, or     *}\r
+{*  (at your option) any later version.                                   *}\r
+{*                                                                        *}\r
+{*  This program is distributed in the hope that it will be useful,       *}\r
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}\r
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}\r
+{*  GNU General Public License for more details.                          *}\r
+{*                                                                        *}\r
+{*  You should have received a copy of the GNU General Public License     *}\r
+{*  along with this program; if not, write to the Free Software           *}\r
+{*  Foundation, Inc.,                                                     *}\r
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}\r
+{*                                                                        *}\r
+{**************************************************************************}\r
+\r
+<h1>Erreurs d'exécution</h1>\r
+  {if $errors}\r
+    {$errors|smarty:nodefaults}\r
+  {else}\r
+<p>\r
+    Il n'y a pas d'erreurs actuellement recensées.\r
+</p>\r
+  {/if}\r
+<form action="site_errors" method="post">\r
+  <div>\r
+    <input type="submit" name="clear" value="Effacer les erreurs" />\r
+  </div>\r
+</form>\r
+\r
+\r
+{* vim:set et sws=2 sts=2 sw=2 enc=utf-8: *}\r
diff --git a/templates/sql_errors.tpl b/templates/sql_errors.tpl
deleted file mode 100644 (file)
index 7c67ce5..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-{**************************************************************************}\r
-{*                                                                        *}\r
-{*  Copyright (C) 2003-2010 Polytechnique.org                             *}\r
-{*  http://opensource.polytechnique.org/                                  *}\r
-{*                                                                        *}\r
-{*  This program is free software; you can redistribute it and/or modify  *}\r
-{*  it under the terms of the GNU General Public License as published by  *}\r
-{*  the Free Software Foundation; either version 2 of the License, or     *}\r
-{*  (at your option) any later version.                                   *}\r
-{*                                                                        *}\r
-{*  This program is distributed in the hope that it will be useful,       *}\r
-{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}\r
-{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}\r
-{*  GNU General Public License for more details.                          *}\r
-{*                                                                        *}\r
-{*  You should have received a copy of the GNU General Public License     *}\r
-{*  along with this program; if not, write to the Free Software           *}\r
-{*  Foundation, Inc.,                                                     *}\r
-{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}\r
-{*                                                                        *}\r
-{**************************************************************************}\r
-\r
-<h1>Erreurs MySQL</h1>\r
-  {if $errors}\r
-    {$errors|smarty:nodefaults}\r
-  {else}\r
-<p>\r
-    Il n'y a pas d'erreurs actuellement recensées.\r
-</p>\r
-  {/if}\r
-<form action="sql_errors" method="post">\r
-  <div>\r
-    <input type="submit" name="clear" value="Effacer les erreurs" />\r
-  </div>\r
-</form>\r
-\r
-\r
-{* vim:set et sws=2 sts=2 sw=2 enc=utf-8: *}\r