nicer exception handling
authorMichael Wallner <mike@php.net>
Fri, 8 May 2015 19:15:17 +0000 (21:15 +0200)
committerMichael Wallner <mike@php.net>
Fri, 8 May 2015 19:15:17 +0000 (21:15 +0200)
app/Web.php
app/views/404.phtml
app/views/405.phtml
app/views/500.phtml [new file with mode: 0644]
app/views/alert.phtml
app/views/github/repo.phtml
public/index.php

index c9659b68231f276ffd4951b15173c196b2b37acd..0353a996c2b75e97a9a653c9495395a1684ce458 100644 (file)
@@ -29,28 +29,36 @@ class Web
 
                switch ($route[0]) {
                        case Dispatcher::NOT_FOUND:
-                               $this->response->setResponseCode(404);
-                               $this->response->getBody()->append($this->view->render("404"));
+                               $this->display(404, null, 404);
                                break;
 
                        case Dispatcher::METHOD_NOT_ALLOWED:
-                               $this->response->setResponseCode(405);
-                               $this->response->setHeader("Allowed", $route[1]);
-                               $this->response->getBody()->append($this->view->render("405"));
+                               $this->display(405, null, 405, ["Allowed" => $route[1]]);
                                break;
 
                        case Dispatcher::FOUND:
                                list(, $handler, $args) = $route;
-                               $handler(array_map("urldecode", $args));
+                               try {
+                                       $handler(array_map("urldecode", $args));
+                               } catch (\Exception $exception) {
+                                       self::cleanBuffers();
+                                       $this->display(500, compact("exception"), 500, ["X-Exception", get_class($exception)]);
+                               }
                                break;
                }
 
                $this->response->send();
        }
 
-       function display($view, array $data = []) {
+       function display($view, array $data = null, $code = null, array $headers = []) {
+               if (isset($code)) {
+                       $this->response->setResponseCode($code);
+               }
+               if ($headers) {
+                       $this->response->addHeaders($headers);
+               }
                $this->response->getBody()->append(
-                       $this->view->render($view, $data));
+                       $this->view->render($view, (array) $data));
        }
 
        function redirect($url, $code = 302) {
@@ -73,4 +81,12 @@ class Web
        function getResponse() {
                return $this->response;
        }
+       
+       static function cleanBuffers() {
+               while (ob_get_level()) {
+                       if (!@ob_end_clean()) {
+                               break;
+                       }
+               }
+       }
 }
index 491df9c636b5f50708144f484bd8599ed1a5b22f..f8fd0bb8c3150bcae281059f79008ab113a170d6 100644 (file)
@@ -1,5 +1,8 @@
 <?php $this->layout("layout") ?>
 
 <div class="page-header">
-       <h1>404 <small>Not Found</small>
+       <h1>Not Found <small>404</small></h1>
 </div>
+<p>
+       Page <?= $this->e($request->getRequestUrl()) ?> was not found.
+</p>
index ec251640410e0f6f3f13a048bc18d5e41325472a..0143f6787cd5475b84cc09f2d093d285593fa45d 100644 (file)
@@ -1,5 +1,8 @@
 <?php $this->layout("layout") ?>
 
 <div class="page-header">
-       <h1>405 <small>Method Not Allowed</small>
+       <h1>Method Not Allowed <small>405</small>
 </div>
+<p>
+       Request method <?= $this->e($request->getRequestMethod()) ?> is not allowed.
+</p>
diff --git a/app/views/500.phtml b/app/views/500.phtml
new file mode 100644 (file)
index 0000000..98692b9
--- /dev/null
@@ -0,0 +1,7 @@
+<?php $this->layout("layout") ?>
+
+<div class="page-header">
+       <h1>Application error <small>500</small></h1>
+</div>
+
+<?= $this->fetch("alert", compact("exception")) ?>
index bd8c0b76b28e8fbf48c8c171607084ba6e2cc14e..5d0a51644b1bbcb6075f5d5e843556f3fb13f7e6 100644 (file)
@@ -1,6 +1,6 @@
 
 <div class="alert alert-danger" role="alert">
-       <strong><?= $this->e($exception->getMessage()) ?></strong><br>
+       <strong><?= nl2br($this->e($exception->getMessage())) ?></strong><br>
        <?php if ($exception instanceof \app\Github\Exception\TokenException) : ?>
                You might want to try to <a href="<?= $baseUrl->mod("./github/signin") ?>">renew your token</a>!
        <?php endif; ?>
@@ -8,3 +8,8 @@
                You might want to try to <a href="<?= $baseUrl->mod("./github/signin") ?>">try again</a>!
        <?php endif; ?>
 </div>
+
+<?php if (APP_ENVIRONMENT != "production") : ?>
+<h3>Stack Trace</h3>
+<pre><?= $this->e($exception->getTraceAsString()) ?></pre>
+<?php endif; ?>
index 36849c00094ae9720b192637cb4cfe5ac392ccdf..d32183068e95ff43e214e3daa57dfe250f1e8064 100644 (file)
                                <?= $this->e($v->tag->name) ?>
                                <span class="label label-default pull-right">Tag</span>
                        <?php else : ?>
-                               <?= $this->e($v->release->name) ?>
+                               <?= $this->e($v->release->name ?: $v->tag->name) ?>
                                <span class="label label-info pull-right">Release</span>
                        <?php endif; ?>
                </h3>
index 5718129b2397f3b9e978b8511b630421b8083919..7603f62973f67b31d91940ea33255e80e98b8129 100644 (file)
@@ -2,6 +2,38 @@
 
 namespace app;
 
-$bootstrap = require "../app/bootstrap.php";
-$injector = $bootstrap(["config", "github", "plates", "model", "web"]);
-$injector->execute(Web::class);
+try {
+       $bootstrap = require "../app/bootstrap.php";
+       $injector = $bootstrap(["config", "github", "plates", "model", "web"]);
+       return $injector->execute(Web::class);
+} catch (\Exception $e) {
+       $error = $e->getMessage();
+       $stack = $e->getTraceAsString();
+       @header("X-Exception: ".get_class($e), false, 500);
+       Web::cleanBuffers();
+}
+?>
+<html>
+       <head>
+               <meta charset="utf-8">
+               <title>Application Error</title>
+               <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
+       </head>
+       <body>
+               <div class="container">
+                       <div class="jumbotron">
+                               <h1>Application Error</h1>
+                               <h2>Aww, you really gotta do that?!</h2>
+                               <p class="text-danger">
+                                       <strong><?= htmlspecialchars($error) ?></strong>
+                               </p>
+                               <p>
+                                       Sorry, anyway.
+                               </p>
+                       </div>
+                       <?php if (APP_ENVIRONMENT != "production") : ?>
+                       <pre><?= htmlspecialchars($stack) ?></pre>
+                       <?php endif; ?>
+               </div>
+       </body>
+</html>