From 4f7e5b00bc783feb8c5b1a2220bc5370991ada61 Mon Sep 17 00:00:00 2001 From: pzinovkin Date: Sun, 7 Mar 2010 17:26:44 +0000 Subject: [PATCH] Errors and exceptions handling, #16 git-svn-id: svn+ssh://code.netmonsters.ru/svn/majestic/branches/evo@121 4cb57b5f-5bbd-dd11-951b-001d605cbbc5 --- app/ErrorAction.php | 59 +++++++++++++ app/FrontController.php | 58 +++++------- classes/Env.class.php | 38 +++++--- exception/Error404Exception.php | 13 +-- exception/ErrorHandler.php | 190 ++++++++++++++++++++++++++++++++++++++++ exception/GeneralException.php | 19 +--- view/PHPView.php | 10 ++- 7 files changed, 305 insertions(+), 82 deletions(-) create mode 100644 app/ErrorAction.php create mode 100644 exception/ErrorHandler.php diff --git a/app/ErrorAction.php b/app/ErrorAction.php new file mode 100644 index 0000000..0ffc9ee --- /dev/null +++ b/app/ErrorAction.php @@ -0,0 +1,59 @@ + + * @link http://netmonsters.ru + * @package Majestic + * @subpackage app + * @since 2010-02-25 + * @version SVN: $Id$ + * @filesource $URL$ + */ + +class ErrorAction extends ViewAction +{ + + /** + * @var Exception + */ + protected $exception; + + public function __construct($exception) + { + $this->exception = $exception; + $this->view = FrontController::getInstance()->getView(); + $this->execute(); + } + + protected function execute() + { + $this->template = 500; + if ($this->exception instanceof Error404Exception) { + $this->template = 404; + } + } + + protected function getTemplate() + { + return '/static/' . $this->template; + } + + protected function sendHttpCode($code) + { + if (headers_sent()) { + return; + } + switch ($code) { + case 404: + header('HTTP/1.0 404 Not Found'); + break; + default: + header('HTTP/1.0 500 Internal Server Error'); + } + } + + public function fetch() + { + $this->sendHTTPCode($this->template); + return $this->view->fetch($this->getTemplate()); + } +} \ No newline at end of file diff --git a/app/FrontController.php b/app/FrontController.php index 5df27de..67d683e 100644 --- a/app/FrontController.php +++ b/app/FrontController.php @@ -21,11 +21,6 @@ class FrontController */ protected $view = 'PHPView'; - /** - * @var string - */ - protected $view_path; - protected $base_url = ''; /** @@ -36,9 +31,13 @@ class FrontController private function __construct() { + ErrorHandler::init(); $this->router = new Router(); } + /** + * Refuse cloning + */ private function __clone(){} /** @@ -46,23 +45,13 @@ class FrontController */ static public function getInstance() { - if (! isset(self::$instance)) { + if (!isset(self::$instance)) { self::$instance = new self(); } return self::$instance; } /** - * @param string $path - * @return FrontController - */ - public function setViewPath($path) - { - $this->view_path = $path; - return $this; - } - - /** * @param string $view * @return FrontController */ @@ -79,7 +68,7 @@ class FrontController public function getView($view = null) { $view = ($view) ? $view : $this->view; - return new $view($this->view_path); + return new $view(Config::get($view)); } /** @@ -106,29 +95,26 @@ class FrontController public function execute() { - try { - try { - $request = Env::getRequestUri(); - $route = $this->getRouter()->route($request); - if (!$route) { - throw new Exception('Route "' . $request . '" not found'); - } - - $action_class = $route->getAction(); - $action = new $action_class(); - $layout_class = $route->getLayout(); - $layout = new $layout_class(); - return $layout->fetch($action); - } catch (GeneralException $e) { - throw $e; - } catch (Exception $e) { - throw new GeneralException($e->getMessage(), $e->getCode()); + + $request = Env::getRequestUri(); + $route = $this->getRouter()->route($request); + if (!$route) { + throw new Error404Exception('Route "' . $request . '" not found'); } - } catch (Exception $e) { + + $action_class = $route->getAction(); + $action = new $action_class(); + $layout_class = $route->getLayout(); + $layout = new $layout_class(); + return $layout->fetch($action); + + } catch(Exception $e) { if (DEBUG == true) { - return $e->toHtml(); + return ErrorHandler::showDebug($e); } + $layout = new DefaultLayout(); + return $layout->fetch(new ErrorAction($e)); } } } \ No newline at end of file diff --git a/classes/Env.class.php b/classes/Env.class.php index db72236..eafb9fe 100644 --- a/classes/Env.class.php +++ b/classes/Env.class.php @@ -30,19 +30,36 @@ class Env return self::$request; } - static public function Get($var, $default = false) + static public function Get($key = null, $default = null) { - return isset($_GET[$var]) ? $_GET[$var] : $default; + if ($key === null) { + return $_GET; + } + return (isset($_GET[$key])) ? $_GET[$key] : $default; } - - static public function Post($var, $default = false) + + static public function Post($key = null, $default = null) { - return isset($_POST[$var]) ? $_POST[$var] : $default; + if ($key === null) { + return $_POST; + } + return (isset($_POST[$key])) ? $_POST[$key] : $default; } - - static public function Server($var, $default = false) + + static public function Cookie($key = null, $default = false) + { + if ($key === null) { + return $_COOKIE; + } + return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : $default; + } + + static public function Server($key = null, $default = null) { - return isset($_SERVER[$var]) ? $_SERVER[$var] : $default; + if ($key === null) { + return $_SERVER; + } + return (isset($_SERVER[$key])) ? $_SERVER[$key] : $default; } static public function Session($var, $default = false) @@ -67,11 +84,6 @@ class Env } } - static public function getCookie($var, $default = false) - { - return isset($_COOKIE[$var]) ? $_COOKIE[$var] : $default; - } - static public function setCookie($var, $value, $time = 0, $path = '/') { return setcookie($var, $value, $time, $path); diff --git a/exception/Error404Exception.php b/exception/Error404Exception.php index 0f6b6e0..b6690fe 100644 --- a/exception/Error404Exception.php +++ b/exception/Error404Exception.php @@ -9,15 +9,4 @@ * @filesource $URL$ */ -class Error404Exception extends GeneralException -{ - protected $code = 404; - - protected function sendHeader() - { - if (! headers_sent()) { - header('HTTP/1.0 404 Not Found'); - } - } - -} \ No newline at end of file +class Error404Exception extends GeneralException {} \ No newline at end of file diff --git a/exception/ErrorHandler.php b/exception/ErrorHandler.php new file mode 100644 index 0000000..18dd2f6 --- /dev/null +++ b/exception/ErrorHandler.php @@ -0,0 +1,190 @@ + + * @link http://netmonsters.ru + * @package Majestic + * @subpackage exception + * @since 2010-02-26 + * @version SVN: $Id$ + * @filesource $URL$ + */ + +class ErrorHandler +{ + + static public function init() + { + set_error_handler(array('ErrorHandler', 'error_handler')); + } + + static public function error_handler($errno, $errstr, $errfile, $errline ) + { + throw new ErrorException($errstr, 0, $errno, $errfile, $errline); + return false; + } + + static protected function getSource($file, $hiline) + { + $code = array(); + $i = 0; + foreach(file($file) as $line) { + $i++; + if($i >= $hiline - 10 && $i <= $hiline + 10) { + if ($i == $hiline) { + $code[] = '' . $i . '' . $line . ''; + }else{ + $code[] = '' . $i . '' . $line . ''; + } + } + if($i > $hiline + 10) { + break; + } + } + return implode('', $code); + } + + static protected function wrapArray($array, $name) + { + if (!$array) { + return '

No ' . $name . ' data

'; + } + $text = ''; + foreach ($array as $key => $value) { + $text .= ''; + } + $text .= '
VariableValue
' . $key . '
' . $value . '
'; + return $text; + } + + static protected function wrapTrace($trace) + { + return '' . nl2br($trace) . ''; + } + + /** + * @param Exception $exception + */ + static public function showDebug($exception) + { + $class = get_class($exception); + + $method = Env::Server('REQUEST_METHOD', ''); + $uri = Env::getRequestUri(); + $source = self::getSource($exception->getFile(), $exception->getLine()); + $time = date('r', Env::Server('REQUEST_TIME', time())); + + $trace = self::wrapTrace($exception->getTraceAsString()); + + $get = self::wrapArray(Env::Get(), 'GET'); + $post = self::wrapArray(Env::Post(), 'POST'); + $files = self::wrapArray(Env::Files(), 'FILES'); + $cookies = self::wrapArray(Env::Cookie(), 'COOKIE'); + $server = self::wrapArray(Env::Server(), 'SERVER'); + + $message =<< + + + + {$class} at {$uri} + + + +
+

{$class} at {$uri}

+
{$exception->getMessage()}
+ + + + + + + + + +
Request Method:{$method}
Exception Type:{$class}
Exception Message:
{$exception->getMessage()}
Exception Location:{$exception->getFile()}, line {$exception->getLine()}
Server time:{$time}
+
+ +
+

Context

+

In file {$exception->getFile()}, error at line {$exception->getLine()}

+

{$exception->getMessage()}

+ + {$source} +
+
+ +
+

Traceback

+
{$trace}
+
+ +
+

Request information

+

GET

+ {$get} +

POST

+ {$post} +

FILES

+ {$files} + + {$cookies} +

SERVER

+ {$server} +

Settings

+

todo

+
+ +
+

You're seeing this error because you have defined constant DEBUG = True in your config file. Change that to False, and it will display a standard 500 page.

+
+ + +EOD; + return $message; + } +} \ No newline at end of file diff --git a/exception/GeneralException.php b/exception/GeneralException.php index 9127984..41c3bd3 100644 --- a/exception/GeneralException.php +++ b/exception/GeneralException.php @@ -9,21 +9,4 @@ * @filesource $URL$ */ -class GeneralException extends Exception -{ - - protected $code = 500; - - protected function sendHeader() - { - if (!headers_sent()) { - header('HTTP/1.0 500 Internal Server Error'); - } - } - - public function toHtml() - { - $this->sendHeader(); - return 'Exception caught: ' . $this->getMessage(); - } -} \ No newline at end of file +class GeneralException extends Exception {} \ No newline at end of file diff --git a/view/PHPView.php b/view/PHPView.php index b2ac3a1..cdb7f9e 100644 --- a/view/PHPView.php +++ b/view/PHPView.php @@ -17,9 +17,12 @@ class PHPView implements iView protected $extension = '.phtml'; protected $template = ''; - public function __construct($path) + public function __construct($config) { - $this->setPath($path); + if (!isset($config['path'])) { + throw new Exception('Configuration must have a "host".'); + } + $this->setPath($config['path']); } public function getPath() @@ -53,10 +56,11 @@ class PHPView implements iView unset($template); extract($this->variables); ob_start(); - if (!(include($this->template)) == 'OK') { + if (!is_readable($this->template)) { ob_clean(); throw new Exception('Template "' . $this->template .'" not found.'); } + include($this->template); return ob_get_clean(); }