Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
d4ad533d
Commit
d4ad533d
authored
Mar 28, 2014
by
Carsten Brandt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
moved error handling related methods from app to errorhandler
parent
33c8f703
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
451 additions
and
448 deletions
+451
-448
Application.php
framework/base/Application.php
+9
-187
ErrorHandler.php
framework/base/ErrorHandler.php
+122
-258
Controller.php
framework/web/Controller.php
+1
-2
ErrorAction.php
framework/web/ErrorAction.php
+1
-1
ErrorHandler.php
framework/web/ErrorHandler.php
+318
-0
No files found.
framework/base/Application.php
View file @
d4ad533d
...
...
@@ -64,7 +64,6 @@ abstract class Application extends Module
* it will use the "app\controllers" namespace.
*/
public
$controllerNamespace
=
'app\\controllers'
;
/**
* @var string the application name.
*/
...
...
@@ -98,13 +97,6 @@ abstract class Application extends Module
*/
public
$layout
=
'main'
;
/**
* @var integer the size of the reserved memory. A portion of memory is pre-allocated so that
* when an out-of-memory issue occurs, the error handler is able to handle the error with
* the help of this reserved memory. If you set this value to be 0, no memory will be reserved.
* Defaults to 256KB.
*/
public
$memoryReserveSize
=
262144
;
/**
* @var string the requested route
*/
public
$requestedRoute
;
...
...
@@ -139,16 +131,7 @@ abstract class Application extends Module
* will be invoked at the beginning of [[init()]].
*/
public
$bootstrap
=
[];
/**
* @var \Exception the exception that is being handled currently. When this is not null,
* it means the application is handling some exception and extra care should be taken.
*/
public
$exception
;
/**
* @var string Used to reserve memory for fatal error handler.
*/
private
$_memoryReserve
;
/**
* Constructor.
...
...
@@ -160,8 +143,15 @@ abstract class Application extends Module
{
Yii
::
$app
=
$this
;
// TODO how to deal with exceptions thrown in preInit()
$this
->
preInit
(
$config
);
$this
->
registerErrorHandlers
();
if
(
YII_ENABLE_ERROR_HANDLER
)
{
if
(
isset
(
$config
[
'components'
][
'errorHandler'
]))
{
$this
->
set
(
'errorHandler'
,
$config
[
'components'
][
'errorHandler'
]);
unset
(
$config
[
'components'
][
'errorHandler'
]);
}
$this
->
getErrorHandler
()
->
register
();
}
Component
::
__construct
(
$config
);
}
...
...
@@ -264,22 +254,6 @@ abstract class Application extends Module
}
/**
* Registers error handlers.
*/
public
function
registerErrorHandlers
()
{
if
(
YII_ENABLE_ERROR_HANDLER
)
{
ini_set
(
'display_errors'
,
0
);
set_exception_handler
([
$this
,
'handleException'
]);
set_error_handler
([
$this
,
'handleError'
]);
if
(
$this
->
memoryReserveSize
>
0
)
{
$this
->
_memoryReserve
=
str_repeat
(
'x'
,
$this
->
memoryReserveSize
);
}
register_shutdown_function
([
$this
,
'handleFatalError'
]);
}
}
/**
* Returns an ID that uniquely identifies this module among all modules within the current application.
* Since this is an application instance, it will always return an empty string.
* @return string the unique ID of the module.
...
...
@@ -429,7 +403,7 @@ abstract class Application extends Module
*/
public
function
getErrorHandler
()
{
return
$this
->
get
(
'errorHandler'
);
return
$this
->
get
(
'errorHandler'
,
false
);
}
/**
...
...
@@ -531,156 +505,4 @@ abstract class Application extends Module
'assetManager'
=>
[
'class'
=>
'yii\web\AssetManager'
],
];
}
/**
* Handles uncaught PHP exceptions.
*
* This method is implemented as a PHP exception handler.
*
* @param \Exception $exception the exception that is not caught
*/
public
function
handleException
(
$exception
)
{
$this
->
exception
=
$exception
;
// disable error capturing to avoid recursive errors while handling exceptions
restore_error_handler
();
restore_exception_handler
();
try
{
$this
->
logException
(
$exception
);
if
((
$handler
=
$this
->
getErrorHandler
())
!==
null
)
{
$handler
->
handle
(
$exception
);
}
else
{
echo
$this
->
renderException
(
$exception
);
if
(
PHP_SAPI
===
'cli'
&&
!
YII_ENV_TEST
)
{
exit
(
1
);
}
}
}
catch
(
\Exception
$e
)
{
// exception could be thrown in ErrorHandler::handle()
$msg
=
(
string
)
$e
;
$msg
.=
"
\n
Previous exception:
\n
"
;
$msg
.=
(
string
)
$exception
;
if
(
YII_DEBUG
)
{
if
(
PHP_SAPI
===
'cli'
)
{
echo
$msg
.
"
\n
"
;
}
else
{
echo
'<pre>'
.
htmlspecialchars
(
$msg
,
ENT_QUOTES
,
$this
->
charset
)
.
'</pre>'
;
}
}
$msg
.=
"
\n\$
_SERVER = "
.
var_export
(
$_SERVER
,
true
);
error_log
(
$msg
);
exit
(
1
);
}
}
/**
* Handles PHP execution errors such as warnings, notices.
*
* This method is used as a PHP error handler. It will simply raise an `ErrorException`.
*
* @param integer $code the level of the error raised
* @param string $message the error message
* @param string $file the filename that the error was raised in
* @param integer $line the line number the error was raised at
*
* @throws ErrorException
*/
public
function
handleError
(
$code
,
$message
,
$file
,
$line
)
{
if
(
error_reporting
()
&
$code
)
{
// load ErrorException manually here because autoloading them will not work
// when error occurs while autoloading a class
if
(
!
class_exists
(
'\\yii\\base\\Exception'
,
false
))
{
require_once
(
__DIR__
.
'/Exception.php'
);
}
if
(
!
class_exists
(
'\\yii\\base\\ErrorException'
,
false
))
{
require_once
(
__DIR__
.
'/ErrorException.php'
);
}
$exception
=
new
ErrorException
(
$message
,
$code
,
$code
,
$file
,
$line
);
// in case error appeared in __toString method we can't throw any exception
$trace
=
debug_backtrace
(
false
);
array_shift
(
$trace
);
foreach
(
$trace
as
$frame
)
{
if
(
$frame
[
'function'
]
==
'__toString'
)
{
$this
->
handleException
(
$exception
);
exit
(
1
);
}
}
throw
$exception
;
}
}
/**
* Handles fatal PHP errors
*/
public
function
handleFatalError
()
{
unset
(
$this
->
_memoryReserve
);
// load ErrorException manually here because autoloading them will not work
// when error occurs while autoloading a class
if
(
!
class_exists
(
'\\yii\\base\\Exception'
,
false
))
{
require_once
(
__DIR__
.
'/Exception.php'
);
}
if
(
!
class_exists
(
'\\yii\\base\\ErrorException'
,
false
))
{
require_once
(
__DIR__
.
'/ErrorException.php'
);
}
$error
=
error_get_last
();
if
(
ErrorException
::
isFatalError
(
$error
))
{
$exception
=
new
ErrorException
(
$error
[
'message'
],
$error
[
'type'
],
$error
[
'type'
],
$error
[
'file'
],
$error
[
'line'
]);
$this
->
exception
=
$exception
;
// use error_log because it's too late to use Yii log
error_log
(
$exception
);
if
((
$handler
=
$this
->
getErrorHandler
())
!==
null
)
{
$handler
->
handle
(
$exception
);
}
else
{
echo
$this
->
renderException
(
$exception
);
}
exit
(
1
);
}
}
/**
* Renders an exception without using rich format.
* @param \Exception $exception the exception to be rendered.
* @return string the rendering result
*/
public
function
renderException
(
$exception
)
{
if
(
$exception
instanceof
Exception
&&
(
$exception
instanceof
UserException
||
!
YII_DEBUG
))
{
$message
=
$exception
->
getName
()
.
': '
.
$exception
->
getMessage
();
if
(
Yii
::
$app
->
controller
instanceof
\yii\console\Controller
)
{
$message
=
Yii
::
$app
->
controller
->
ansiFormat
(
$message
,
Console
::
FG_RED
);
}
}
else
{
$message
=
YII_DEBUG
?
(
string
)
$exception
:
'Error: '
.
$exception
->
getMessage
();
}
if
(
PHP_SAPI
===
'cli'
)
{
return
$message
.
"
\n
"
;
}
else
{
return
'<pre>'
.
htmlspecialchars
(
$message
,
ENT_QUOTES
,
$this
->
charset
)
.
'</pre>'
;
}
}
/**
* Logs the given exception
* @param \Exception $exception the exception to be logged
*/
protected
function
logException
(
$exception
)
{
$category
=
get_class
(
$exception
);
if
(
$exception
instanceof
HttpException
)
{
$category
=
'yii\\web\\HttpException:'
.
$exception
->
statusCode
;
}
elseif
(
$exception
instanceof
\ErrorException
)
{
$category
.=
':'
.
$exception
->
getSeverity
();
}
Yii
::
error
((
string
)
$exception
,
$category
);
}
}
framework/base/ErrorHandler.php
View file @
d4ad533d
...
...
@@ -8,6 +8,7 @@
namespace
yii\base
;
use
Yii
;
use
yii\helpers\Console
;
use
yii\web\HttpException
;
/**
...
...
@@ -26,330 +27,193 @@ use yii\web\HttpException;
class
ErrorHandler
extends
Component
{
/**
* @var integer maximum number of source code lines to be displayed. Defaults to 25.
*/
public
$maxSourceLines
=
25
;
/**
* @var integer maximum number of trace source code lines to be displayed. Defaults to 10.
*/
public
$maxTraceSourceLines
=
10
;
/**
* @var boolean whether to discard any existing page output before error display. Defaults to true.
*/
public
$discardExistingOutput
=
true
;
/**
* @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->exception. 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 without call stack information.
*/
public
$errorView
=
'@yii/views/errorHandler/error.php'
;
/**
* @var string the path of the view file for rendering exceptions.
* @var integer the size of the reserved memory. A portion of memory is pre-allocated so that
* when an out-of-memory issue occurs, the error handler is able to handle the error with
* the help of this reserved memory. If you set this value to be 0, no memory will be reserved.
* Defaults to 256KB.
*/
public
$exceptionView
=
'@yii/views/errorHandler/exception.php'
;
/**
* @var string the path of the view file for rendering exceptions and errors call stack element.
*/
public
$callStackItemView
=
'@yii/views/errorHandler/callStackItem.php'
;
/**
* @var string the path of the view file for rendering previous exceptions.
*/
public
$previousExceptionView
=
'@yii/views/errorHandler/previousException.php'
;
public
$memoryReserveSize
=
262144
;
/**
* @var \Exception the exception that is being handled currently.
*/
public
$exception
;
/**
* Handles exception.
* @param \Exception $exception to be handled.
* @var string Used to reserve memory for fatal error handler.
*/
public
function
handle
(
$exception
)
{
$this
->
exception
=
$exception
;
if
(
$this
->
discardExistingOutput
)
{
$this
->
clearOutput
();
}
$this
->
renderException
(
$exception
);
}
/**
* Renders the exception.
* @param \Exception $exception the exception to be handled.
*/
protected
function
renderException
(
$exception
)
{
if
(
Yii
::
$app
instanceof
\yii\console\Application
||
YII_ENV_TEST
)
{
echo
Yii
::
$app
->
renderException
(
$exception
);
if
(
!
YII_ENV_TEST
)
{
exit
(
1
);
}
return
;
}
private
$_memoryReserve
;
$response
=
Yii
::
$app
->
getResponse
();
$useErrorView
=
$response
->
format
===
\yii\web\Response
::
FORMAT_HTML
&&
(
!
YII_DEBUG
||
$exception
instanceof
UserException
);
if
(
$useErrorView
&&
$this
->
errorAction
!==
null
)
{
$result
=
Yii
::
$app
->
runAction
(
$this
->
errorAction
);
if
(
$result
instanceof
Response
)
{
$response
=
$result
;
}
else
{
$response
->
data
=
$result
;
}
}
elseif
(
$response
->
format
===
\yii\web\Response
::
FORMAT_HTML
)
{
if
(
isset
(
$_SERVER
[
'HTTP_X_REQUESTED_WITH'
])
&&
$_SERVER
[
'HTTP_X_REQUESTED_WITH'
]
===
'XMLHttpRequest'
)
{
// AJAX request
$response
->
data
=
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
if
(
YII_DEBUG
)
{
ini_set
(
'display_errors'
,
1
);
}
$file
=
$useErrorView
?
$this
->
errorView
:
$this
->
exceptionView
;
$response
->
data
=
$this
->
renderFile
(
$file
,
[
'exception'
=>
$exception
,
]);
}
}
else
{
$response
->
data
=
$this
->
convertExceptionToArray
(
$exception
);
}
if
(
$exception
instanceof
HttpException
)
{
$response
->
setStatusCode
(
$exception
->
statusCode
);
}
else
{
$response
->
setStatusCode
(
500
);
}
$response
->
send
();
}
/**
* Converts an exception into an array.
* @param \Exception $exception the exception being converted
* @return array the array representation of the exception.
* Register this errorhandler
*/
p
rotected
function
convertExceptionToArray
(
$exception
)
p
ublic
function
register
(
)
{
$array
=
[
'type'
=>
get_class
(
$exception
),
'name'
=>
$exception
instanceof
\yii\base\Exception
||
$exception
instanceof
\yii\base\ErrorException
?
$exception
->
getName
()
:
'Exception'
,
'message'
=>
$exception
->
getMessage
(),
'code'
=>
$exception
->
getCode
(),
];
if
(
YII_DEBUG
)
{
$array
[
'stack-trace'
]
=
explode
(
"
\n
"
,
$exception
->
getTraceAsString
());
// TODO care for errorReporting set to deprecated or not
ini_set
(
'display_errors'
,
0
);
set_exception_handler
([
$this
,
'handleException'
]);
set_error_handler
([
$this
,
'handleError'
]);
if
(
$this
->
memoryReserveSize
>
0
)
{
$this
->
_memoryReserve
=
str_repeat
(
'x'
,
$this
->
memoryReserveSize
);
}
if
(
$exception
instanceof
HttpException
)
{
$array
[
'status'
]
=
$exception
->
statusCode
;
}
if
((
$prev
=
$exception
->
getPrevious
())
!==
null
)
{
$array
[
'previous'
]
=
$this
->
convertExceptionToArray
(
$prev
);
}
return
$array
;
register_shutdown_function
([
$this
,
'handleFatalError'
]);
}
/**
* Converts special characters to HTML entities.
* @param string $text to encode.
* @return string encoded original text.
* Handles uncaught PHP exceptions.
*
* This method is implemented as a PHP exception handler.
*
* @param \Exception $exception the exception that is not caught
*/
public
function
h
tmlEncode
(
$text
)
public
function
h
andleException
(
$exception
)
{
return
htmlspecialchars
(
$text
,
ENT_QUOTES
,
Yii
::
$app
->
charset
);
}
$this
->
exception
=
$exception
;
/**
* Removes all output echoed before calling this method.
*/
public
function
clearOutput
()
{
// the following manual level counting is to deal with zlib.output_compression set to On
for
(
$level
=
ob_get_level
();
$level
>
0
;
--
$level
)
{
if
(
!@
ob_end_clean
())
{
ob_clean
();
// disable error capturing to avoid recursive errors while handling exceptions
restore_error_handler
();
// TODO maybe not needed
restore_exception_handler
();
try
{
$this
->
logException
(
$exception
);
// TODO set HTTP header when HTTP exception
if
(
$this
->
discardExistingOutput
)
{
$this
->
clearOutput
();
}
echo
$this
->
renderException
(
$exception
);
if
(
PHP_SAPI
===
'cli'
&&
!
YII_ENV_TEST
)
{
// TODO rethink condition
exit
(
1
);
}
}
catch
(
\Exception
$e
)
{
// an other exception could be thrown while displaying the exception
$msg
=
(
string
)
$e
;
$msg
.=
"
\n
Previous exception:
\n
"
;
$msg
.=
(
string
)
$exception
;
if
(
YII_DEBUG
)
{
if
(
PHP_SAPI
===
'cli'
)
{
echo
$msg
.
"
\n
"
;
}
else
{
echo
'<pre>'
.
htmlspecialchars
(
$msg
,
ENT_QUOTES
,
$this
->
charset
)
.
'</pre>'
;
}
/**
* Adds informational links to the given PHP type/class.
* @param string $code type/class name to be linkified.
* @return string linkified with HTML type/class name.
*/
public
function
addTypeLinks
(
$code
)
{
$html
=
''
;
if
(
strpos
(
$code
,
'\\'
)
!==
false
)
{
// namespaced class
foreach
(
explode
(
'\\'
,
$code
)
as
$part
)
{
$html
.=
'<a href="http://yiiframework.com/doc/api/2.0/'
.
$this
->
htmlEncode
(
$part
)
.
'" target="_blank">'
.
$this
->
htmlEncode
(
$part
)
.
'</a>\\'
;
}
$html
=
rtrim
(
$html
,
'\\'
);
}
elseif
(
strpos
(
$code
,
'()'
)
!==
false
)
{
// method/function call
$html
=
preg_replace_callback
(
'/^(.*)\(\)$/'
,
function
(
$matches
)
{
return
'<a href="http://yiiframework.com/doc/api/2.0/'
.
$this
->
htmlEncode
(
$matches
[
1
])
.
'" target="_blank">'
.
$this
->
htmlEncode
(
$matches
[
1
])
.
'</a>()'
;
},
$code
);
$msg
.=
"
\n\$
_SERVER = "
.
var_export
(
$_SERVER
,
true
);
error_log
(
$msg
);
exit
(
1
);
}
return
$html
;
}
/**
* Renders a view file as a PHP script.
* @param string $_file_ the view file.
* @param array $_params_ the parameters (name-value pairs) that will be extracted and made available in the view file.
* @return string the rendering result
* Handles PHP execution errors such as warnings and notices.
*
* This method is used as a PHP error handler. It will simply raise an [[ErrorException]].
*
* @param integer $code the level of the error raised.
* @param string $message the error message.
* @param string $file the filename that the error was raised in.
* @param integer $line the line number the error was raised at.
*
* @throws ErrorException
*/
public
function
renderFile
(
$_file_
,
$_params_
)
public
function
handleError
(
$code
,
$message
,
$file
,
$line
)
{
$_params_
[
'handler'
]
=
$this
;
if
(
$this
->
exception
instanceof
ErrorException
)
{
ob_start
();
ob_implicit_flush
(
false
);
extract
(
$_params_
,
EXTR_OVERWRITE
);
require
(
Yii
::
getAlias
(
$_file_
));
return
ob_get_clean
();
}
else
{
return
Yii
::
$app
->
getView
()
->
renderFile
(
$_file_
,
$_params_
,
$this
);
if
(
error_reporting
()
&
$code
)
{
// load ErrorException manually here because autoloading them will not work
// when error occurs while autoloading a class
if
(
!
class_exists
(
'\\yii\\base\\ErrorException'
,
false
))
{
require_once
(
__DIR__
.
'/ErrorException.php'
);
}
$exception
=
new
ErrorException
(
$message
,
$code
,
$code
,
$file
,
$line
);
// in case error appeared in __toString method we can't throw any exception
$trace
=
debug_backtrace
(
0
);
array_shift
(
$trace
);
foreach
(
$trace
as
$frame
)
{
if
(
$frame
[
'function'
]
==
'__toString'
)
{
$this
->
handleException
(
$exception
);
exit
(
1
);
}
}
/**
* Renders the previous exception stack for a given Exception.
* @param \Exception $exception the exception whose precursors should be rendered.
* @return string HTML content of the rendered previous exceptions.
* Empty string if there are none.
*/
public
function
renderPreviousExceptions
(
$exception
)
{
if
((
$previous
=
$exception
->
getPrevious
())
!==
null
)
{
return
$this
->
renderFile
(
$this
->
previousExceptionView
,
[
'exception'
=>
$previous
]);
}
else
{
return
''
;
throw
$exception
;
}
}
/**
* Renders a single call stack element.
* @param string|null $file name where call has happened.
* @param integer|null $line number on which call has happened.
* @param string|null $class called class name.
* @param string|null $method called function/method name.
* @param integer $index number of the call stack element.
* @return string HTML content of the rendered call stack element.
* Handles fatal PHP errors
*/
public
function
renderCallStackItem
(
$file
,
$line
,
$class
,
$method
,
$index
)
public
function
handleFatalError
(
)
{
$lines
=
[];
$begin
=
$end
=
0
;
if
(
$file
!==
null
&&
$line
!==
null
)
{
$line
--
;
// adjust line number from one-based to zero-based
$lines
=
@
file
(
$file
);
if
(
$line
<
0
||
$lines
===
false
||
(
$lineCount
=
count
(
$lines
))
<
$line
+
1
)
{
return
''
;
}
unset
(
$this
->
_memoryReserve
);
$half
=
(
int
)
((
$index
==
0
?
$this
->
maxSourceLines
:
$this
->
maxTraceSourceLines
)
/
2
);
$begin
=
$line
-
$half
>
0
?
$line
-
$half
:
0
;
$end
=
$line
+
$half
<
$lineCount
?
$line
+
$half
:
$lineCount
-
1
;
// load ErrorException manually here because autoloading them will not work
// when error occurs while autoloading a class
if
(
!
class_exists
(
'\\yii\\base\\ErrorException'
,
false
))
{
require_once
(
__DIR__
.
'/ErrorException.php'
);
}
return
$this
->
renderFile
(
$this
->
callStackItemView
,
[
'file'
=>
$file
,
'line'
=>
$line
,
'class'
=>
$class
,
'method'
=>
$method
,
'index'
=>
$index
,
'lines'
=>
$lines
,
'begin'
=>
$begin
,
'end'
=>
$end
,
]);
$error
=
error_get_last
();
if
(
ErrorException
::
isFatalError
(
$error
))
{
$exception
=
new
ErrorException
(
$error
[
'message'
],
$error
[
'type'
],
$error
[
'type'
],
$error
[
'file'
],
$error
[
'line'
]);
$this
->
exception
=
$exception
;
// use error_log because it's too late to use Yii log
error_log
(
$exception
);
if
(
$this
->
discardExistingOutput
)
{
$this
->
clearOutput
();
}
echo
$this
->
renderException
(
$exception
);
exit
(
1
);
}
}
/**
* Renders the request information.
* Renders an exception without using rich format.
* @param \Exception $exception the exception to be rendered.
* @return string the rendering result
*/
p
ublic
function
renderRequest
(
)
p
rotected
function
renderException
(
$exception
)
{
$request
=
''
;
foreach
([
'_GET'
,
'_POST'
,
'_SERVER'
,
'_FILES'
,
'_COOKIE'
,
'_SESSION'
,
'_ENV'
]
as
$name
)
{
if
(
!
empty
(
$GLOBALS
[
$name
])
)
{
$
request
.=
'$'
.
$name
.
' = '
.
var_export
(
$GLOBALS
[
$name
],
true
)
.
";
\n\n
"
;
if
(
$exception
instanceof
Exception
&&
(
$exception
instanceof
UserException
||
!
YII_DEBUG
))
{
$message
=
$exception
->
getName
()
.
': '
.
$exception
->
getMessage
();
if
(
Yii
::
$app
->
controller
instanceof
\yii\console\Controller
)
{
$
message
=
Yii
::
$app
->
controller
->
ansiFormat
(
$message
,
Console
::
FG_RED
)
;
}
}
else
{
$message
=
YII_DEBUG
?
(
string
)
$exception
:
'Error: '
.
$exception
->
getMessage
();
// TODO improve output
}
return
'<pre>'
.
rtrim
(
$request
,
"
\n
"
)
.
'</pre>'
;
return
$message
.
"
\n
"
;
}
/**
* Determines whether given name of the file belongs to the framework.
* @param string $file name to be checked.
* @return boolean whether given name of the file belongs to the framework.
* Logs the given exception
* @param \Exception $exception the exception to be logged
*/
p
ublic
function
isCoreFile
(
$file
)
p
rotected
function
logException
(
$exception
)
{
return
$file
===
null
||
strpos
(
realpath
(
$file
),
YII_PATH
.
DIRECTORY_SEPARATOR
)
===
0
;
// TODO logger may not be registered
$category
=
get_class
(
$exception
);
if
(
$exception
instanceof
HttpException
)
{
$category
=
'yii\\web\\HttpException:'
.
$exception
->
statusCode
;
}
elseif
(
$exception
instanceof
\ErrorException
)
{
$category
.=
':'
.
$exception
->
getSeverity
();
}
/**
* Creates HTML containing link to the page with the information on given HTTP status code.
* @param integer $statusCode to be used to generate information link.
* @param string $statusDescription Description to display after the the status code.
* @return string generated HTML with HTTP status code information.
*/
public
function
createHttpStatusLink
(
$statusCode
,
$statusDescription
)
{
return
'<a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#'
.
(
int
)
$statusCode
.
'" target="_blank">HTTP '
.
(
int
)
$statusCode
.
' – '
.
$statusDescription
.
'</a>'
;
Yii
::
error
((
string
)
$exception
,
$category
);
}
/**
* Creates string containing HTML link which refers to the home page of determined web-server software
* and its full name.
* @return string server software information hyperlink.
* Removes all output echoed before calling this method.
*/
public
function
c
reateServerInformationLink
()
public
function
c
learOutput
()
{
static
$serverUrls
=
[
'http://httpd.apache.org/'
=>
[
'apache'
],
'http://nginx.org/'
=>
[
'nginx'
],
'http://lighttpd.net/'
=>
[
'lighttpd'
],
'http://gwan.com/'
=>
[
'g-wan'
,
'gwan'
],
'http://iis.net/'
=>
[
'iis'
,
'services'
],
'http://php.net/manual/en/features.commandline.webserver.php'
=>
[
'development'
],
];
if
(
isset
(
$_SERVER
[
'SERVER_SOFTWARE'
]))
{
foreach
(
$serverUrls
as
$url
=>
$keywords
)
{
foreach
(
$keywords
as
$keyword
)
{
if
(
stripos
(
$_SERVER
[
'SERVER_SOFTWARE'
],
$keyword
)
!==
false
)
{
return
'<a href="'
.
$url
.
'" target="_blank">'
.
$this
->
htmlEncode
(
$_SERVER
[
'SERVER_SOFTWARE'
])
.
'</a>'
;
}
}
}
// the following manual level counting is to deal with zlib.output_compression set to On
for
(
$level
=
ob_get_level
();
$level
>
0
;
--
$level
)
{
if
(
!@
ob_end_clean
())
{
ob_clean
();
}
return
''
;
}
/**
* Creates string containing HTML link which refers to the page with the current version
* of the framework and version number text.
* @return string framework version information hyperlink.
*/
public
function
createFrameworkVersionLink
()
{
return
'<a href="http://github.com/yiisoft/yii2/" target="_blank">'
.
$this
->
htmlEncode
(
Yii
::
getVersion
())
.
'</a>'
;
}
}
framework/web/Controller.php
View file @
d4ad533d
...
...
@@ -105,10 +105,9 @@ class Controller extends \yii\base\Controller
public
function
beforeAction
(
$action
)
{
if
(
parent
::
beforeAction
(
$action
))
{
if
(
$this
->
enableCsrfValidation
&&
Yii
::
$app
->
exception
===
null
&&
!
Yii
::
$app
->
getRequest
()
->
validateCsrfToken
())
{
if
(
$this
->
enableCsrfValidation
&&
Yii
::
$app
->
e
rrorHandler
->
e
xception
===
null
&&
!
Yii
::
$app
->
getRequest
()
->
validateCsrfToken
())
{
throw
new
BadRequestHttpException
(
Yii
::
t
(
'yii'
,
'Unable to verify your data submission.'
));
}
return
true
;
}
else
{
return
false
;
...
...
framework/web/ErrorAction.php
View file @
d4ad533d
...
...
@@ -68,7 +68,7 @@ class ErrorAction extends Action
public
function
run
()
{
if
((
$exception
=
Yii
::
$app
->
exception
)
===
null
)
{
if
((
$exception
=
Yii
::
$app
->
e
rrorHandler
->
e
xception
)
===
null
)
{
return
''
;
}
...
...
framework/web/ErrorHandler.php
0 → 100644
View file @
d4ad533d
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\web
;
use
Yii
;
use
yii\base\ErrorException
;
use
yii\base\UserException
;
/**
* ErrorHandler handles uncaught PHP errors and exceptions.
*
* ErrorHandler displays these errors using appropriate views based on the
* nature of the errors and the mode the application runs at.
*
* ErrorHandler is configured as an application component in [[\yii\base\Application]] by default.
* You can access that instance via `Yii::$app->errorHandler`.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @author Timur Ruziev <resurtm@gmail.com>
* @since 2.0
*/
class
ErrorHandler
extends
\yii\base\ErrorHandler
{
/**
* @var integer maximum number of source code lines to be displayed. Defaults to 25.
*/
public
$maxSourceLines
=
25
;
/**
* @var integer maximum number of trace source code lines to be displayed. Defaults to 10.
*/
public
$maxTraceSourceLines
=
10
;
/**
* @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->exception. 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 without call stack information.
*/
public
$errorView
=
'@yii/views/errorHandler/error.php'
;
/**
* @var string the path of the view file for rendering exceptions.
*/
public
$exceptionView
=
'@yii/views/errorHandler/exception.php'
;
/**
* @var string the path of the view file for rendering exceptions and errors call stack element.
*/
public
$callStackItemView
=
'@yii/views/errorHandler/callStackItem.php'
;
/**
* @var string the path of the view file for rendering previous exceptions.
*/
public
$previousExceptionView
=
'@yii/views/errorHandler/previousException.php'
;
/**
* Renders the exception.
* @param \Exception $exception the exception to be handled.
*/
protected
function
renderException
(
$exception
)
{
// TODO what to do different in test env?
// parent::renderException($exception); + <pre>
$response
=
Yii
::
$app
->
getResponse
();
$useErrorView
=
$response
->
format
===
\yii\web\Response
::
FORMAT_HTML
&&
(
!
YII_DEBUG
||
$exception
instanceof
UserException
);
if
(
$useErrorView
&&
$this
->
errorAction
!==
null
)
{
$result
=
Yii
::
$app
->
runAction
(
$this
->
errorAction
);
if
(
$result
instanceof
Response
)
{
$response
=
$result
;
}
else
{
$response
->
data
=
$result
;
}
}
elseif
(
$response
->
format
===
\yii\web\Response
::
FORMAT_HTML
)
{
if
(
isset
(
$_SERVER
[
'HTTP_X_REQUESTED_WITH'
])
&&
$_SERVER
[
'HTTP_X_REQUESTED_WITH'
]
===
'XMLHttpRequest'
)
{
// AJAX request
$response
->
data
=
'<pre>'
.
htmlspecialchars
(
parent
::
renderException
(
$exception
),
ENT_QUOTES
,
$this
->
charset
)
.
'</pre>'
;
}
else
{
// if there is an error during error rendering it's useful to
// display PHP error in debug mode instead of a blank screen
if
(
YII_DEBUG
)
{
ini_set
(
'display_errors'
,
1
);
}
$file
=
$useErrorView
?
$this
->
errorView
:
$this
->
exceptionView
;
$response
->
data
=
$this
->
renderFile
(
$file
,
[
'exception'
=>
$exception
,
]);
}
}
else
{
$response
->
data
=
$this
->
convertExceptionToArray
(
$exception
);
}
if
(
$exception
instanceof
HttpException
)
{
$response
->
setStatusCode
(
$exception
->
statusCode
);
}
else
{
$response
->
setStatusCode
(
500
);
}
$response
->
send
();
}
/**
* Converts an exception into an array.
* @param \Exception $exception the exception being converted
* @return array the array representation of the exception.
*/
protected
function
convertExceptionToArray
(
$exception
)
{
$array
=
[
'type'
=>
get_class
(
$exception
),
'name'
=>
$exception
instanceof
\yii\base\Exception
||
$exception
instanceof
\yii\base\ErrorException
?
$exception
->
getName
()
:
'Exception'
,
'message'
=>
$exception
->
getMessage
(),
'code'
=>
$exception
->
getCode
(),
];
if
(
YII_DEBUG
)
{
$array
[
'stack-trace'
]
=
explode
(
"
\n
"
,
$exception
->
getTraceAsString
());
}
if
(
$exception
instanceof
HttpException
)
{
$array
[
'status'
]
=
$exception
->
statusCode
;
}
if
((
$prev
=
$exception
->
getPrevious
())
!==
null
)
{
$array
[
'previous'
]
=
$this
->
convertExceptionToArray
(
$prev
);
}
return
$array
;
}
/**
* Converts special characters to HTML entities.
* @param string $text to encode.
* @return string encoded original text.
*/
public
function
htmlEncode
(
$text
)
{
return
htmlspecialchars
(
$text
,
ENT_QUOTES
,
Yii
::
$app
->
charset
);
}
/**
* Adds informational links to the given PHP type/class.
* @param string $code type/class name to be linkified.
* @return string linkified with HTML type/class name.
*/
public
function
addTypeLinks
(
$code
)
{
$html
=
''
;
if
(
strpos
(
$code
,
'\\'
)
!==
false
)
{
// namespaced class
foreach
(
explode
(
'\\'
,
$code
)
as
$part
)
{
$html
.=
'<a href="http://yiiframework.com/doc/api/2.0/'
.
$this
->
htmlEncode
(
$part
)
.
'" target="_blank">'
.
$this
->
htmlEncode
(
$part
)
.
'</a>\\'
;
}
$html
=
rtrim
(
$html
,
'\\'
);
}
elseif
(
strpos
(
$code
,
'()'
)
!==
false
)
{
// method/function call
$html
=
preg_replace_callback
(
'/^(.*)\(\)$/'
,
function
(
$matches
)
{
return
'<a href="http://yiiframework.com/doc/api/2.0/'
.
$this
->
htmlEncode
(
$matches
[
1
])
.
'" target="_blank">'
.
$this
->
htmlEncode
(
$matches
[
1
])
.
'</a>()'
;
},
$code
);
}
return
$html
;
}
/**
* Renders a view file as a PHP script.
* @param string $_file_ the view file.
* @param array $_params_ the parameters (name-value pairs) that will be extracted and made available in the view file.
* @return string the rendering result
*/
public
function
renderFile
(
$_file_
,
$_params_
)
{
$_params_
[
'handler'
]
=
$this
;
if
(
$this
->
exception
instanceof
ErrorException
)
{
ob_start
();
ob_implicit_flush
(
false
);
extract
(
$_params_
,
EXTR_OVERWRITE
);
require
(
Yii
::
getAlias
(
$_file_
));
return
ob_get_clean
();
}
else
{
return
Yii
::
$app
->
getView
()
->
renderFile
(
$_file_
,
$_params_
,
$this
);
}
}
/**
* Renders the previous exception stack for a given Exception.
* @param \Exception $exception the exception whose precursors should be rendered.
* @return string HTML content of the rendered previous exceptions.
* Empty string if there are none.
*/
public
function
renderPreviousExceptions
(
$exception
)
{
if
((
$previous
=
$exception
->
getPrevious
())
!==
null
)
{
return
$this
->
renderFile
(
$this
->
previousExceptionView
,
[
'exception'
=>
$previous
]);
}
else
{
return
''
;
}
}
/**
* Renders a single call stack element.
* @param string|null $file name where call has happened.
* @param integer|null $line number on which call has happened.
* @param string|null $class called class name.
* @param string|null $method called function/method name.
* @param integer $index number of the call stack element.
* @return string HTML content of the rendered call stack element.
*/
public
function
renderCallStackItem
(
$file
,
$line
,
$class
,
$method
,
$index
)
{
$lines
=
[];
$begin
=
$end
=
0
;
if
(
$file
!==
null
&&
$line
!==
null
)
{
$line
--
;
// adjust line number from one-based to zero-based
$lines
=
@
file
(
$file
);
if
(
$line
<
0
||
$lines
===
false
||
(
$lineCount
=
count
(
$lines
))
<
$line
+
1
)
{
return
''
;
}
$half
=
(
int
)
((
$index
==
0
?
$this
->
maxSourceLines
:
$this
->
maxTraceSourceLines
)
/
2
);
$begin
=
$line
-
$half
>
0
?
$line
-
$half
:
0
;
$end
=
$line
+
$half
<
$lineCount
?
$line
+
$half
:
$lineCount
-
1
;
}
return
$this
->
renderFile
(
$this
->
callStackItemView
,
[
'file'
=>
$file
,
'line'
=>
$line
,
'class'
=>
$class
,
'method'
=>
$method
,
'index'
=>
$index
,
'lines'
=>
$lines
,
'begin'
=>
$begin
,
'end'
=>
$end
,
]);
}
/**
* Renders the request information.
* @return string the rendering result
*/
public
function
renderRequest
()
{
$request
=
''
;
foreach
([
'_GET'
,
'_POST'
,
'_SERVER'
,
'_FILES'
,
'_COOKIE'
,
'_SESSION'
,
'_ENV'
]
as
$name
)
{
if
(
!
empty
(
$GLOBALS
[
$name
]))
{
$request
.=
'$'
.
$name
.
' = '
.
var_export
(
$GLOBALS
[
$name
],
true
)
.
";
\n\n
"
;
}
}
return
'<pre>'
.
rtrim
(
$request
,
"
\n
"
)
.
'</pre>'
;
}
/**
* Determines whether given name of the file belongs to the framework.
* @param string $file name to be checked.
* @return boolean whether given name of the file belongs to the framework.
*/
public
function
isCoreFile
(
$file
)
{
return
$file
===
null
||
strpos
(
realpath
(
$file
),
YII_PATH
.
DIRECTORY_SEPARATOR
)
===
0
;
}
/**
* Creates HTML containing link to the page with the information on given HTTP status code.
* @param integer $statusCode to be used to generate information link.
* @param string $statusDescription Description to display after the the status code.
* @return string generated HTML with HTTP status code information.
*/
public
function
createHttpStatusLink
(
$statusCode
,
$statusDescription
)
{
return
'<a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes#'
.
(
int
)
$statusCode
.
'" target="_blank">HTTP '
.
(
int
)
$statusCode
.
' – '
.
$statusDescription
.
'</a>'
;
}
/**
* Creates string containing HTML link which refers to the home page of determined web-server software
* and its full name.
* @return string server software information hyperlink.
*/
public
function
createServerInformationLink
()
{
static
$serverUrls
=
[
'http://httpd.apache.org/'
=>
[
'apache'
],
'http://nginx.org/'
=>
[
'nginx'
],
'http://lighttpd.net/'
=>
[
'lighttpd'
],
'http://gwan.com/'
=>
[
'g-wan'
,
'gwan'
],
'http://iis.net/'
=>
[
'iis'
,
'services'
],
'http://php.net/manual/en/features.commandline.webserver.php'
=>
[
'development'
],
];
if
(
isset
(
$_SERVER
[
'SERVER_SOFTWARE'
]))
{
foreach
(
$serverUrls
as
$url
=>
$keywords
)
{
foreach
(
$keywords
as
$keyword
)
{
if
(
stripos
(
$_SERVER
[
'SERVER_SOFTWARE'
],
$keyword
)
!==
false
)
{
return
'<a href="'
.
$url
.
'" target="_blank">'
.
$this
->
htmlEncode
(
$_SERVER
[
'SERVER_SOFTWARE'
])
.
'</a>'
;
}
}
}
}
return
''
;
}
/**
* Creates string containing HTML link which refers to the page with the current version
* of the framework and version number text.
* @return string framework version information hyperlink.
*/
public
function
createFrameworkVersionLink
()
{
return
'<a href="http://github.com/yiisoft/yii2/" target="_blank">'
.
$this
->
htmlEncode
(
Yii
::
getVersion
())
.
'</a>'
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment