the whole shebang
This commit is contained in:
14
vendor/filp/whoops/src/Whoops/Exception/ErrorException.php
vendored
Normal file
14
vendor/filp/whoops/src/Whoops/Exception/ErrorException.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Exception;
|
||||
use ErrorException as BaseErrorException;
|
||||
|
||||
/**
|
||||
* Wraps ErrorException; mostly used for typing (at least now)
|
||||
* to easily cleanup the stack trace of redundant info.
|
||||
*/
|
||||
class ErrorException extends BaseErrorException {}
|
228
vendor/filp/whoops/src/Whoops/Exception/Frame.php
vendored
Normal file
228
vendor/filp/whoops/src/Whoops/Exception/Frame.php
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Exception;
|
||||
use InvalidArgumentException;
|
||||
use Serializable;
|
||||
|
||||
class Frame implements Serializable
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $frame;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $fileContentsCache;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
protected $comments = array();
|
||||
|
||||
/**
|
||||
* @param array[]
|
||||
*/
|
||||
public function __construct(array $frame)
|
||||
{
|
||||
$this->frame = $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $shortened
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFile($shortened = false)
|
||||
{
|
||||
$file = !empty($this->frame['file']) ? $this->frame['file'] : null;
|
||||
if ($shortened && is_string($file)) {
|
||||
// Replace the part of the path that all frames have in common, and add 'soft hyphens' for smoother line-breaks.
|
||||
$dirname = dirname(dirname(dirname(dirname(dirname(dirname(__DIR__))))));
|
||||
$file = str_replace($dirname, "…", $file);
|
||||
$file = str_replace("/", "/­", $file);
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLine()
|
||||
{
|
||||
return isset($this->frame['line']) ? $this->frame['line'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getClass()
|
||||
{
|
||||
return isset($this->frame['class']) ? $this->frame['class'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFunction()
|
||||
{
|
||||
return isset($this->frame['function']) ? $this->frame['function'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getArgs()
|
||||
{
|
||||
return isset($this->frame['args']) ? (array) $this->frame['args'] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full contents of the file for this frame,
|
||||
* if it's known.
|
||||
* @return string|null
|
||||
*/
|
||||
public function getFileContents()
|
||||
{
|
||||
if($this->fileContentsCache === null && $filePath = $this->getFile()) {
|
||||
$this->fileContentsCache = file_get_contents($filePath);
|
||||
}
|
||||
|
||||
return $this->fileContentsCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comment to this frame, that can be received and
|
||||
* used by other handlers. For example, the PrettyPage handler
|
||||
* can attach these comments under the code for each frame.
|
||||
*
|
||||
* An interesting use for this would be, for example, code analysis
|
||||
* & annotations.
|
||||
*
|
||||
* @param string $comment
|
||||
* @param string $context Optional string identifying the origin of the comment
|
||||
*/
|
||||
public function addComment($comment, $context = 'global')
|
||||
{
|
||||
$this->comments[] = array(
|
||||
'comment' => $comment,
|
||||
'context' => $context
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all comments for this frame. Optionally allows
|
||||
* a filter to only retrieve comments from a specific
|
||||
* context.
|
||||
*
|
||||
* @param string $filter
|
||||
* @return array[]
|
||||
*/
|
||||
public function getComments($filter = null)
|
||||
{
|
||||
$comments = $this->comments;
|
||||
|
||||
if($filter !== null) {
|
||||
$comments = array_filter($comments, function($c) use($filter) {
|
||||
return $c['context'] == $filter;
|
||||
});
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the array containing the raw frame data from which
|
||||
* this Frame object was built
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRawFrame()
|
||||
{
|
||||
return $this->frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the file for this frame as an
|
||||
* array of lines, and optionally as a clamped range of lines.
|
||||
*
|
||||
* NOTE: lines are 0-indexed
|
||||
*
|
||||
* @example
|
||||
* Get all lines for this file
|
||||
* $frame->getFileLines(); // => array( 0 => '<?php', 1 => '...', ...)
|
||||
* @example
|
||||
* Get one line for this file, starting at line 10 (zero-indexed, remember!)
|
||||
* $frame->getFileLines(9, 1); // array( 10 => '...', 11 => '...')
|
||||
*
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
* @return string[]|null
|
||||
*/
|
||||
public function getFileLines($start = 0, $length = null)
|
||||
{
|
||||
if(null !== ($contents = $this->getFileContents())) {
|
||||
$lines = explode("\n", $contents);
|
||||
|
||||
// Get a subset of lines from $start to $end
|
||||
if($length !== null)
|
||||
{
|
||||
$start = (int) $start;
|
||||
$length = (int) $length;
|
||||
if ($start < 0) {
|
||||
$start = 0;
|
||||
}
|
||||
|
||||
if($length <= 0) {
|
||||
throw new InvalidArgumentException(
|
||||
"\$length($length) cannot be lower or equal to 0"
|
||||
);
|
||||
}
|
||||
|
||||
$lines = array_slice($lines, $start, $length, true);
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the Serializable interface, with special
|
||||
* steps to also save the existing comments.
|
||||
*
|
||||
* @see Serializable::serialize
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
$frame = $this->frame;
|
||||
if(!empty($this->comments)) {
|
||||
$frame['_comments'] = $this->comments;
|
||||
}
|
||||
|
||||
return serialize($frame);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserializes the frame data, while also preserving
|
||||
* any existing comment data.
|
||||
*
|
||||
* @see Serializable::unserialize
|
||||
* @param string $serializedFrame
|
||||
*/
|
||||
public function unserialize($serializedFrame)
|
||||
{
|
||||
$frame = unserialize($serializedFrame);
|
||||
|
||||
if(!empty($frame['_comments'])) {
|
||||
$this->comments = $frame['_comments'];
|
||||
unset($frame['_comments']);
|
||||
}
|
||||
|
||||
$this->frame = $frame;
|
||||
}
|
||||
}
|
122
vendor/filp/whoops/src/Whoops/Exception/FrameCollection.php
vendored
Normal file
122
vendor/filp/whoops/src/Whoops/Exception/FrameCollection.php
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Exception;
|
||||
use Whoops\Exception\Frame;
|
||||
use UnexpectedValueException;
|
||||
use IteratorAggregate;
|
||||
use ArrayIterator;
|
||||
use Serializable;
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* Exposes a fluent interface for dealing with an ordered list
|
||||
* of stack-trace frames.
|
||||
*/
|
||||
class FrameCollection implements IteratorAggregate, Serializable, Countable
|
||||
{
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
private $frames;
|
||||
|
||||
/**
|
||||
* @param array $frames
|
||||
*/
|
||||
public function __construct(array $frames)
|
||||
{
|
||||
$this->frames = array_map(function($frame) {
|
||||
return new Frame($frame);
|
||||
}, $frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters frames using a callable, returns the same FrameCollection
|
||||
*
|
||||
* @param callable $callable
|
||||
* @return Whoops\Exception\FrameCollection
|
||||
*/
|
||||
public function filter($callable)
|
||||
{
|
||||
$this->frames = array_filter($this->frames, $callable);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the collection of frames
|
||||
*
|
||||
* @param callable $callable
|
||||
* @return Whoops\Exception\FrameCollection
|
||||
*/
|
||||
public function map($callable)
|
||||
{
|
||||
// Contain the map within a higher-order callable
|
||||
// that enforces type-correctness for the $callable
|
||||
$this->frames = array_map(function($frame) use($callable) {
|
||||
$frame = call_user_func($callable, $frame);
|
||||
|
||||
if(!$frame instanceof Frame) {
|
||||
throw new UnexpectedValueException(
|
||||
"Callable to " . __METHOD__ . " must return a Frame object"
|
||||
);
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}, $this->frames);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all frames, does not affect
|
||||
* the internal array.
|
||||
*
|
||||
* @todo If this gets any more complex than this,
|
||||
* have getIterator use this method.
|
||||
* @see Whoops\Exception\FrameCollection::getIterator
|
||||
* @return array
|
||||
*/
|
||||
public function getArray()
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IteratorAggregate::getIterator
|
||||
* @return ArrayIterator
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new ArrayIterator($this->frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Countable::count
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return count($this->frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Serializable::serialize
|
||||
* @return string
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
return serialize($this->frames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Serializable::unserialize
|
||||
* @param string $serializedFrames
|
||||
*/
|
||||
public function unserialize($serializedFrames)
|
||||
{
|
||||
$this->frames = unserialize($serializedFrames);
|
||||
}
|
||||
}
|
115
vendor/filp/whoops/src/Whoops/Exception/Inspector.php
vendored
Normal file
115
vendor/filp/whoops/src/Whoops/Exception/Inspector.php
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Exception;
|
||||
use Whoops\Exception\FrameCollection;
|
||||
use Whoops\Exception\ErrorException;
|
||||
use Exception;
|
||||
|
||||
class Inspector
|
||||
{
|
||||
/**
|
||||
* @var Exception
|
||||
*/
|
||||
private $exception;
|
||||
|
||||
/**
|
||||
* @var Whoops\Exception\FrameCollection
|
||||
*/
|
||||
private $frames;
|
||||
|
||||
/**
|
||||
* @param Exception $exception The exception to inspect
|
||||
*/
|
||||
public function __construct(Exception $exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exception
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getExceptionName()
|
||||
{
|
||||
return get_class($this->exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getExceptionMessage()
|
||||
{
|
||||
return $this->exception->getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for the inspected exception's
|
||||
* frames.
|
||||
* @return Whoops\Exception\FrameCollection
|
||||
*/
|
||||
public function getFrames()
|
||||
{
|
||||
if($this->frames === null) {
|
||||
$frames = $this->exception->getTrace();
|
||||
|
||||
// If we're handling an ErrorException thrown by Whoops,
|
||||
// get rid of the last frame, which matches the handleError method,
|
||||
// and do not add the current exception to trace. We ensure that
|
||||
// the next frame does have a filename / linenumber, though.
|
||||
if($this->exception instanceof ErrorException && empty($frames[1]['line'])) {
|
||||
$frames = array($this->getFrameFromError($this->exception));
|
||||
} else {
|
||||
$firstFrame = $this->getFrameFromException($this->exception);
|
||||
array_unshift($frames, $firstFrame);
|
||||
}
|
||||
$this->frames = new FrameCollection($frames);
|
||||
}
|
||||
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an exception, generates an array in the format
|
||||
* generated by Exception::getTrace()
|
||||
* @param Exception $exception
|
||||
* @return array
|
||||
*/
|
||||
protected function getFrameFromException(Exception $exception)
|
||||
{
|
||||
return array(
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
'class' => get_class($exception),
|
||||
'args' => array(
|
||||
$exception->getMessage()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an error, generates an array in the format
|
||||
* generated by ErrorException
|
||||
* @param ErrorException $exception
|
||||
* @return array
|
||||
*/
|
||||
protected function getFrameFromError(ErrorException $exception)
|
||||
{
|
||||
return array(
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine(),
|
||||
'class' => null,
|
||||
'args' => array()
|
||||
);
|
||||
}
|
||||
}
|
48
vendor/filp/whoops/src/Whoops/Handler/CallbackHandler.php
vendored
Normal file
48
vendor/filp/whoops/src/Whoops/Handler/CallbackHandler.php
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
use Whoops\Handler\Handler;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Wrapper for Closures passed as handlers. Can be used
|
||||
* directly, or will be instantiated automagically by Whoops\Run
|
||||
* if passed to Run::pushHandler
|
||||
*/
|
||||
class CallbackHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
protected $callable;
|
||||
|
||||
/**
|
||||
* @param callable $callable
|
||||
*/
|
||||
public function __construct($callable)
|
||||
{
|
||||
if(!is_callable($callable)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Argument to ' . __METHOD__ . ' must be valid callable'
|
||||
);
|
||||
}
|
||||
|
||||
$this->callable = $callable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$exception = $this->getException();
|
||||
$inspector = $this->getInspector();
|
||||
$run = $this->getRun();
|
||||
|
||||
return call_user_func($this->callable, $exception, $inspector, $run);
|
||||
}
|
||||
}
|
89
vendor/filp/whoops/src/Whoops/Handler/Handler.php
vendored
Normal file
89
vendor/filp/whoops/src/Whoops/Handler/Handler.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
use Whoops\Handler\HandlerInterface;
|
||||
use Whoops\Exception\Inspector;
|
||||
use Whoops\Run;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Abstract implementation of a Handler.
|
||||
*/
|
||||
abstract class Handler implements HandlerInterface
|
||||
{
|
||||
/**
|
||||
* Return constants that can be returned from Handler::handle
|
||||
* to message the handler walker.
|
||||
*/
|
||||
const DONE = 0x10; // returning this is optional, only exists for
|
||||
// semantic purposes
|
||||
const LAST_HANDLER = 0x20;
|
||||
const QUIT = 0x30;
|
||||
|
||||
/**
|
||||
* @var Whoops\Run
|
||||
*/
|
||||
private $run;
|
||||
|
||||
/**
|
||||
* @var Whoops\Exception\Inspector $inspector
|
||||
*/
|
||||
private $inspector;
|
||||
|
||||
/**
|
||||
* @var Exception $exception
|
||||
*/
|
||||
private $exception;
|
||||
|
||||
/**
|
||||
* @param Whoops\Run $run
|
||||
*/
|
||||
public function setRun(Run $run)
|
||||
{
|
||||
$this->run = $run;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whoops\Run
|
||||
*/
|
||||
protected function getRun()
|
||||
{
|
||||
return $this->run;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Whoops\Exception\Inspector $inspector
|
||||
*/
|
||||
public function setInspector(Inspector $inspector)
|
||||
{
|
||||
$this->inspector = $inspector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whoops\Run
|
||||
*/
|
||||
protected function getInspector()
|
||||
{
|
||||
return $this->inspector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Exception $exception
|
||||
*/
|
||||
public function setException(Exception $exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Exception
|
||||
*/
|
||||
protected function getException()
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
}
|
33
vendor/filp/whoops/src/Whoops/Handler/HandlerInterface.php
vendored
Normal file
33
vendor/filp/whoops/src/Whoops/Handler/HandlerInterface.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
use Whoops\Exception\Inspector;
|
||||
use Whoops\Run;
|
||||
use Exception;
|
||||
|
||||
interface HandlerInterface
|
||||
{
|
||||
/**
|
||||
* @return int|null A handler may return nothing, or a Handler::HANDLE_* constant
|
||||
*/
|
||||
public function handle();
|
||||
|
||||
/**
|
||||
* @param Whoops\Run $run
|
||||
*/
|
||||
public function setRun(Run $run);
|
||||
|
||||
/**
|
||||
* @param Exception $exception
|
||||
*/
|
||||
public function setException(Exception $exception);
|
||||
|
||||
/**
|
||||
* @param Whoops\Exception\Inspector $run
|
||||
*/
|
||||
public function setInspector(Inspector $inspector);
|
||||
}
|
106
vendor/filp/whoops/src/Whoops/Handler/JsonResponseHandler.php
vendored
Normal file
106
vendor/filp/whoops/src/Whoops/Handler/JsonResponseHandler.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
use Whoops\Handler\Handler;
|
||||
|
||||
/**
|
||||
* Catches an exception and converts it to a JSON
|
||||
* response. Additionally can also return exception
|
||||
* frames for consumption by an API.
|
||||
*/
|
||||
class JsonResponseHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $returnFrames = false;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $onlyForAjaxRequests = false;
|
||||
|
||||
/**
|
||||
* @param bool|null $returnFrames
|
||||
* @return null|bool
|
||||
*/
|
||||
public function addTraceToOutput($returnFrames = null)
|
||||
{
|
||||
if(func_num_args() == 0) {
|
||||
return $this->returnFrames;
|
||||
}
|
||||
|
||||
$this->returnFrames = (bool) $returnFrames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|null $onlyForAjaxRequests
|
||||
* @return null|bool
|
||||
*/
|
||||
public function onlyForAjaxRequests($onlyForAjaxRequests = null)
|
||||
{
|
||||
if(func_num_args() == 0) {
|
||||
return $this->onlyForAjaxRequests;
|
||||
}
|
||||
|
||||
$this->onlyForAjaxRequests = (bool) $onlyForAjaxRequests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check, if possible, that this execution was triggered by an AJAX request.
|
||||
* @param bool
|
||||
*/
|
||||
private function isAjaxRequest()
|
||||
{
|
||||
return (
|
||||
!empty($_SERVER['HTTP_X_REQUESTED_WITH'])
|
||||
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if($this->onlyForAjaxRequests() && !$this->isAjaxRequest()) {
|
||||
return Handler::DONE;
|
||||
}
|
||||
|
||||
$exception = $this->getException();
|
||||
|
||||
$response = array(
|
||||
'error' => array(
|
||||
'type' => get_class($exception),
|
||||
'message' => $exception->getMessage(),
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine()
|
||||
)
|
||||
);
|
||||
|
||||
if($this->addTraceToOutput()) {
|
||||
$inspector = $this->getInspector();
|
||||
$frames = $inspector->getFrames();
|
||||
$frameData = array();
|
||||
|
||||
foreach($frames as $frame) {
|
||||
$frameData[] = array(
|
||||
'file' => $frame->getFile(),
|
||||
'line' => $frame->getLine(),
|
||||
'function' => $frame->getFunction(),
|
||||
'class' => $frame->getClass(),
|
||||
'args' => $frame->getArgs()
|
||||
);
|
||||
}
|
||||
|
||||
$response['error']['trace'] = $frameData;
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
return Handler::QUIT;
|
||||
}
|
||||
}
|
328
vendor/filp/whoops/src/Whoops/Handler/PrettyPageHandler.php
vendored
Normal file
328
vendor/filp/whoops/src/Whoops/Handler/PrettyPageHandler.php
vendored
Normal file
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
use Whoops\Handler\Handler;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class PrettyPageHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $resourcesPath;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
private $extraTables = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $pageTitle = 'Whoops! There was an error.';
|
||||
|
||||
/**
|
||||
* A string identifier for a known IDE/text editor, or a closure
|
||||
* that resolves a string that can be used to open a given file
|
||||
* in an editor. If the string contains the special substrings
|
||||
* %file or %line, they will be replaced with the correct data.
|
||||
*
|
||||
* @example
|
||||
* "txmt://open?url=%file&line=%line"
|
||||
* @var mixed $editor
|
||||
*/
|
||||
protected $editor;
|
||||
|
||||
/**
|
||||
* A list of known editor strings
|
||||
* @var array
|
||||
*/
|
||||
protected $editors = array(
|
||||
'sublime' => 'subl://open?url=file://%file&line=%line',
|
||||
'textmate' => 'txmt://open?url=file://%file&line=%line',
|
||||
'emacs' => 'emacs://open?url=file://%file&line=%line',
|
||||
'macvim' => 'mvim://open/?url=file://%file&line=%line'
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (extension_loaded('xdebug')) {
|
||||
// Register editor using xdebug's file_link_format option.
|
||||
$this->editors['xdebug'] = function($file, $line) {
|
||||
return str_replace(array('%f', '%l'), array($file, $line), ini_get('xdebug.file_link_format'));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
// Check conditions for outputting HTML:
|
||||
// @todo: make this more robust
|
||||
if(php_sapi_name() === 'cli' && !isset($_ENV['whoops-test'])) {
|
||||
return Handler::DONE;
|
||||
}
|
||||
|
||||
// Get the 'pretty-template.php' template file
|
||||
// @todo: this can be made more dynamic &&|| cleaned-up
|
||||
if(!($resources = $this->getResourcesPath())) {
|
||||
$resources = __DIR__ . '/../Resources';
|
||||
}
|
||||
|
||||
$templateFile = "$resources/pretty-template.php";
|
||||
|
||||
// @todo: Make this more reliable,
|
||||
// possibly by adding methods to append CSS & JS to the page
|
||||
$cssFile = "$resources/pretty-page.css";
|
||||
|
||||
// Prepare the $v global variable that will pass relevant
|
||||
// information to the template
|
||||
$inspector = $this->getInspector();
|
||||
$frames = $inspector->getFrames();
|
||||
|
||||
$v = (object) array(
|
||||
'title' => $this->getPageTitle(),
|
||||
'name' => explode('\\', $inspector->getExceptionName()),
|
||||
'message' => $inspector->getException()->getMessage(),
|
||||
'frames' => $frames,
|
||||
'hasFrames' => !!count($frames),
|
||||
'handler' => $this,
|
||||
'handlers' => $this->getRun()->getHandlers(),
|
||||
'pageStyle' => file_get_contents($cssFile),
|
||||
|
||||
'tables' => array(
|
||||
'Server/Request Data' => $_SERVER,
|
||||
'GET Data' => $_GET,
|
||||
'POST Data' => $_POST,
|
||||
'Files' => $_FILES,
|
||||
'Cookies' => $_COOKIE,
|
||||
'Session' => isset($_SESSION) ? $_SESSION: array(),
|
||||
'Environment Variables' => $_ENV
|
||||
)
|
||||
);
|
||||
|
||||
$extraTables = array_map(function($table) {
|
||||
return $table instanceof \Closure ? $table() : $table;
|
||||
}, $this->getDataTables());
|
||||
|
||||
// Add extra entries list of data tables:
|
||||
$v->tables = array_merge($extraTables, $v->tables);
|
||||
|
||||
call_user_func(function() use($templateFile, $v) {
|
||||
// $e -> cleanup output, optionally preserving URIs as anchors:
|
||||
$e = function($_, $allowLinks = false) {
|
||||
$escaped = htmlspecialchars($_, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
// convert URIs to clickable anchor elements:
|
||||
if($allowLinks) {
|
||||
$escaped = preg_replace(
|
||||
'@([A-z]+?://([-\w\.]+[-\w])+(:\d+)?(/([\w/_\.#-]*(\?\S+)?[^\.\s])?)?)@',
|
||||
"<a href=\"$1\" target=\"_blank\">$1</a>", $escaped
|
||||
);
|
||||
}
|
||||
|
||||
return $escaped;
|
||||
};
|
||||
|
||||
// $slug -> sluggify string (i.e: Hello world! -> hello-world)
|
||||
$slug = function($_) {
|
||||
$_ = str_replace(" ", "-", $_);
|
||||
$_ = preg_replace('/[^\w\d\-\_]/i', '', $_);
|
||||
return strtolower($_);
|
||||
};
|
||||
|
||||
require $templateFile;
|
||||
});
|
||||
|
||||
|
||||
return Handler::QUIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entry to the list of tables displayed in the template.
|
||||
* The expected data is a simple associative array. Any nested arrays
|
||||
* will be flattened with print_r
|
||||
* @param string $label
|
||||
* @param array $data
|
||||
*/
|
||||
public function addDataTable($label, array $data)
|
||||
{
|
||||
$this->extraTables[$label] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazily adds an entry to the list of tables displayed in the table.
|
||||
* The supplied callback argument will be called when the error is rendered,
|
||||
* it should produce a simple associative array. Any nested arrays will
|
||||
* be flattened with print_r.
|
||||
* @param string $label
|
||||
* @param callable $callback Callable returning an associative array
|
||||
*/
|
||||
public function addDataTableCallback($label, /* callable */ $callback)
|
||||
{
|
||||
if (!is_callable($callback)) {
|
||||
throw new InvalidArgumentException('Expecting callback argument to be callable');
|
||||
}
|
||||
|
||||
$this->extraTables[$label] = function() use ($callback) {
|
||||
try {
|
||||
$result = call_user_func($callback);
|
||||
|
||||
// Only return the result if it can be iterated over by foreach().
|
||||
return is_array($result) || $result instanceof \Traversable ? $result : array();
|
||||
} catch (\Exception $e) {
|
||||
// Don't allow failiure to break the rendering of the original exception.
|
||||
return array();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the extra data tables registered with this handler.
|
||||
* Optionally accepts a 'label' parameter, to only return the data
|
||||
* table under that label.
|
||||
* @param string|null $label
|
||||
* @return array[]
|
||||
*/
|
||||
public function getDataTables($label = null)
|
||||
{
|
||||
if($label !== null) {
|
||||
return isset($this->extraTables[$label]) ?
|
||||
$this->extraTables[$label] : array();
|
||||
}
|
||||
|
||||
return $this->extraTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an editor resolver, identified by a string
|
||||
* name, and that may be a string path, or a callable
|
||||
* resolver. If the callable returns a string, it will
|
||||
* be set as the file reference's href attribute.
|
||||
*
|
||||
* @example
|
||||
* $run->addEditor('macvim', "mvim://open?url=file://%file&line=%line")
|
||||
* @example
|
||||
* $run->addEditor('remove-it', function($file, $line) {
|
||||
* unlink($file);
|
||||
* return "http://stackoverflow.com";
|
||||
* });
|
||||
* @param string $identifier
|
||||
* @param string $resolver
|
||||
*/
|
||||
public function addEditor($identifier, $resolver)
|
||||
{
|
||||
$this->editors[$identifier] = $resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the editor to use to open referenced files, by a string
|
||||
* identifier, or a callable that will be executed for every
|
||||
* file reference, with a $file and $line argument, and should
|
||||
* return a string.
|
||||
*
|
||||
* @example
|
||||
* $run->setEditor(function($file, $line) { return "file:///{$file}"; });
|
||||
* @example
|
||||
* $run->setEditor('sublime');
|
||||
*
|
||||
* @param string|callable $editor
|
||||
*/
|
||||
public function setEditor($editor)
|
||||
{
|
||||
if(!is_callable($editor) && !isset($this->editors[$editor])) {
|
||||
throw new InvalidArgumentException(
|
||||
"Unknown editor identifier: $editor. Known editors:" .
|
||||
implode(",", array_keys($this->editors))
|
||||
);
|
||||
}
|
||||
|
||||
$this->editor = $editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string file path, and an integer file line,
|
||||
* executes the editor resolver and returns, if available,
|
||||
* a string that may be used as the href property for that
|
||||
* file reference.
|
||||
*
|
||||
* @param string $filePath
|
||||
* @param int $line
|
||||
* @return string|false
|
||||
*/
|
||||
public function getEditorHref($filePath, $line)
|
||||
{
|
||||
if($this->editor === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$editor = $this->editor;
|
||||
if(is_string($editor)) {
|
||||
$editor = $this->editors[$editor];
|
||||
}
|
||||
|
||||
if(is_callable($editor)) {
|
||||
$editor = call_user_func($editor, $filePath, $line);
|
||||
}
|
||||
|
||||
// Check that the editor is a string, and replace the
|
||||
// %line and %file placeholders:
|
||||
if(!is_string($editor)) {
|
||||
throw new InvalidArgumentException(
|
||||
__METHOD__ . " should always resolve to a string; got something else instead"
|
||||
);
|
||||
}
|
||||
|
||||
$editor = str_replace("%line", rawurlencode($line), $editor);
|
||||
$editor = str_replace("%file", rawurlencode($filePath), $editor);
|
||||
|
||||
return $editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public function setPageTitle($title)
|
||||
{
|
||||
$this->pageTitle = (string) $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPageTitle()
|
||||
{
|
||||
return $this->pageTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getResourcesPath()
|
||||
{
|
||||
return $this->resourcesPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $resourcesPath
|
||||
*/
|
||||
public function setResourcesPath($resourcesPath)
|
||||
{
|
||||
if(!is_dir($resourcesPath)) {
|
||||
throw new InvalidArgumentException(
|
||||
"$resourcesPath is not a valid directory"
|
||||
);
|
||||
}
|
||||
|
||||
$this->resourcesPath = $resourcesPath;
|
||||
}
|
||||
}
|
69
vendor/filp/whoops/src/Whoops/Provider/Phalcon/WhoopsServiceProvider.php
vendored
Normal file
69
vendor/filp/whoops/src/Whoops/Provider/Phalcon/WhoopsServiceProvider.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Provider\Phalcon;
|
||||
|
||||
use Whoops\Run;
|
||||
use Whoops\Handler\PrettyPageHandler;
|
||||
use Phalcon\DI;
|
||||
use Phalcon\DI\Exception;
|
||||
|
||||
class WhoopsServiceProvider
|
||||
{
|
||||
/**
|
||||
* @param Phalcon\DI $di
|
||||
*/
|
||||
public function __construct(DI $di = null)
|
||||
{
|
||||
if (!$di) {
|
||||
$di = DI::getDefault();
|
||||
}
|
||||
|
||||
// There's only ever going to be one error page...right?
|
||||
$di->setShared('whoops.error_page_handler', function() {
|
||||
return new PrettyPageHandler;
|
||||
});
|
||||
|
||||
// Retrieves info on the Phalcon environment and ships it off
|
||||
// to the PrettyPageHandler's data tables:
|
||||
// This works by adding a new handler to the stack that runs
|
||||
// before the error page, retrieving the shared page handler
|
||||
// instance, and working with it to add new data tables
|
||||
$phalcon_info_handler = function() use($di) {
|
||||
try {
|
||||
$request = $di['request'];
|
||||
} catch (Exception $e) {
|
||||
// This error occurred too early in the application's life
|
||||
// and the request instance is not yet available.
|
||||
return;
|
||||
}
|
||||
|
||||
// Request info:
|
||||
$di['whoops.error_page_handler']->addDataTable('Phalcon Application (Request)', array(
|
||||
'URI' => $request->getScheme().'://'.$request->getServer('HTTP_HOST').$request->getServer('REQUEST_URI'),
|
||||
'Request URI' => $request->getServer('REQUEST_URI'),
|
||||
'Path Info' => $request->getServer('PATH_INFO'),
|
||||
'Query String'=> $request->getServer('QUERY_STRING') ?: '<none>',
|
||||
'HTTP Method' => $request->getMethod(),
|
||||
'Script Name' => $request->getServer('SCRIPT_NAME'),
|
||||
//'Base Path' => $request->getBasePath(),
|
||||
//'Base URL' => $request->getBaseUrl(),
|
||||
'Scheme' => $request->getScheme(),
|
||||
'Port' => $request->getServer('SERVER_PORT'),
|
||||
'Host' => $request->getServerName(),
|
||||
));
|
||||
};
|
||||
|
||||
$di->setShared('whoops', function() use($di, $phalcon_info_handler) {
|
||||
$run = new Run;
|
||||
$run->pushHandler($di['whoops.error_page_handler']);
|
||||
$run->pushHandler($phalcon_info_handler);
|
||||
return $run;
|
||||
});
|
||||
|
||||
$di['whoops']->register();
|
||||
}
|
||||
}
|
81
vendor/filp/whoops/src/Whoops/Provider/Silex/WhoopsServiceProvider.php
vendored
Normal file
81
vendor/filp/whoops/src/Whoops/Provider/Silex/WhoopsServiceProvider.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Provider\Silex;
|
||||
use Whoops\Run;
|
||||
use Whoops\Handler\PrettyPageHandler;
|
||||
use Silex\ServiceProviderInterface;
|
||||
use Silex\Application;
|
||||
use RuntimeException;
|
||||
|
||||
class WhoopsServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
/**
|
||||
* @see Silex\ServiceProviderInterface::register
|
||||
* @param Silex\Application $app
|
||||
*/
|
||||
public function register(Application $app)
|
||||
{
|
||||
// There's only ever going to be one error page...right?
|
||||
$app['whoops.error_page_handler'] = $app->share(function() {
|
||||
return new PrettyPageHandler;
|
||||
});
|
||||
|
||||
// Retrieves info on the Silex environment and ships it off
|
||||
// to the PrettyPageHandler's data tables:
|
||||
// This works by adding a new handler to the stack that runs
|
||||
// before the error page, retrieving the shared page handler
|
||||
// instance, and working with it to add new data tables
|
||||
$app['whoops.silex_info_handler'] = $app->protect(function() use($app) {
|
||||
try {
|
||||
$request = $app['request'];
|
||||
} catch (RuntimeException $e) {
|
||||
// This error occurred too early in the application's life
|
||||
// and the request instance is not yet available.
|
||||
return;
|
||||
}
|
||||
|
||||
// General application info:
|
||||
$app['whoops.error_page_handler']->addDataTable('Silex Application', array(
|
||||
'Charset' => $app['charset'],
|
||||
'Locale' => $app['locale'],
|
||||
'Route Class' => $app['route_class'],
|
||||
'Dispatcher Class' => $app['dispatcher_class'],
|
||||
'Application Class'=> get_class($app)
|
||||
));
|
||||
|
||||
// Request info:
|
||||
$app['whoops.error_page_handler']->addDataTable('Silex Application (Request)', array(
|
||||
'URI' => $request->getUri(),
|
||||
'Request URI' => $request->getRequestUri(),
|
||||
'Path Info' => $request->getPathInfo(),
|
||||
'Query String'=> $request->getQueryString() ?: '<none>',
|
||||
'HTTP Method' => $request->getMethod(),
|
||||
'Script Name' => $request->getScriptName(),
|
||||
'Base Path' => $request->getBasePath(),
|
||||
'Base URL' => $request->getBaseUrl(),
|
||||
'Scheme' => $request->getScheme(),
|
||||
'Port' => $request->getPort(),
|
||||
'Host' => $request->getHost(),
|
||||
));
|
||||
});
|
||||
|
||||
$app['whoops'] = $app->share(function() use($app) {
|
||||
$run = new Run;
|
||||
$run->pushHandler($app['whoops.error_page_handler']);
|
||||
$run->pushHandler($app['whoops.silex_info_handler']);
|
||||
return $run;
|
||||
});
|
||||
|
||||
$app->error(array($app['whoops'], Run::EXCEPTION_HANDLER));
|
||||
$app['whoops']->register();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Silex\ServiceProviderInterface::boot
|
||||
*/
|
||||
public function boot(Application $app) {}
|
||||
}
|
56
vendor/filp/whoops/src/Whoops/Provider/Zend/ExceptionStrategy.php
vendored
Normal file
56
vendor/filp/whoops/src/Whoops/Provider/Zend/ExceptionStrategy.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* ZF2 Integration for Whoops
|
||||
* @author Balázs Németh <zsilbi@zsilbi.hu>
|
||||
*/
|
||||
|
||||
namespace Whoops\Provider\Zend;
|
||||
|
||||
use Whoops\Run;
|
||||
|
||||
use Zend\Mvc\View\Http\ExceptionStrategy as BaseExceptionStrategy;
|
||||
use Zend\Mvc\MvcEvent;
|
||||
use Zend\Mvc\Application;
|
||||
|
||||
class ExceptionStrategy extends BaseExceptionStrategy {
|
||||
|
||||
protected $run;
|
||||
|
||||
public function __construct(Run $run) {
|
||||
$this->run = $run;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function prepareExceptionViewModel(MvcEvent $event) {
|
||||
// Do nothing if no error in the event
|
||||
$error = $event->getError();
|
||||
if (empty($error)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do nothing if the result is a response object
|
||||
$result = $event->getResult();
|
||||
if ($result instanceof Response) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($error) {
|
||||
case Application::ERROR_CONTROLLER_NOT_FOUND:
|
||||
case Application::ERROR_CONTROLLER_INVALID:
|
||||
case Application::ERROR_ROUTER_NO_MATCH:
|
||||
// Specifically not handling these
|
||||
return;
|
||||
|
||||
case Application::ERROR_EXCEPTION:
|
||||
default:
|
||||
$response = $event->getResponse();
|
||||
if (!$response || $response->getStatusCode() === 200) {
|
||||
header('HTTP/1.0 500 Internal Server Error', true, 500);
|
||||
}
|
||||
ob_clean();
|
||||
$this->run->handleException($event->getParam('exception'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
106
vendor/filp/whoops/src/Whoops/Provider/Zend/Module.php
vendored
Normal file
106
vendor/filp/whoops/src/Whoops/Provider/Zend/Module.php
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* ZF2 Integration for Whoops
|
||||
* @author Balázs Németh <zsilbi@zsilbi.hu>
|
||||
*
|
||||
* The Whoops directory should be added as a module to ZF2 (/vendor/Whoops)
|
||||
*
|
||||
* Whoops must be added as the first module
|
||||
* For example:
|
||||
* 'modules' => array(
|
||||
* 'Whoops',
|
||||
* 'Application',
|
||||
* ),
|
||||
*
|
||||
* This file should be moved next to Whoops/Run.php (/vendor/Whoops/Module.php)
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Whoops;
|
||||
|
||||
use Whoops\Run;
|
||||
use Whoops\Provider\Zend\ExceptionStrategy;
|
||||
use Whoops\Provider\Zend\RouteNotFoundStrategy;
|
||||
use Whoops\Handler\JsonResponseHandler;
|
||||
use Whoops\Handler\PrettyPageHandler;
|
||||
use Zend\EventManager\EventInterface;
|
||||
use Zend\Console\Request as ConsoleRequest;
|
||||
|
||||
class Module
|
||||
{
|
||||
protected $run;
|
||||
|
||||
public function onBootstrap(EventInterface $event)
|
||||
{
|
||||
$prettyPageHandler = new PrettyPageHandler();
|
||||
|
||||
// Set editor
|
||||
$config = $event->getApplication()->getServiceManager()->get('Config');
|
||||
if (isset($config['view_manager']['editor'])) {
|
||||
$prettyPageHandler->setEditor($config['view_manager']['editor']);
|
||||
}
|
||||
|
||||
|
||||
$this->run = new Run();
|
||||
$this->run->register();
|
||||
$this->run->pushHandler($prettyPageHandler);
|
||||
|
||||
$this->attachListeners($event);
|
||||
}
|
||||
|
||||
public function getAutoloaderConfig()
|
||||
{
|
||||
return array(
|
||||
'Zend\Loader\StandardAutoloader' => array(
|
||||
'namespaces' => array(
|
||||
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private function attachListeners(EventInterface $event)
|
||||
{
|
||||
$request = $event->getRequest();
|
||||
$application = $event->getApplication();
|
||||
$services = $application->getServiceManager();
|
||||
$events = $application->getEventManager();
|
||||
$config = $services->get('Config');
|
||||
|
||||
//Display exceptions based on configuration and console mode
|
||||
if ($request instanceof ConsoleRequest || empty($config['view_manager']['display_exceptions']))
|
||||
return;
|
||||
|
||||
$jsonHandler = new JsonResponseHandler();
|
||||
|
||||
if (!empty($config['view_manager']['json_exceptions']['show_trace'])) {
|
||||
//Add trace to the JSON output
|
||||
$jsonHandler->addTraceToOutput(true);
|
||||
}
|
||||
|
||||
if (!empty($config['view_manager']['json_exceptions']['ajax_only'])) {
|
||||
//Only return JSON response for AJAX requests
|
||||
$jsonHandler->onlyForAjaxRequests(true);
|
||||
}
|
||||
|
||||
if (!empty($config['view_manager']['json_exceptions']['display'])) {
|
||||
//Turn on JSON handler
|
||||
$this->run->pushHandler($jsonHandler);
|
||||
}
|
||||
|
||||
//Attach the Whoops ExceptionStrategy
|
||||
$exceptionStrategy = new ExceptionStrategy($this->run);
|
||||
$exceptionStrategy->attach($events);
|
||||
|
||||
//Attach the Whoops RouteNotFoundStrategy
|
||||
$routeNotFoundStrategy = new RouteNotFoundStrategy($this->run);
|
||||
$routeNotFoundStrategy->attach($events);
|
||||
|
||||
//Detach default ExceptionStrategy
|
||||
$services->get('Zend\Mvc\View\Http\ExceptionStrategy')->detach($events);
|
||||
|
||||
//Detach default RouteNotFoundStrategy
|
||||
$services->get('Zend\Mvc\View\Http\RouteNotFoundStrategy')->detach($events);
|
||||
}
|
||||
|
||||
}
|
64
vendor/filp/whoops/src/Whoops/Provider/Zend/RouteNotFoundStrategy.php
vendored
Normal file
64
vendor/filp/whoops/src/Whoops/Provider/Zend/RouteNotFoundStrategy.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* ZF2 Integration for Whoops
|
||||
* @author Balázs Németh <zsilbi@zsilbi.hu>
|
||||
*/
|
||||
|
||||
namespace Whoops\Provider\Zend;
|
||||
|
||||
use Whoops\Run;
|
||||
|
||||
use Zend\Mvc\View\Http\RouteNotFoundStrategy as BaseRouteNotFoundStrategy;
|
||||
use Zend\Mvc\MvcEvent;
|
||||
use Zend\Stdlib\ResponseInterface as Response;
|
||||
use Zend\View\Model\ViewModel;
|
||||
|
||||
class RouteNotFoundStrategy extends BaseRouteNotFoundStrategy {
|
||||
|
||||
protected $run;
|
||||
|
||||
public function __construct(Run $run) {
|
||||
$this->run = $run;
|
||||
}
|
||||
|
||||
public function prepareNotFoundViewModel(MvcEvent $e) {
|
||||
$vars = $e->getResult();
|
||||
if ($vars instanceof Response) {
|
||||
// Already have a response as the result
|
||||
return;
|
||||
}
|
||||
|
||||
$response = $e->getResponse();
|
||||
if ($response->getStatusCode() != 404) {
|
||||
// Only handle 404 responses
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$vars instanceof ViewModel) {
|
||||
$model = new ViewModel();
|
||||
if (is_string($vars)) {
|
||||
$model->setVariable('message', $vars);
|
||||
} else {
|
||||
$model->setVariable('message', 'Page not found.');
|
||||
}
|
||||
} else {
|
||||
$model = $vars;
|
||||
if ($model->getVariable('message') === null) {
|
||||
$model->setVariable('message', 'Page not found.');
|
||||
}
|
||||
}
|
||||
// If displaying reasons, inject the reason
|
||||
$this->injectNotFoundReason($model, $e);
|
||||
|
||||
// If displaying exceptions, inject
|
||||
$this->injectException($model, $e);
|
||||
|
||||
// Inject controller if we're displaying either the reason or the exception
|
||||
$this->injectController($model, $e);
|
||||
|
||||
ob_clean();
|
||||
|
||||
throw new \Exception($model->getVariable('message') . ' ' . $model->getVariable('reason'));
|
||||
}
|
||||
|
||||
}
|
20
vendor/filp/whoops/src/Whoops/Provider/Zend/module.config.example.php
vendored
Normal file
20
vendor/filp/whoops/src/Whoops/Provider/Zend/module.config.example.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* ZF2 Integration for Whoops
|
||||
* @author Balázs Németh <zsilbi@zsilbi.hu>
|
||||
*
|
||||
* Example controller configuration
|
||||
*/
|
||||
|
||||
return array(
|
||||
'view_manager' => array(
|
||||
'editor' => 'sublime',
|
||||
'display_not_found_reason' => true,
|
||||
'display_exceptions' => true,
|
||||
'json_exceptions' => array(
|
||||
'display' => true,
|
||||
'ajax_only' => true,
|
||||
'show_trace' => true
|
||||
)
|
||||
),
|
||||
);
|
319
vendor/filp/whoops/src/Whoops/Resources/pretty-page.css
vendored
Normal file
319
vendor/filp/whoops/src/Whoops/Resources/pretty-page.css
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
.cf:before, .cf:after {content: " ";display: table;} .cf:after {clear: both;} .cf {*zoom: 1;}
|
||||
body {
|
||||
font: 14px helvetica, arial, sans-serif;
|
||||
color: #2B2B2B;
|
||||
background-color: #D4D4D4;
|
||||
padding:0;
|
||||
margin: 0;
|
||||
max-height: 100%;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.container{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.branding {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 20px;
|
||||
color: #777777;
|
||||
font-size: 10px;
|
||||
z-index: 100;
|
||||
}
|
||||
.branding a {
|
||||
color: #CD3F3F;
|
||||
}
|
||||
|
||||
header {
|
||||
padding: 30px 20px;
|
||||
color: white;
|
||||
background: #272727;
|
||||
box-sizing: border-box;
|
||||
border-left: 5px solid #CD3F3F;
|
||||
}
|
||||
.exc-title {
|
||||
margin: 0;
|
||||
color: #616161;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, .1);
|
||||
}
|
||||
.exc-title-primary { color: #CD3F3F; }
|
||||
.exc-message {
|
||||
font-size: 32px;
|
||||
margin: 5px 0;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.stack-container {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.details-container {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
float: right;
|
||||
width: 70%;
|
||||
background: #DADADA;
|
||||
}
|
||||
.details {
|
||||
padding: 10px;
|
||||
padding-left: 5px;
|
||||
border-left: 5px solid rgba(0, 0, 0, .1);
|
||||
}
|
||||
|
||||
.frames-container {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
float: left;
|
||||
width: 30%;
|
||||
background: #FFF;
|
||||
}
|
||||
.frame {
|
||||
padding: 14px;
|
||||
background: #F3F3F3;
|
||||
border-right: 1px solid rgba(0, 0, 0, .2);
|
||||
cursor: pointer;
|
||||
}
|
||||
.frame.active {
|
||||
background-color: #4288CE;
|
||||
color: #F3F3F3;
|
||||
box-shadow: inset -2px 0 0 rgba(255, 255, 255, .1);
|
||||
text-shadow: 0 1px 0 rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.frame:not(.active):hover {
|
||||
background: #BEE9EA;
|
||||
}
|
||||
|
||||
.frame-class, .frame-function, .frame-index {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.frame-index {
|
||||
font-size: 11px;
|
||||
color: #BDBDBD;
|
||||
}
|
||||
|
||||
.frame-class {
|
||||
color: #4288CE;
|
||||
}
|
||||
.active .frame-class {
|
||||
color: #BEE9EA;
|
||||
}
|
||||
|
||||
.frame-file {
|
||||
font-family: consolas, monospace;
|
||||
word-wrap:break-word;
|
||||
}
|
||||
|
||||
.frame-file .editor-link {
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
.frame-line {
|
||||
font-weight: bold;
|
||||
color: #4288CE;
|
||||
}
|
||||
|
||||
.active .frame-line { color: #BEE9EA; }
|
||||
.frame-line:before {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
.frame-code {
|
||||
padding: 10px;
|
||||
padding-left: 5px;
|
||||
background: #BDBDBD;
|
||||
display: none;
|
||||
border-left: 5px solid #4288CE;
|
||||
}
|
||||
|
||||
.frame-code.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.frame-code .frame-file {
|
||||
background: #C6C6C6;
|
||||
color: #525252;
|
||||
text-shadow: 0 1px 0 #E7E7E7;
|
||||
padding: 10px 10px 5px 10px;
|
||||
|
||||
border-top-right-radius: 6px;
|
||||
border-top-left-radius: 6px;
|
||||
|
||||
border: 1px solid rgba(0, 0, 0, .1);
|
||||
border-bottom: none;
|
||||
box-shadow: inset 0 1px 0 #DADADA;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
padding: 10px;
|
||||
margin: 0;
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
|
||||
}
|
||||
|
||||
.linenums {
|
||||
margin: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.frame-comments {
|
||||
box-shadow: inset 0 0 6px rgba(0, 0, 0, .3);
|
||||
border: 1px solid rgba(0, 0, 0, .2);
|
||||
border-top: none;
|
||||
|
||||
border-bottom-right-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
|
||||
padding: 5px;
|
||||
font-size: 12px;
|
||||
background: #404040;
|
||||
}
|
||||
|
||||
.frame-comments.empty {
|
||||
padding: 8px 15px;
|
||||
}
|
||||
|
||||
.frame-comments.empty:before {
|
||||
content: "No comments for this stack frame.";
|
||||
font-style: italic;
|
||||
color: #828282;
|
||||
}
|
||||
|
||||
.frame-comment {
|
||||
padding: 10px;
|
||||
color: #D2D2D2;
|
||||
}
|
||||
.frame-comment a {
|
||||
color: #BEE9EA;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
.frame-comment a:hover {
|
||||
color: #4bb1b1;
|
||||
}
|
||||
|
||||
.frame-comment:not(:last-child) {
|
||||
border-bottom: 1px dotted rgba(0, 0, 0, .3);
|
||||
}
|
||||
|
||||
.frame-comment-context {
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
color: #86D2B6;
|
||||
}
|
||||
|
||||
.data-table-container label {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #4288CE;
|
||||
margin: 10px 0;
|
||||
padding: 10px 0;
|
||||
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 1px dotted rgba(0, 0, 0, .2);
|
||||
}
|
||||
.data-table {
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.data-table tbody {
|
||||
font: 13px consolas, monospace;
|
||||
}
|
||||
|
||||
.data-table thead {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.data-table tr {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.data-table td:first-child {
|
||||
width: 20%;
|
||||
min-width: 130px;
|
||||
overflow: hidden;
|
||||
font-weight: bold;
|
||||
color: #463C54;
|
||||
padding-right: 5px;
|
||||
|
||||
}
|
||||
|
||||
.data-table td:last-child {
|
||||
width: 80%;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
-webkit-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
.data-table .empty {
|
||||
color: rgba(0, 0, 0, .3);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.handler {
|
||||
padding: 10px;
|
||||
font: 14px monospace;
|
||||
}
|
||||
|
||||
.handler.active {
|
||||
color: #BBBBBB;
|
||||
background: #989898;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* prettify code style
|
||||
Uses the Doxy theme as a base */
|
||||
pre .str, code .str { color: #BCD42A; } /* string */
|
||||
pre .kwd, code .kwd { color: #4bb1b1; font-weight: bold; } /* keyword*/
|
||||
pre .com, code .com { color: #888; font-weight: bold; } /* comment */
|
||||
pre .typ, code .typ { color: #ef7c61; } /* type */
|
||||
pre .lit, code .lit { color: #BCD42A; } /* literal */
|
||||
pre .pun, code .pun { color: #fff; font-weight: bold; } /* punctuation */
|
||||
pre .pln, code .pln { color: #e9e4e5; } /* plaintext */
|
||||
pre .tag, code .tag { color: #4bb1b1; } /* html/xml tag */
|
||||
pre .htm, code .htm { color: #dda0dd; } /* html tag */
|
||||
pre .xsl, code .xsl { color: #d0a0d0; } /* xslt tag */
|
||||
pre .atn, code .atn { color: #ef7c61; font-weight: normal;} /* html/xml attribute name */
|
||||
pre .atv, code .atv { color: #bcd42a; } /* html/xml attribute value */
|
||||
pre .dec, code .dec { color: #606; } /* decimal */
|
||||
pre.prettyprint, code.prettyprint {
|
||||
font-family: 'Source Code Pro', Monaco, Consolas, "Lucida Console", monospace;;
|
||||
background: #333;
|
||||
color: #e9e4e5;
|
||||
}
|
||||
pre.prettyprint {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
pre.prettyprint a, code.prettyprint a {
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.linenums li {
|
||||
color: #A5A5A5;
|
||||
}
|
||||
|
||||
.linenums li.current{
|
||||
background: rgba(255, 100, 100, .07);
|
||||
padding-top: 4px;
|
||||
padding-left: 1px;
|
||||
}
|
||||
.linenums li.current.active {
|
||||
background: rgba(255, 100, 100, .17);
|
||||
}
|
205
vendor/filp/whoops/src/Whoops/Resources/pretty-template.php
vendored
Normal file
205
vendor/filp/whoops/src/Whoops/Resources/pretty-template.php
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* Template file for Whoops's pretty error output.
|
||||
* Check the $v global variable (stdClass) for what's available
|
||||
* to work with.
|
||||
* @var $v
|
||||
*/
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><?php echo $e($v->title) ?></title>
|
||||
|
||||
<style><?php echo $v->pageStyle ?></style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
|
||||
<div class="stack-container">
|
||||
|
||||
<div class="frames-container cf <?php echo (!$v->hasFrames ? 'empty' : '') ?>">
|
||||
|
||||
<?php /* List file names & line numbers for all stack frames;
|
||||
clicking these links/buttons will display the code view
|
||||
for that particular frame */ ?>
|
||||
<?php foreach($v->frames as $i => $frame): ?>
|
||||
<div class="frame <?php echo ($i == 0 ? 'active' : '') ?>" id="frame-line-<?php echo $i ?>">
|
||||
<div class="frame-method-info">
|
||||
<span class="frame-index"><?php echo (count($v->frames) - $i - 1) ?>.</span>
|
||||
<span class="frame-class"><?php echo $e($frame->getClass() ?: '') ?></span>
|
||||
<span class="frame-function"><?php echo $e($frame->getFunction() ?: '') ?></span>
|
||||
</div>
|
||||
|
||||
<span class="frame-file">
|
||||
<?php echo ($frame->getFile(true) ?: '<#unknown>') ?><!--
|
||||
--><span class="frame-line"><?php echo (int) $frame->getLine() ?></span>
|
||||
</span>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="details-container cf">
|
||||
|
||||
<header>
|
||||
<div class="exception">
|
||||
<h3 class="exc-title">
|
||||
<?php foreach($v->name as $i => $nameSection): ?>
|
||||
<?php if($i == count($v->name) - 1): ?>
|
||||
<span class="exc-title-primary"><?php echo $e($nameSection) ?></span>
|
||||
<?php else: ?>
|
||||
<?php echo $e($nameSection) . ' \\' ?>
|
||||
<?php endif ?>
|
||||
<?php endforeach ?>
|
||||
</h3>
|
||||
<p class="exc-message">
|
||||
<?php echo $e($v->message) ?>
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<?php /* Display a code block for all frames in the stack.
|
||||
* @todo: This should PROBABLY be done on-demand, lest
|
||||
* we get 200 frames to process. */ ?>
|
||||
<div class="frame-code-container <?php echo (!$v->hasFrames ? 'empty' : '') ?>">
|
||||
<?php foreach($v->frames as $i => $frame): ?>
|
||||
<?php $line = $frame->getLine(); ?>
|
||||
<div class="frame-code <?php echo ($i == 0 ) ? 'active' : '' ?>" id="frame-code-<?php echo $i ?>">
|
||||
<div class="frame-file">
|
||||
<?php $filePath = $frame->getFile(); ?>
|
||||
<?php if($filePath && $editorHref = $v->handler->getEditorHref($filePath, (int) $line)): ?>
|
||||
Open:
|
||||
<a href="<?php echo $editorHref ?>" class="editor-link">
|
||||
<strong><?php echo $e($filePath ?: '<#unknown>') ?></strong>
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<strong><?php echo $e($filePath ?: '<#unknown>') ?></strong>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php
|
||||
// Do nothing if there's no line to work off
|
||||
if($line !== null):
|
||||
|
||||
// the $line is 1-indexed, we nab -1 where needed to account for this
|
||||
$range = $frame->getFileLines($line - 8, 10);
|
||||
$range = array_map(function($line){ return empty($line) ? ' ' : $line;}, $range);
|
||||
$start = key($range) + 1;
|
||||
$code = join("\n", $range);
|
||||
?>
|
||||
<pre class="code-block prettyprint linenums:<?php echo $start ?>"><?php echo $e($code) ?></pre>
|
||||
<?php endif ?>
|
||||
|
||||
<?php
|
||||
// Append comments for this frame */
|
||||
$comments = $frame->getComments();
|
||||
?>
|
||||
<div class="frame-comments <?php echo empty($comments) ? 'empty' : '' ?>">
|
||||
<?php foreach($comments as $commentNo => $comment): ?>
|
||||
<?php extract($comment) ?>
|
||||
<div class="frame-comment" id="comment-<?php echo $i . '-' . $commentNo ?>">
|
||||
<span class="frame-comment-context"><?php echo $e($context) ?></span>
|
||||
<?php echo $e($comment, true) ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
||||
<?php /* List data-table values, i.e: $_SERVER, $_GET, .... */ ?>
|
||||
<div class="details">
|
||||
<div class="data-table-container" id="data-tables">
|
||||
<?php foreach($v->tables as $label => $data): ?>
|
||||
<div class="data-table" id="sg-<?php echo $e($slug($label)) ?>">
|
||||
<label><?php echo $e($label) ?></label>
|
||||
<?php if(!empty($data)): ?>
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="data-table-k">Key</td>
|
||||
<td class="data-table-v">Value</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php foreach($data as $k => $value): ?>
|
||||
<tr>
|
||||
<td><?php echo $e($k) ?></td>
|
||||
<td><?php echo $e(print_r($value, true)) ?></td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<span class="empty">empty</span>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
||||
<?php /* List registered handlers, in order of first to last registered */ ?>
|
||||
<div class="data-table-container" id="handlers">
|
||||
<label>Registered Handlers</label>
|
||||
<?php foreach($v->handlers as $i => $handler): ?>
|
||||
<div class="handler <?php echo ($handler === $v->handler) ? 'active' : ''?>">
|
||||
<?php echo $i ?>. <?php echo $e(get_class($handler)) ?>
|
||||
</div>
|
||||
<?php endforeach ?>
|
||||
</div>
|
||||
|
||||
</div> <!-- .details -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/prettify/r224/prettify.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
prettyPrint();
|
||||
|
||||
var $frameLines = $('[id^="frame-line-"]');
|
||||
var $activeLine = $('.frames-container .active');
|
||||
var $activeFrame = $('.active[id^="frame-code-"]').show();
|
||||
var $container = $('.details-container');
|
||||
var headerHeight = $('header').css('height');
|
||||
|
||||
var highlightCurrentLine = function() {
|
||||
// Highlight the active and neighboring lines for this frame:
|
||||
var activeLineNumber = +($activeLine.find('.frame-line').text());
|
||||
var $lines = $activeFrame.find('.linenums li');
|
||||
var firstLine = +($lines.first().val());
|
||||
|
||||
$($lines[activeLineNumber - firstLine - 1]).addClass('current');
|
||||
$($lines[activeLineNumber - firstLine]).addClass('current active');
|
||||
$($lines[activeLineNumber - firstLine + 1]).addClass('current');
|
||||
}
|
||||
|
||||
// Highlight the active for the first frame:
|
||||
highlightCurrentLine();
|
||||
|
||||
$frameLines.click(function() {
|
||||
var $this = $(this);
|
||||
var id = /frame\-line\-([\d]*)/.exec($this.attr('id'))[1];
|
||||
var $codeFrame = $('#frame-code-' + id);
|
||||
|
||||
if($codeFrame) {
|
||||
$activeLine.removeClass('active');
|
||||
$activeFrame.removeClass('active');
|
||||
|
||||
$this.addClass('active');
|
||||
$codeFrame.addClass('active');
|
||||
|
||||
$activeLine = $this;
|
||||
$activeFrame = $codeFrame;
|
||||
|
||||
highlightCurrentLine();
|
||||
|
||||
$container.animate({ scrollTop: headerHeight }, "fast");
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
253
vendor/filp/whoops/src/Whoops/Run.php
vendored
Normal file
253
vendor/filp/whoops/src/Whoops/Run.php
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops;
|
||||
use Whoops\Handler\HandlerInterface;
|
||||
use Whoops\Handler\Handler;
|
||||
use Whoops\Handler\CallbackHandler;
|
||||
use Whoops\Exception\Inspector;
|
||||
use Whoops\Exception\ErrorException;
|
||||
use InvalidArgumentException;
|
||||
use Exception;
|
||||
|
||||
class Run
|
||||
{
|
||||
const EXCEPTION_HANDLER = 'handleException';
|
||||
const ERROR_HANDLER = 'handleError';
|
||||
const SHUTDOWN_HANDLER = 'handleShutdown';
|
||||
|
||||
protected $isRegistered;
|
||||
protected $allowQuit = true;
|
||||
protected $sendOutput = true;
|
||||
|
||||
/**
|
||||
* @var Whoops\Handler\HandlerInterface[]
|
||||
*/
|
||||
protected $handlerStack = array();
|
||||
|
||||
/**
|
||||
* Pushes a handler to the end of the stack.
|
||||
* @param Whoops\HandlerInterface $handler
|
||||
* @return Whoops\Run
|
||||
*/
|
||||
public function pushHandler($handler)
|
||||
{
|
||||
if(is_callable($handler)) {
|
||||
$handler = new CallbackHandler($handler);
|
||||
}
|
||||
|
||||
if(!$handler instanceof HandlerInterface) {
|
||||
throw new InvalidArgumentException(
|
||||
'Argument to ' . __METHOD__ . ' must be a callable, or instance of'
|
||||
. 'Whoops\\Handler\\HandlerInterface'
|
||||
);
|
||||
}
|
||||
|
||||
$this->handlerStack[] = $handler;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the last handler in the stack and returns it.
|
||||
* Returns null if there's nothing else to pop.
|
||||
* @return null|Whoops\Handler\HandlerInterface
|
||||
*/
|
||||
public function popHandler()
|
||||
{
|
||||
return array_pop($this->handlerStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all handlers, in the
|
||||
* order they were added to the stack.
|
||||
* @return array
|
||||
*/
|
||||
public function getHandlers()
|
||||
{
|
||||
return $this->handlerStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all handlers in the handlerStack, including
|
||||
* the default PrettyPage handler.
|
||||
* @return Whoops\Run
|
||||
*/
|
||||
public function clearHandlers()
|
||||
{
|
||||
$this->handlerStack = array();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Exception $exception
|
||||
* @return Whoops\Exception\Inspector
|
||||
*/
|
||||
protected function getInspector(Exception $exception)
|
||||
{
|
||||
return new Inspector($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an error handler.
|
||||
* @return Whoops\Run
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
if(!$this->isRegistered) {
|
||||
set_error_handler(array($this, self::ERROR_HANDLER));
|
||||
set_exception_handler(array($this, self::EXCEPTION_HANDLER));
|
||||
register_shutdown_function(array($this, self::SHUTDOWN_HANDLER));
|
||||
|
||||
$this->isRegistered = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters all handlers registered by this Whoops\Run instance
|
||||
* @return Whoops\Run
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
if($this->isRegistered) {
|
||||
restore_exception_handler();
|
||||
restore_error_handler();
|
||||
|
||||
$this->isRegistered = false;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should Whoops allow Handlers to force the script to quit?
|
||||
* @param bool|num $exit
|
||||
* @return bool
|
||||
*/
|
||||
public function allowQuit($exit = null)
|
||||
{
|
||||
if(func_num_args() == 0) {
|
||||
return $this->allowQuit;
|
||||
}
|
||||
|
||||
return $this->allowQuit = (bool) $exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should Whoops push output directly to the client?
|
||||
* If this is false, output will be returned by handleException
|
||||
* @param bool|num $send
|
||||
* @return bool
|
||||
*/
|
||||
public function writeToOutput($send = null)
|
||||
{
|
||||
if(func_num_args() == 0) {
|
||||
return $this->sendOutput;
|
||||
}
|
||||
|
||||
return $this->sendOutput = (bool) $send;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an exception, ultimately generating a Whoops error
|
||||
* page.
|
||||
*
|
||||
* @param Exception $exception
|
||||
* @return string Output generated by handlers
|
||||
*/
|
||||
public function handleException(Exception $exception)
|
||||
{
|
||||
// Walk the registered handlers in the reverse order
|
||||
// they were registered, and pass off the exception
|
||||
$inspector = $this->getInspector($exception);
|
||||
|
||||
// Capture output produced while handling the exception,
|
||||
// we might want to send it straight away to the client,
|
||||
// or return it silently.
|
||||
ob_start();
|
||||
|
||||
for($i = count($this->handlerStack) - 1; $i >= 0; $i--) {
|
||||
$handler = $this->handlerStack[$i];
|
||||
|
||||
$handler->setRun($this);
|
||||
$handler->setInspector($inspector);
|
||||
$handler->setException($exception);
|
||||
|
||||
$handlerResponse = $handler->handle($exception);
|
||||
|
||||
if(in_array($handlerResponse, array(Handler::LAST_HANDLER, Handler::QUIT))) {
|
||||
// The Handler has handled the exception in some way, and
|
||||
// wishes to quit execution (Handler::QUIT), or skip any
|
||||
// other handlers (Handler::LAST_HANDLER). If $this->allowQuit
|
||||
// is false, Handler::QUIT behaves like Handler::LAST_HANDLER
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$output = ob_get_clean();
|
||||
|
||||
// If we're allowed to, send output generated by handlers directly
|
||||
// to the output, otherwise, and if the script doesn't quit, return
|
||||
// it so that it may be used by the caller
|
||||
if($this->writeToOutput()) {
|
||||
// @todo Might be able to clean this up a bit better
|
||||
// If we're going to quit execution, cleanup all other output
|
||||
// buffers before sending our own output:
|
||||
if($handlerResponse == Handler::QUIT && $this->allowQuit()) {
|
||||
while (ob_get_level() > 0) ob_end_clean();
|
||||
}
|
||||
|
||||
echo $output;
|
||||
}
|
||||
|
||||
// Handlers are done! Check if we got here because of Handler::QUIT
|
||||
// ($handlerResponse will be the response from the last queried handler)
|
||||
// and if so, try to quit execution.
|
||||
if($handlerResponse == Handler::QUIT && $this->allowQuit()) {
|
||||
exit;
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts generic PHP errors to \ErrorException
|
||||
* instances, before passing them off to be handled.
|
||||
*
|
||||
* This method MUST be compatible with set_error_handler.
|
||||
*
|
||||
* @param int $level
|
||||
* @param string $message
|
||||
* @param string $file
|
||||
* @param int $line
|
||||
*/
|
||||
public function handleError($level, $message, $file = null, $line = null)
|
||||
{
|
||||
if ($level & error_reporting()) {
|
||||
$this->handleException(
|
||||
new ErrorException(
|
||||
$message, $level, 0, $file, $line
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special case to deal with Fatal errors and the like.
|
||||
*/
|
||||
public function handleShutdown()
|
||||
{
|
||||
if($error = error_get_last()) {
|
||||
$this->handleError(
|
||||
$error['type'],
|
||||
$error['message'],
|
||||
$error['file'],
|
||||
$error['line']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user