Initial commit
This commit is contained in:
commit
1ff19bf38f
830 changed files with 159212 additions and 0 deletions
52
kirby/vendor/filp/whoops/src/Whoops/Handler/CallbackHandler.php
vendored
Normal file
52
kirby/vendor/filp/whoops/src/Whoops/Handler/CallbackHandler.php
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\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;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException If argument is not 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();
|
||||
$callable = $this->callable;
|
||||
|
||||
// invoke the callable directly, to get simpler stacktraces (in comparison to call_user_func).
|
||||
// this assumes that $callable is a properly typed php-callable, which we check in __construct().
|
||||
return $callable($exception, $inspector, $run);
|
||||
}
|
||||
}
|
95
kirby/vendor/filp/whoops/src/Whoops/Handler/Handler.php
vendored
Normal file
95
kirby/vendor/filp/whoops/src/Whoops/Handler/Handler.php
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
|
||||
use Whoops\Exception\Inspector;
|
||||
use Whoops\RunInterface;
|
||||
|
||||
/**
|
||||
* 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
|
||||
/**
|
||||
* The Handler has handled the Throwable in some way, and wishes to skip any other Handler.
|
||||
* Execution will continue.
|
||||
*/
|
||||
const LAST_HANDLER = 0x20;
|
||||
/**
|
||||
* The Handler has handled the Throwable in some way, and wishes to quit/stop execution
|
||||
*/
|
||||
const QUIT = 0x30;
|
||||
|
||||
/**
|
||||
* @var RunInterface
|
||||
*/
|
||||
private $run;
|
||||
|
||||
/**
|
||||
* @var Inspector $inspector
|
||||
*/
|
||||
private $inspector;
|
||||
|
||||
/**
|
||||
* @var \Throwable $exception
|
||||
*/
|
||||
private $exception;
|
||||
|
||||
/**
|
||||
* @param RunInterface $run
|
||||
*/
|
||||
public function setRun(RunInterface $run)
|
||||
{
|
||||
$this->run = $run;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RunInterface
|
||||
*/
|
||||
protected function getRun()
|
||||
{
|
||||
return $this->run;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Inspector $inspector
|
||||
*/
|
||||
public function setInspector(Inspector $inspector)
|
||||
{
|
||||
$this->inspector = $inspector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Inspector
|
||||
*/
|
||||
protected function getInspector()
|
||||
{
|
||||
return $this->inspector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Throwable $exception
|
||||
*/
|
||||
public function setException($exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Throwable
|
||||
*/
|
||||
protected function getException()
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
}
|
36
kirby/vendor/filp/whoops/src/Whoops/Handler/HandlerInterface.php
vendored
Normal file
36
kirby/vendor/filp/whoops/src/Whoops/Handler/HandlerInterface.php
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
|
||||
use Whoops\Exception\Inspector;
|
||||
use Whoops\RunInterface;
|
||||
|
||||
interface HandlerInterface
|
||||
{
|
||||
/**
|
||||
* @return int|null A handler may return nothing, or a Handler::HANDLE_* constant
|
||||
*/
|
||||
public function handle();
|
||||
|
||||
/**
|
||||
* @param RunInterface $run
|
||||
* @return void
|
||||
*/
|
||||
public function setRun(RunInterface $run);
|
||||
|
||||
/**
|
||||
* @param \Throwable $exception
|
||||
* @return void
|
||||
*/
|
||||
public function setException($exception);
|
||||
|
||||
/**
|
||||
* @param Inspector $inspector
|
||||
* @return void
|
||||
*/
|
||||
public function setInspector(Inspector $inspector);
|
||||
}
|
88
kirby/vendor/filp/whoops/src/Whoops/Handler/JsonResponseHandler.php
vendored
Normal file
88
kirby/vendor/filp/whoops/src/Whoops/Handler/JsonResponseHandler.php
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
|
||||
use Whoops\Exception\Formatter;
|
||||
|
||||
/**
|
||||
* 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 $jsonApi = false;
|
||||
|
||||
/**
|
||||
* Returns errors[[]] instead of error[] to be in compliance with the json:api spec
|
||||
* @param bool $jsonApi Default is false
|
||||
* @return static
|
||||
*/
|
||||
public function setJsonApi($jsonApi = false)
|
||||
{
|
||||
$this->jsonApi = (bool) $jsonApi;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool|null $returnFrames
|
||||
* @return bool|static
|
||||
*/
|
||||
public function addTraceToOutput($returnFrames = null)
|
||||
{
|
||||
if (func_num_args() == 0) {
|
||||
return $this->returnFrames;
|
||||
}
|
||||
|
||||
$this->returnFrames = (bool) $returnFrames;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->jsonApi === true) {
|
||||
$response = [
|
||||
'errors' => [
|
||||
Formatter::formatExceptionAsDataArray(
|
||||
$this->getInspector(),
|
||||
$this->addTraceToOutput()
|
||||
),
|
||||
]
|
||||
];
|
||||
} else {
|
||||
$response = [
|
||||
'error' => Formatter::formatExceptionAsDataArray(
|
||||
$this->getInspector(),
|
||||
$this->addTraceToOutput()
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
echo json_encode($response, defined('JSON_PARTIAL_OUTPUT_ON_ERROR') ? JSON_PARTIAL_OUTPUT_ON_ERROR : 0);
|
||||
|
||||
return Handler::QUIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function contentType()
|
||||
{
|
||||
return 'application/json';
|
||||
}
|
||||
}
|
359
kirby/vendor/filp/whoops/src/Whoops/Handler/PlainTextHandler.php
vendored
Normal file
359
kirby/vendor/filp/whoops/src/Whoops/Handler/PlainTextHandler.php
vendored
Normal file
|
@ -0,0 +1,359 @@
|
|||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
* Plaintext handler for command line and logs.
|
||||
* @author Pierre-Yves Landuré <https://howto.biapy.com/>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Whoops\Exception\Frame;
|
||||
|
||||
/**
|
||||
* Handler outputing plaintext error messages. Can be used
|
||||
* directly, or will be instantiated automagically by Whoops\Run
|
||||
* if passed to Run::pushHandler
|
||||
*/
|
||||
class PlainTextHandler extends Handler
|
||||
{
|
||||
const VAR_DUMP_PREFIX = ' | ';
|
||||
|
||||
/**
|
||||
* @var \Psr\Log\LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
protected $dumper;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $addTraceToOutput = true;
|
||||
|
||||
/**
|
||||
* @var bool|integer
|
||||
*/
|
||||
private $addTraceFunctionArgsToOutput = false;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
private $traceFunctionArgsOutputLimit = 1024;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $addPreviousToOutput = true;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $loggerOnly = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @throws InvalidArgumentException If argument is not null or a LoggerInterface
|
||||
* @param \Psr\Log\LoggerInterface|null $logger
|
||||
*/
|
||||
public function __construct($logger = null)
|
||||
{
|
||||
$this->setLogger($logger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output logger interface.
|
||||
* @throws InvalidArgumentException If argument is not null or a LoggerInterface
|
||||
* @param \Psr\Log\LoggerInterface|null $logger
|
||||
*/
|
||||
public function setLogger($logger = null)
|
||||
{
|
||||
if (! (is_null($logger)
|
||||
|| $logger instanceof LoggerInterface)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Argument to ' . __METHOD__ .
|
||||
" must be a valid Logger Interface (aka. Monolog), " .
|
||||
get_class($logger) . ' given.'
|
||||
);
|
||||
}
|
||||
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Psr\Log\LoggerInterface|null
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
return $this->logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set var dumper callback function.
|
||||
*
|
||||
* @param callable $dumper
|
||||
* @return static
|
||||
*/
|
||||
public function setDumper(callable $dumper)
|
||||
{
|
||||
$this->dumper = $dumper;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add error trace to output.
|
||||
* @param bool|null $addTraceToOutput
|
||||
* @return bool|static
|
||||
*/
|
||||
public function addTraceToOutput($addTraceToOutput = null)
|
||||
{
|
||||
if (func_num_args() == 0) {
|
||||
return $this->addTraceToOutput;
|
||||
}
|
||||
|
||||
$this->addTraceToOutput = (bool) $addTraceToOutput;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add previous exceptions to output.
|
||||
* @param bool|null $addPreviousToOutput
|
||||
* @return bool|static
|
||||
*/
|
||||
public function addPreviousToOutput($addPreviousToOutput = null)
|
||||
{
|
||||
if (func_num_args() == 0) {
|
||||
return $this->addPreviousToOutput;
|
||||
}
|
||||
|
||||
$this->addPreviousToOutput = (bool) $addPreviousToOutput;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add error trace function arguments to output.
|
||||
* Set to True for all frame args, or integer for the n first frame args.
|
||||
* @param bool|integer|null $addTraceFunctionArgsToOutput
|
||||
* @return static|bool|integer
|
||||
*/
|
||||
public function addTraceFunctionArgsToOutput($addTraceFunctionArgsToOutput = null)
|
||||
{
|
||||
if (func_num_args() == 0) {
|
||||
return $this->addTraceFunctionArgsToOutput;
|
||||
}
|
||||
|
||||
if (! is_integer($addTraceFunctionArgsToOutput)) {
|
||||
$this->addTraceFunctionArgsToOutput = (bool) $addTraceFunctionArgsToOutput;
|
||||
} else {
|
||||
$this->addTraceFunctionArgsToOutput = $addTraceFunctionArgsToOutput;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the size limit in bytes of frame arguments var_dump output.
|
||||
* If the limit is reached, the var_dump output is discarded.
|
||||
* Prevent memory limit errors.
|
||||
* @var integer
|
||||
* @return static
|
||||
*/
|
||||
public function setTraceFunctionArgsOutputLimit($traceFunctionArgsOutputLimit)
|
||||
{
|
||||
$this->traceFunctionArgsOutputLimit = (integer) $traceFunctionArgsOutputLimit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create plain text response and return it as a string
|
||||
* @return string
|
||||
*/
|
||||
public function generateResponse()
|
||||
{
|
||||
$exception = $this->getException();
|
||||
$message = $this->getExceptionOutput($exception);
|
||||
|
||||
if ($this->addPreviousToOutput) {
|
||||
$previous = $exception->getPrevious();
|
||||
while ($previous) {
|
||||
$message .= "\n\nCaused by\n" . $this->getExceptionOutput($previous);
|
||||
$previous = $previous->getPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $message . $this->getTraceOutput() . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size limit in bytes of frame arguments var_dump output.
|
||||
* If the limit is reached, the var_dump output is discarded.
|
||||
* Prevent memory limit errors.
|
||||
* @return integer
|
||||
*/
|
||||
public function getTraceFunctionArgsOutputLimit()
|
||||
{
|
||||
return $this->traceFunctionArgsOutputLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only output to logger.
|
||||
* @param bool|null $loggerOnly
|
||||
* @return static|bool
|
||||
*/
|
||||
public function loggerOnly($loggerOnly = null)
|
||||
{
|
||||
if (func_num_args() == 0) {
|
||||
return $this->loggerOnly;
|
||||
}
|
||||
|
||||
$this->loggerOnly = (bool) $loggerOnly;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if handler can output to stdout.
|
||||
* @return bool
|
||||
*/
|
||||
private function canOutput()
|
||||
{
|
||||
return !$this->loggerOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the frame args var_dump.
|
||||
* @param \Whoops\Exception\Frame $frame [description]
|
||||
* @param integer $line [description]
|
||||
* @return string
|
||||
*/
|
||||
private function getFrameArgsOutput(Frame $frame, $line)
|
||||
{
|
||||
if ($this->addTraceFunctionArgsToOutput() === false
|
||||
|| $this->addTraceFunctionArgsToOutput() < $line) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Dump the arguments:
|
||||
ob_start();
|
||||
$this->dump($frame->getArgs());
|
||||
if (ob_get_length() > $this->getTraceFunctionArgsOutputLimit()) {
|
||||
// The argument var_dump is to big.
|
||||
// Discarded to limit memory usage.
|
||||
ob_clean();
|
||||
return sprintf(
|
||||
"\n%sArguments dump length greater than %d Bytes. Discarded.",
|
||||
self::VAR_DUMP_PREFIX,
|
||||
$this->getTraceFunctionArgsOutputLimit()
|
||||
);
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
"\n%s",
|
||||
preg_replace('/^/m', self::VAR_DUMP_PREFIX, ob_get_clean())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump variable.
|
||||
*
|
||||
* @param mixed $var
|
||||
* @return void
|
||||
*/
|
||||
protected function dump($var)
|
||||
{
|
||||
if ($this->dumper) {
|
||||
call_user_func($this->dumper, $var);
|
||||
} else {
|
||||
var_dump($var);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception trace as plain text.
|
||||
* @return string
|
||||
*/
|
||||
private function getTraceOutput()
|
||||
{
|
||||
if (! $this->addTraceToOutput()) {
|
||||
return '';
|
||||
}
|
||||
$inspector = $this->getInspector();
|
||||
$frames = $inspector->getFrames();
|
||||
|
||||
$response = "\nStack trace:";
|
||||
|
||||
$line = 1;
|
||||
foreach ($frames as $frame) {
|
||||
/** @var Frame $frame */
|
||||
$class = $frame->getClass();
|
||||
|
||||
$template = "\n%3d. %s->%s() %s:%d%s";
|
||||
if (! $class) {
|
||||
// Remove method arrow (->) from output.
|
||||
$template = "\n%3d. %s%s() %s:%d%s";
|
||||
}
|
||||
|
||||
$response .= sprintf(
|
||||
$template,
|
||||
$line,
|
||||
$class,
|
||||
$frame->getFunction(),
|
||||
$frame->getFile(),
|
||||
$frame->getLine(),
|
||||
$this->getFrameArgsOutput($frame, $line)
|
||||
);
|
||||
|
||||
$line++;
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception as plain text.
|
||||
* @param \Throwable $exception
|
||||
* @return string
|
||||
*/
|
||||
private function getExceptionOutput($exception)
|
||||
{
|
||||
return sprintf(
|
||||
"%s: %s in file %s on line %d",
|
||||
get_class($exception),
|
||||
$exception->getMessage(),
|
||||
$exception->getFile(),
|
||||
$exception->getLine()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$response = $this->generateResponse();
|
||||
|
||||
if ($this->getLogger()) {
|
||||
$this->getLogger()->error($response);
|
||||
}
|
||||
|
||||
if (! $this->canOutput()) {
|
||||
return Handler::DONE;
|
||||
}
|
||||
|
||||
echo $response;
|
||||
|
||||
return Handler::QUIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function contentType()
|
||||
{
|
||||
return 'text/plain';
|
||||
}
|
||||
}
|
830
kirby/vendor/filp/whoops/src/Whoops/Handler/PrettyPageHandler.php
vendored
Normal file
830
kirby/vendor/filp/whoops/src/Whoops/Handler/PrettyPageHandler.php
vendored
Normal file
|
@ -0,0 +1,830 @@
|
|||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\VarDumper\Cloner\AbstractCloner;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use UnexpectedValueException;
|
||||
use Whoops\Exception\Formatter;
|
||||
use Whoops\Util\Misc;
|
||||
use Whoops\Util\TemplateHelper;
|
||||
|
||||
class PrettyPageHandler extends Handler
|
||||
{
|
||||
const EDITOR_SUBLIME = "sublime";
|
||||
const EDITOR_TEXTMATE = "textmate";
|
||||
const EDITOR_EMACS = "emacs";
|
||||
const EDITOR_MACVIM = "macvim";
|
||||
const EDITOR_PHPSTORM = "phpstorm";
|
||||
const EDITOR_IDEA = "idea";
|
||||
const EDITOR_VSCODE = "vscode";
|
||||
const EDITOR_ATOM = "atom";
|
||||
const EDITOR_ESPRESSO = "espresso";
|
||||
const EDITOR_XDEBUG = "xdebug";
|
||||
|
||||
/**
|
||||
* Search paths to be scanned for resources.
|
||||
*
|
||||
* Stored in the reverse order they're declared.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $searchPaths = [];
|
||||
|
||||
/**
|
||||
* Fast lookup cache for known resource locations.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $resourceCache = [];
|
||||
|
||||
/**
|
||||
* The name of the custom css file.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $customCss = null;
|
||||
|
||||
/**
|
||||
* The name of the custom js file.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
private $customJs = null;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
private $extraTables = [];
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $handleUnconditionally = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $pageTitle = "Whoops! There was an error.";
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
private $applicationPaths;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
private $blacklist = [
|
||||
'_GET' => [],
|
||||
'_POST' => [],
|
||||
'_FILES' => [],
|
||||
'_COOKIE' => [],
|
||||
'_SESSION' => [],
|
||||
'_SERVER' => [],
|
||||
'_ENV' => [],
|
||||
];
|
||||
|
||||
/**
|
||||
* An identifier for a known IDE/text editor.
|
||||
*
|
||||
* Either a string, or a calalble 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 callable|string $editor
|
||||
*/
|
||||
protected $editor;
|
||||
|
||||
/**
|
||||
* A list of known editor strings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $editors = [
|
||||
"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",
|
||||
"phpstorm" => "phpstorm://open?file=%file&line=%line",
|
||||
"idea" => "idea://open?file=%file&line=%line",
|
||||
"vscode" => "vscode://file/%file:%line",
|
||||
"atom" => "atom://core/open/file?filename=%file&line=%line",
|
||||
"espresso" => "x-espresso://open?filepath=%file&lines=%line",
|
||||
];
|
||||
|
||||
/**
|
||||
* @var TemplateHelper
|
||||
*/
|
||||
protected $templateHelper;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
if (ini_get('xdebug.file_link_format') || extension_loaded('xdebug')) {
|
||||
// Register editor using xdebug's file_link_format option.
|
||||
$this->editors['xdebug'] = function ($file, $line) {
|
||||
return str_replace(['%f', '%l'], [$file, $line], ini_get('xdebug.file_link_format'));
|
||||
};
|
||||
|
||||
// If xdebug is available, use it as default editor.
|
||||
$this->setEditor('xdebug');
|
||||
}
|
||||
|
||||
// Add the default, local resource search path:
|
||||
$this->searchPaths[] = __DIR__ . "/../Resources";
|
||||
|
||||
// blacklist php provided auth based values
|
||||
$this->blacklist('_SERVER', 'PHP_AUTH_PW');
|
||||
|
||||
$this->templateHelper = new TemplateHelper();
|
||||
|
||||
if (class_exists('Symfony\Component\VarDumper\Cloner\VarCloner')) {
|
||||
$cloner = new VarCloner();
|
||||
// Only dump object internals if a custom caster exists for performance reasons
|
||||
// https://github.com/filp/whoops/pull/404
|
||||
$cloner->addCasters(['*' => function ($obj, $a, $stub, $isNested, $filter = 0) {
|
||||
$class = $stub->class;
|
||||
$classes = [$class => $class] + class_parents($obj) + class_implements($obj);
|
||||
|
||||
foreach ($classes as $class) {
|
||||
if (isset(AbstractCloner::$defaultCasters[$class])) {
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all internals
|
||||
return [];
|
||||
}]);
|
||||
$this->templateHelper->setCloner($cloner);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|null
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (!$this->handleUnconditionally()) {
|
||||
// Check conditions for outputting HTML:
|
||||
// @todo: Make this more robust
|
||||
if (PHP_SAPI === 'cli') {
|
||||
// Help users who have been relying on an internal test value
|
||||
// fix their code to the proper method
|
||||
if (isset($_ENV['whoops-test'])) {
|
||||
throw new \Exception(
|
||||
'Use handleUnconditionally instead of whoops-test'
|
||||
.' environment variable'
|
||||
);
|
||||
}
|
||||
|
||||
return Handler::DONE;
|
||||
}
|
||||
}
|
||||
|
||||
$templateFile = $this->getResource("views/layout.html.php");
|
||||
$cssFile = $this->getResource("css/whoops.base.css");
|
||||
$zeptoFile = $this->getResource("js/zepto.min.js");
|
||||
$prettifyFile = $this->getResource("js/prettify.min.js");
|
||||
$clipboard = $this->getResource("js/clipboard.min.js");
|
||||
$jsFile = $this->getResource("js/whoops.base.js");
|
||||
|
||||
if ($this->customCss) {
|
||||
$customCssFile = $this->getResource($this->customCss);
|
||||
}
|
||||
|
||||
if ($this->customJs) {
|
||||
$customJsFile = $this->getResource($this->customJs);
|
||||
}
|
||||
|
||||
$inspector = $this->getInspector();
|
||||
$frames = $this->getExceptionFrames();
|
||||
$code = $this->getExceptionCode();
|
||||
|
||||
// List of variables that will be passed to the layout template.
|
||||
$vars = [
|
||||
"page_title" => $this->getPageTitle(),
|
||||
|
||||
// @todo: Asset compiler
|
||||
"stylesheet" => file_get_contents($cssFile),
|
||||
"zepto" => file_get_contents($zeptoFile),
|
||||
"prettify" => file_get_contents($prettifyFile),
|
||||
"clipboard" => file_get_contents($clipboard),
|
||||
"javascript" => file_get_contents($jsFile),
|
||||
|
||||
// Template paths:
|
||||
"header" => $this->getResource("views/header.html.php"),
|
||||
"header_outer" => $this->getResource("views/header_outer.html.php"),
|
||||
"frame_list" => $this->getResource("views/frame_list.html.php"),
|
||||
"frames_description" => $this->getResource("views/frames_description.html.php"),
|
||||
"frames_container" => $this->getResource("views/frames_container.html.php"),
|
||||
"panel_details" => $this->getResource("views/panel_details.html.php"),
|
||||
"panel_details_outer" => $this->getResource("views/panel_details_outer.html.php"),
|
||||
"panel_left" => $this->getResource("views/panel_left.html.php"),
|
||||
"panel_left_outer" => $this->getResource("views/panel_left_outer.html.php"),
|
||||
"frame_code" => $this->getResource("views/frame_code.html.php"),
|
||||
"env_details" => $this->getResource("views/env_details.html.php"),
|
||||
|
||||
"title" => $this->getPageTitle(),
|
||||
"name" => explode("\\", $inspector->getExceptionName()),
|
||||
"message" => $inspector->getExceptionMessage(),
|
||||
"previousMessages" => $inspector->getPreviousExceptionMessages(),
|
||||
"docref_url" => $inspector->getExceptionDocrefUrl(),
|
||||
"code" => $code,
|
||||
"previousCodes" => $inspector->getPreviousExceptionCodes(),
|
||||
"plain_exception" => Formatter::formatExceptionPlain($inspector),
|
||||
"frames" => $frames,
|
||||
"has_frames" => !!count($frames),
|
||||
"handler" => $this,
|
||||
"handlers" => $this->getRun()->getHandlers(),
|
||||
|
||||
"active_frames_tab" => count($frames) && $frames->offsetGet(0)->isApplication() ? 'application' : 'all',
|
||||
"has_frames_tabs" => $this->getApplicationPaths(),
|
||||
|
||||
"tables" => [
|
||||
"GET Data" => $this->masked($_GET, '_GET'),
|
||||
"POST Data" => $this->masked($_POST, '_POST'),
|
||||
"Files" => isset($_FILES) ? $this->masked($_FILES, '_FILES') : [],
|
||||
"Cookies" => $this->masked($_COOKIE, '_COOKIE'),
|
||||
"Session" => isset($_SESSION) ? $this->masked($_SESSION, '_SESSION') : [],
|
||||
"Server/Request Data" => $this->masked($_SERVER, '_SERVER'),
|
||||
"Environment Variables" => $this->masked($_ENV, '_ENV'),
|
||||
],
|
||||
];
|
||||
|
||||
if (isset($customCssFile)) {
|
||||
$vars["stylesheet"] .= file_get_contents($customCssFile);
|
||||
}
|
||||
|
||||
if (isset($customJsFile)) {
|
||||
$vars["javascript"] .= file_get_contents($customJsFile);
|
||||
}
|
||||
|
||||
// Add extra entries list of data tables:
|
||||
// @todo: Consolidate addDataTable and addDataTableCallback
|
||||
$extraTables = array_map(function ($table) use ($inspector) {
|
||||
return $table instanceof \Closure ? $table($inspector) : $table;
|
||||
}, $this->getDataTables());
|
||||
$vars["tables"] = array_merge($extraTables, $vars["tables"]);
|
||||
|
||||
$plainTextHandler = new PlainTextHandler();
|
||||
$plainTextHandler->setException($this->getException());
|
||||
$plainTextHandler->setInspector($this->getInspector());
|
||||
$vars["preface"] = "<!--\n\n\n" . $this->templateHelper->escape($plainTextHandler->generateResponse()) . "\n\n\n\n\n\n\n\n\n\n\n-->";
|
||||
|
||||
$this->templateHelper->setVariables($vars);
|
||||
$this->templateHelper->render($templateFile);
|
||||
|
||||
return Handler::QUIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stack trace frames of the exception currently being handled.
|
||||
*
|
||||
* @return \Whoops\Exception\FrameCollection
|
||||
*/
|
||||
protected function getExceptionFrames()
|
||||
{
|
||||
$frames = $this->getInspector()->getFrames();
|
||||
|
||||
if ($this->getApplicationPaths()) {
|
||||
foreach ($frames as $frame) {
|
||||
foreach ($this->getApplicationPaths() as $path) {
|
||||
if (strpos($frame->getFile(), $path) === 0) {
|
||||
$frame->setApplication(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the code of the exception currently being handled.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getExceptionCode()
|
||||
{
|
||||
$exception = $this->getException();
|
||||
|
||||
$code = $exception->getCode();
|
||||
if ($exception instanceof \ErrorException) {
|
||||
// ErrorExceptions wrap the php-error types within the 'severity' property
|
||||
$code = Misc::translateErrorCode($exception->getSeverity());
|
||||
}
|
||||
|
||||
return (string) $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function contentType()
|
||||
{
|
||||
return 'text/html';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addDataTable($label, array $data)
|
||||
{
|
||||
$this->extraTables[$label] = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @throws InvalidArgumentException If $callback is not callable
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addDataTableCallback($label, /* callable */ $callback)
|
||||
{
|
||||
if (!is_callable($callback)) {
|
||||
throw new InvalidArgumentException('Expecting callback argument to be callable');
|
||||
}
|
||||
|
||||
$this->extraTables[$label] = function (\Whoops\Exception\Inspector $inspector = null) use ($callback) {
|
||||
try {
|
||||
$result = call_user_func($callback, $inspector);
|
||||
|
||||
// Only return the result if it can be iterated over by foreach().
|
||||
return is_array($result) || $result instanceof \Traversable ? $result : [];
|
||||
} catch (\Exception $e) {
|
||||
// Don't allow failure to break the rendering of the original exception.
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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[]|callable
|
||||
*/
|
||||
public function getDataTables($label = null)
|
||||
{
|
||||
if ($label !== null) {
|
||||
return isset($this->extraTables[$label]) ?
|
||||
$this->extraTables[$label] : [];
|
||||
}
|
||||
|
||||
return $this->extraTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to handle unconditionally.
|
||||
*
|
||||
* Allows to disable all attempts to dynamically decide whether to handle
|
||||
* or return prematurely. Set this to ensure that the handler will perform,
|
||||
* no matter what.
|
||||
*
|
||||
* @param bool|null $value
|
||||
*
|
||||
* @return bool|static
|
||||
*/
|
||||
public function handleUnconditionally($value = null)
|
||||
{
|
||||
if (func_num_args() == 0) {
|
||||
return $this->handleUnconditionally;
|
||||
}
|
||||
|
||||
$this->handleUnconditionally = (bool) $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an editor resolver.
|
||||
*
|
||||
* Either a string, 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
|
||||
* $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|callable $resolver
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addEditor($identifier, $resolver)
|
||||
{
|
||||
$this->editors[$identifier] = $resolver;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the editor to use to open referenced files.
|
||||
*
|
||||
* Pass either the name of a configured editor, or a closure that directly
|
||||
* resolves an editor string.
|
||||
*
|
||||
* @example
|
||||
* $run->setEditor(function($file, $line) { return "file:///{$file}"; });
|
||||
* @example
|
||||
* $run->setEditor('sublime');
|
||||
*
|
||||
* @param string|callable $editor
|
||||
*
|
||||
* @throws InvalidArgumentException If invalid argument identifier provided
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
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;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the editor href for a given file and line, if available.
|
||||
*
|
||||
* @param string $filePath
|
||||
* @param int $line
|
||||
*
|
||||
* @throws InvalidArgumentException If editor resolver does not return a string
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public function getEditorHref($filePath, $line)
|
||||
{
|
||||
$editor = $this->getEditor($filePath, $line);
|
||||
|
||||
if (empty($editor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the editor is a string, and replace the
|
||||
// %line and %file placeholders:
|
||||
if (!isset($editor['url']) || !is_string($editor['url'])) {
|
||||
throw new UnexpectedValueException(
|
||||
__METHOD__ . " should always resolve to a string or a valid editor array; got something else instead."
|
||||
);
|
||||
}
|
||||
|
||||
$editor['url'] = str_replace("%line", rawurlencode($line), $editor['url']);
|
||||
$editor['url'] = str_replace("%file", rawurlencode($filePath), $editor['url']);
|
||||
|
||||
return $editor['url'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the editor link should act as an Ajax request.
|
||||
*
|
||||
* @param string $filePath
|
||||
* @param int $line
|
||||
*
|
||||
* @throws UnexpectedValueException If editor resolver does not return a boolean
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getEditorAjax($filePath, $line)
|
||||
{
|
||||
$editor = $this->getEditor($filePath, $line);
|
||||
|
||||
// Check that the ajax is a bool
|
||||
if (!isset($editor['ajax']) || !is_bool($editor['ajax'])) {
|
||||
throw new UnexpectedValueException(
|
||||
__METHOD__ . " should always resolve to a bool; got something else instead."
|
||||
);
|
||||
}
|
||||
return $editor['ajax'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines both the editor and if ajax should be used.
|
||||
*
|
||||
* @param string $filePath
|
||||
* @param int $line
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getEditor($filePath, $line)
|
||||
{
|
||||
if (!$this->editor || (!is_string($this->editor) && !is_callable($this->editor))) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (is_string($this->editor) && isset($this->editors[$this->editor]) && !is_callable($this->editors[$this->editor])) {
|
||||
return [
|
||||
'ajax' => false,
|
||||
'url' => $this->editors[$this->editor],
|
||||
];
|
||||
}
|
||||
|
||||
if (is_callable($this->editor) || (isset($this->editors[$this->editor]) && is_callable($this->editors[$this->editor]))) {
|
||||
if (is_callable($this->editor)) {
|
||||
$callback = call_user_func($this->editor, $filePath, $line);
|
||||
} else {
|
||||
$callback = call_user_func($this->editors[$this->editor], $filePath, $line);
|
||||
}
|
||||
|
||||
if (empty($callback)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (is_string($callback)) {
|
||||
return [
|
||||
'ajax' => false,
|
||||
'url' => $callback,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'ajax' => isset($callback['ajax']) ? $callback['ajax'] : false,
|
||||
'url' => isset($callback['url']) ? $callback['url'] : $callback,
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the page title.
|
||||
*
|
||||
* @param string $title
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setPageTitle($title)
|
||||
{
|
||||
$this->pageTitle = (string) $title;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPageTitle()
|
||||
{
|
||||
return $this->pageTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a path to the list of paths to be searched for resources.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @throws InvalidArgumentException If $path is not a valid directory
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addResourcePath($path)
|
||||
{
|
||||
if (!is_dir($path)) {
|
||||
throw new InvalidArgumentException(
|
||||
"'$path' is not a valid directory"
|
||||
);
|
||||
}
|
||||
|
||||
array_unshift($this->searchPaths, $path);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom css file to be loaded.
|
||||
*
|
||||
* @param string|null $name
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addCustomCss($name)
|
||||
{
|
||||
$this->customCss = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a custom js file to be loaded.
|
||||
*
|
||||
* @param string|null $name
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addCustomJs($name)
|
||||
{
|
||||
$this->customJs = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResourcePaths()
|
||||
{
|
||||
return $this->searchPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a resource, by its relative path, in all available search paths.
|
||||
*
|
||||
* The search is performed starting at the last search path, and all the
|
||||
* way back to the first, enabling a cascading-type system of overrides for
|
||||
* all resources.
|
||||
*
|
||||
* @param string $resource
|
||||
*
|
||||
* @throws RuntimeException If resource cannot be found in any of the available paths
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getResource($resource)
|
||||
{
|
||||
// If the resource was found before, we can speed things up
|
||||
// by caching its absolute, resolved path:
|
||||
if (isset($this->resourceCache[$resource])) {
|
||||
return $this->resourceCache[$resource];
|
||||
}
|
||||
|
||||
// Search through available search paths, until we find the
|
||||
// resource we're after:
|
||||
foreach ($this->searchPaths as $path) {
|
||||
$fullPath = $path . "/$resource";
|
||||
|
||||
if (is_file($fullPath)) {
|
||||
// Cache the result:
|
||||
$this->resourceCache[$resource] = $fullPath;
|
||||
return $fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
// If we got this far, nothing was found.
|
||||
throw new RuntimeException(
|
||||
"Could not find resource '$resource' in any resource paths."
|
||||
. "(searched: " . join(", ", $this->searchPaths). ")"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getResourcesPath()
|
||||
{
|
||||
$allPaths = $this->getResourcePaths();
|
||||
|
||||
// Compat: return only the first path added
|
||||
return end($allPaths) ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $resourcesPath
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setResourcesPath($resourcesPath)
|
||||
{
|
||||
$this->addResourcePath($resourcesPath);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the application paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getApplicationPaths()
|
||||
{
|
||||
return $this->applicationPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the application paths.
|
||||
*
|
||||
* @param array $applicationPaths
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApplicationPaths($applicationPaths)
|
||||
{
|
||||
$this->applicationPaths = $applicationPaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the application root path.
|
||||
*
|
||||
* @param string $applicationRootPath
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setApplicationRootPath($applicationRootPath)
|
||||
{
|
||||
$this->templateHelper->setApplicationRootPath($applicationRootPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* blacklist a sensitive value within one of the superglobal arrays.
|
||||
* Alias for the hideSuperglobalKey method.
|
||||
*
|
||||
* @param string $superGlobalName The name of the superglobal array, e.g. '_GET'
|
||||
* @param string $key The key within the superglobal
|
||||
* @see hideSuperglobalKey
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function blacklist($superGlobalName, $key)
|
||||
{
|
||||
$this->blacklist[$superGlobalName][] = $key;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide a sensitive value within one of the superglobal arrays.
|
||||
*
|
||||
* @param string $superGlobalName The name of the superglobal array, e.g. '_GET'
|
||||
* @param string $key The key within the superglobal
|
||||
* @return static
|
||||
*/
|
||||
public function hideSuperglobalKey($superGlobalName, $key)
|
||||
{
|
||||
return $this->blacklist($superGlobalName, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks all values within the given superGlobal array.
|
||||
*
|
||||
* Blacklisted values will be replaced by a equal length string containing
|
||||
* only '*' characters for string values.
|
||||
* Non-string values will be replaced with a fixed asterisk count.
|
||||
* We intentionally dont rely on $GLOBALS as it depends on the 'auto_globals_jit' php.ini setting.
|
||||
*
|
||||
* @param array $superGlobal One of the superglobal arrays
|
||||
* @param string $superGlobalName The name of the superglobal array, e.g. '_GET'
|
||||
*
|
||||
* @return array $values without sensitive data
|
||||
*/
|
||||
private function masked(array $superGlobal, $superGlobalName)
|
||||
{
|
||||
$blacklisted = $this->blacklist[$superGlobalName];
|
||||
|
||||
$values = $superGlobal;
|
||||
|
||||
foreach ($blacklisted as $key) {
|
||||
if (isset($superGlobal[$key])) {
|
||||
$values[$key] = str_repeat('*', is_string($superGlobal[$key]) ? strlen($superGlobal[$key]) : 3);
|
||||
}
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
}
|
107
kirby/vendor/filp/whoops/src/Whoops/Handler/XmlResponseHandler.php
vendored
Normal file
107
kirby/vendor/filp/whoops/src/Whoops/Handler/XmlResponseHandler.php
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
/**
|
||||
* Whoops - php errors for cool kids
|
||||
* @author Filipe Dobreira <http://github.com/filp>
|
||||
*/
|
||||
|
||||
namespace Whoops\Handler;
|
||||
|
||||
use SimpleXMLElement;
|
||||
use Whoops\Exception\Formatter;
|
||||
|
||||
/**
|
||||
* Catches an exception and converts it to an XML
|
||||
* response. Additionally can also return exception
|
||||
* frames for consumption by an API.
|
||||
*/
|
||||
class XmlResponseHandler extends Handler
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $returnFrames = false;
|
||||
|
||||
/**
|
||||
* @param bool|null $returnFrames
|
||||
* @return bool|static
|
||||
*/
|
||||
public function addTraceToOutput($returnFrames = null)
|
||||
{
|
||||
if (func_num_args() == 0) {
|
||||
return $this->returnFrames;
|
||||
}
|
||||
|
||||
$this->returnFrames = (bool) $returnFrames;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$response = [
|
||||
'error' => Formatter::formatExceptionAsDataArray(
|
||||
$this->getInspector(),
|
||||
$this->addTraceToOutput()
|
||||
),
|
||||
];
|
||||
|
||||
echo self::toXml($response);
|
||||
|
||||
return Handler::QUIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function contentType()
|
||||
{
|
||||
return 'application/xml';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SimpleXMLElement $node Node to append data to, will be modified in place
|
||||
* @param array|\Traversable $data
|
||||
* @return SimpleXMLElement The modified node, for chaining
|
||||
*/
|
||||
private static function addDataToNode(\SimpleXMLElement $node, $data)
|
||||
{
|
||||
assert(is_array($data) || $data instanceof Traversable);
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_numeric($key)) {
|
||||
// Convert the key to a valid string
|
||||
$key = "unknownNode_". (string) $key;
|
||||
}
|
||||
|
||||
// Delete any char not allowed in XML element names
|
||||
$key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);
|
||||
|
||||
if (is_array($value)) {
|
||||
$child = $node->addChild($key);
|
||||
self::addDataToNode($child, $value);
|
||||
} else {
|
||||
$value = str_replace('&', '&', print_r($value, true));
|
||||
$node->addChild($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main function for converting to an XML document.
|
||||
*
|
||||
* @param array|\Traversable $data
|
||||
* @return string XML
|
||||
*/
|
||||
private static function toXml($data)
|
||||
{
|
||||
assert(is_array($data) || $data instanceof Traversable);
|
||||
|
||||
$node = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><root />");
|
||||
|
||||
return self::addDataToNode($node, $data)->asXML();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue