From 89bbdae6c11ad1666c646257dac1ede9d8bae508 Mon Sep 17 00:00:00 2001 From: resurtm Date: Thu, 23 May 2013 22:34:37 +0600 Subject: [PATCH] Initial version of the new error/exception page. --- apps/bootstrap/controllers/SiteController.php | 1 + apps/bootstrap/www/index.php | 5 +- framework/yii/base/ErrorHandler.php | 215 +++--------------- framework/yii/views/errorHandler.php | 303 ++++++++++++++++++++++++++ 4 files changed, 333 insertions(+), 191 deletions(-) create mode 100644 framework/yii/views/errorHandler.php diff --git a/apps/bootstrap/controllers/SiteController.php b/apps/bootstrap/controllers/SiteController.php index ff3b8b4..4c00cea 100644 --- a/apps/bootstrap/controllers/SiteController.php +++ b/apps/bootstrap/controllers/SiteController.php @@ -20,6 +20,7 @@ class SiteController extends Controller public function actionIndex() { + throw new \yii\base\HttpException(500, 'Test exception'); echo $this->render('index'); } diff --git a/apps/bootstrap/www/index.php b/apps/bootstrap/www/index.php index 3b7b2fc..cb363a0 100644 --- a/apps/bootstrap/www/index.php +++ b/apps/bootstrap/www/index.php @@ -3,8 +3,9 @@ // comment out the following line to disable debug mode defined('YII_DEBUG') or define('YII_DEBUG', true); -require(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php'); -require(__DIR__ . '/../vendor/autoload.php'); +//require(__DIR__ . '/../vendor/yiisoft/yii2/yii/Yii.php'); +//require(__DIR__ . '/../vendor/autoload.php'); +require(__DIR__ . '/../../../framework/yii/Yii.php'); $config = require(__DIR__ . '/../config/main.php'); diff --git a/framework/yii/base/ErrorHandler.php b/framework/yii/base/ErrorHandler.php index 8340723..09e4a59 100644 --- a/framework/yii/base/ErrorHandler.php +++ b/framework/yii/base/ErrorHandler.php @@ -7,6 +7,8 @@ namespace yii\base; +use Yii; + /** * ErrorHandler handles uncaught PHP errors and exceptions. * @@ -31,28 +33,25 @@ class ErrorHandler extends Component */ public $discardExistingOutput = true; /** - * @var string the route (eg 'site/error') to the controller action that will be used to display external errors. - * Inside the action, it can retrieve the error information by \Yii::$app->errorHandler->error. - * This property defaults to null, meaning ErrorHandler will handle the error display. + * @var string the route (e.g. 'site/error') to the controller action that will be used + * to display external errors. Inside the action, it can retrieve the error information + * by Yii::$app->errorHandler->error. This property defaults to null, meaning ErrorHandler + * will handle the error display. */ public $errorAction; /** - * @var string the path of the view file for rendering exceptions - */ - public $exceptionView = '@yii/views/exception.php'; - /** - * @var string the path of the view file for rendering errors + * @var string the path of the view file for rendering exceptions and errors. */ - public $errorView = '@yii/views/error.php'; + public $view = '@yii/views/errorHandler.php'; /** - * @var \Exception the exception that is being handled currently + * @var \Exception the exception that is being handled currently. */ public $exception; /** - * Handles exception - * @param \Exception $exception + * Handles exception. + * @param \Exception $exception to be handled. */ public function handle($exception) { @@ -66,14 +65,16 @@ class ErrorHandler extends Component } /** - * Renders exception - * @param \Exception $exception + * Renders exception. + * @param \Exception $exception to be handled. */ protected function renderException($exception) { if ($this->errorAction !== null) { - \Yii::$app->runAction($this->errorAction); - } elseif (\Yii::$app instanceof \yii\web\Application) { + Yii::$app->runAction($this->errorAction); + } elseif (!(Yii::$app instanceof \yii\web\Application)) { + Yii::$app->renderException($exception); + } else { if (!headers_sent()) { if ($exception instanceof HttpException) { header('HTTP/1.0 ' . $exception->statusCode . ' ' . $exception->getName()); @@ -82,7 +83,7 @@ class ErrorHandler extends Component } } if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') { - \Yii::$app->renderException($exception); + Yii::$app->renderException($exception); } else { // if there is an error during error rendering it's useful to // display PHP error in debug mode instead of a blank screen @@ -90,177 +91,25 @@ class ErrorHandler extends Component ini_set('display_errors', 1); } - $view = new View; - if (!YII_DEBUG || $exception instanceof UserException) { - $viewName = $this->errorView; - } else { - $viewName = $this->exceptionView; - } - echo $view->renderFile($viewName, array( - 'exception' => $exception, - ), $this); - } - } else { - \Yii::$app->renderException($exception); - } - } - - /** - * Returns server and Yii version information. - * @return string server version information. - */ - public function getVersionInfo() - { - $version = 'Yii Framework/' . \Yii::getVersion(); - if (isset($_SERVER['SERVER_SOFTWARE'])) { - $version = $_SERVER['SERVER_SOFTWARE'] . ' ' . $version; - } - return $version; - } - - /** - * Converts arguments array to its string representation - * - * @param array $args arguments array to be converted - * @return string string representation of the arguments array - */ - public function argumentsToString($args) - { - $isAssoc = $args !== array_values($args); - $count = 0; - foreach ($args as $key => $value) { - $count++; - if ($count >= 5) { - if ($count > 5) { - unset($args[$key]); - } else { - $args[$key] = '...'; - } - continue; - } - - if (is_object($value)) { - $args[$key] = get_class($value); - } elseif (is_bool($value)) { - $args[$key] = $value ? 'true' : 'false'; - } elseif (is_string($value)) { - if (strlen($value) > 64) { - $args[$key] = '"' . substr($value, 0, 64) . '..."'; - } else { - $args[$key] = '"' . $value . '"'; - } - } elseif (is_array($value)) { - $args[$key] = 'array(' . $this->argumentsToString($value) . ')'; - } elseif ($value === null) { - $args[$key] = 'null'; - } elseif (is_resource($value)) { - $args[$key] = 'resource'; - } - - if (is_string($key)) { - $args[$key] = '"' . $key . '" => ' . $args[$key]; - } elseif ($isAssoc) { - $args[$key] = $key . ' => ' . $args[$key]; + $view = new View(); + echo $view->renderFile($this->view, array('e' => $exception), $this); } } - return implode(', ', $args); } /** - * Returns a value indicating whether the call stack is from application code. - * @param array $trace the trace data - * @return boolean whether the call stack is from application code. + * Converts special characters to HTML entities. + * @param string $text to encode. + * @return string encoded text. */ - public function isCoreCode($trace) - { - if (isset($trace['file'])) { - return $trace['file'] === 'unknown' || strpos(realpath($trace['file']), YII_PATH . DIRECTORY_SEPARATOR) === 0; - } - return false; - } - - /** - * Renders the source code around the error line. - * @param string $file source file path - * @param integer $errorLine the error line number - * @param integer $maxLines maximum number of lines to display - */ - public function renderSourceCode($file, $errorLine, $maxLines) + public function htmlEncode($text) { - $errorLine--; // adjust line number to 0-based from 1-based - if ($errorLine < 0 || ($lines = @file($file)) === false || ($lineCount = count($lines)) <= $errorLine) { - return; - } - - $halfLines = (int)($maxLines / 2); - $beginLine = $errorLine - $halfLines > 0 ? $errorLine - $halfLines : 0; - $endLine = $errorLine + $halfLines < $lineCount ? $errorLine + $halfLines : $lineCount - 1; - $lineNumberWidth = strlen($endLine + 1); - - $output = ''; - for ($i = $beginLine; $i <= $endLine; ++$i) { - $isErrorLine = $i === $errorLine; - $code = sprintf("%0{$lineNumberWidth}d %s", $i + 1, $this->htmlEncode(str_replace("\t", ' ', $lines[$i]))); - if (!$isErrorLine) { - $output .= $code; - } else { - $output .= '' . $code . ''; - } - } - echo '
' . $output . '
'; + return htmlspecialchars($text, ENT_QUOTES, Yii::$app->charset); } /** - * Renders calls stack trace - * @param array $trace + * Removes all output echoed before calling this method. */ - public function renderTrace($trace) - { - $count = 0; - echo "\n"; - foreach ($trace as $n => $t) { - if ($this->isCoreCode($t)) { - $cssClass = 'core collapsed'; - } elseif (++$count > 3) { - $cssClass = 'app collapsed'; - } else { - $cssClass = 'app expanded'; - } - - $hasCode = isset($t['file']) && $t['file'] !== 'unknown' && is_file($t['file']); - echo "\n"; - } - echo '
#$n"; - echo '
'; - if ($hasCode) { - echo '
+
-
'; - } - echo ' '; - if (isset($t['file'])) { - echo $this->htmlEncode($t['file']) . '(' . $t['line'] . '): '; - } - if (!empty($t['class'])) { - echo '' . $t['class'] . '' . $t['type']; - } - echo '' . $t['function'] . ''; - echo '(' . (empty($t['args']) ? '' : $this->htmlEncode($this->argumentsToString($t['args']))) . ')'; - echo '
'; - if ($hasCode) { - $this->renderSourceCode($t['file'], $t['line'], $this->maxTraceSourceLines); - } - echo "
'; - } - - /** - * Converts special characters to HTML entities - * @param string $text text to encode - * @return string - */ - public function htmlEncode($text) - { - return htmlspecialchars($text, ENT_QUOTES, \Yii::$app->charset); - } - public function clearOutput() { // the following manual level counting is to deal with zlib.output_compression set to On @@ -268,16 +117,4 @@ class ErrorHandler extends Component @ob_end_clean(); } } - - /** - * @param \Exception $exception - */ - public function renderAsHtml($exception) - { - $view = new View; - $name = !YII_DEBUG || $exception instanceof HttpException ? $this->errorView : $this->exceptionView; - echo $view->renderFile($name, array( - 'exception' => $exception, - ), $this); - } } diff --git a/framework/yii/views/errorHandler.php b/framework/yii/views/errorHandler.php new file mode 100644 index 0000000..92aa812 --- /dev/null +++ b/framework/yii/views/errorHandler.php @@ -0,0 +1,303 @@ +context; +$title = $c->htmlEncode($e instanceof \yii\base\Exception ? $e->getName() : get_class($e)); +?> + + + + + + + <?php echo $title; ?> + + + + + + + +
+ Attention +

Exceptionyii\base\HttpException – 404

+

Requested user cannot be found!

+
+ +
+
+
$_GET = [
+	'show-post' => 100,
+	'refresh-page' => 'yes',
+	'ascending-sort' => 1,
+];
+
+$_POST = [
+	'blog-post-form' => [
+		'title' => 'hello',
+		'author_id' => '12',
+	],
+];
+
+$_SERVER = [
+	'DOCUMENT_ROOT' => '/home/resurtm/work/data',
+	'REMOTE_ADDR' => '::1',
+	'REMOTE_PORT' => '52694',
+	'SERVER_SOFTWARE' => 'PHP 5.4.3 Development Server',
+	'SERVER_PROTOCOL' => 'HTTP/1.1',
+	'SERVER_NAME' => 'localhost',
+	'SERVER_PORT' => '8000',
+	'REQUEST_URI' => '/index.php?post-form[title]=hello&post-form[author_id]=12',
+	'REQUEST_METHOD' => 'GET',
+	'SCRIPT_NAME' => '/index.php',
+	'SCRIPT_FILENAME' => '/home/resurtm/work/data/index.php',
+	'PHP_SELF' => '/index.php',
+	'QUERY_STRING' => 'post-form[title]=hello&post-form[author_id]=12',
+	'HTTP_HOST' => 'localhost:8000',
+	'HTTP_USER_AGENT' => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0',
+	'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
+	'HTTP_ACCEPT_LANGUAGE' => 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
+	'HTTP_ACCEPT_ENCODING' => 'gzip, deflate',
+	'HTTP_CONNECTION' => 'keep-alive',
+	'REQUEST_TIME_FLOAT' => 1369146454.0856,
+	'REQUEST_TIME' => 1369146454,
+];
+
+ + + + + + + + + + +