Skip to content

Commit

Permalink
feat(core): add new code base for Whoops Error handling with updated …
Browse files Browse the repository at this point in the history
…settings
  • Loading branch information
Awilum committed Sep 3, 2021
1 parent 50f1b44 commit 578ddbe
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 40 deletions.
7 changes: 3 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@

"slim/slim": "^4.8.1",

"filp/whoops": "^2.14",

"league/event": "^2.2.0",
"league/glide": "^2.0.0",

Expand All @@ -56,10 +54,11 @@
"slim/psr7": "^1.4",
"php-di/php-di": "^6.3.4",
"php-di/slim-bridge": "^3.1.1",
"middlewares/whoops": "^2.0",
"nette/neon": "^3.2",
"league/commonmark": "^2.0",
"siriusphp/upload": "^3.0"
"siriusphp/upload": "^3.0",

"filp/whoops": "^2.14"
},
"suggest": {
"ext-zend-opcache": "Recommended for better performance",
Expand Down
50 changes: 50 additions & 0 deletions src/flextype/core/Middlewares/WhoopsMiddleware.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

declare(strict_types=1);

/**
* Flextype (https://flextype.org)
* Founded by Sergey Romanenko and maintained by Flextype Community.
*/

namespace Flextype\Middlewares;

use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Flextype\WhoopsGuard;

class WhoopsMiddleware implements MiddlewareInterface {

protected $settings = [];
protected $handlers = [];

/**
* Instance the whoops middleware object
*
* @param array $settings
* @param array $handlers
*/
public function __construct(array $settings = [], array $handlers = []) {
$this->settings = $settings;
$this->handlers = $handlers;
}

/**
* Handle the requests
*
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
$whoopsGuard = new WhoopsGuard($this->settings);
$whoopsGuard->setRequest($request);
$whoopsGuard->setHandlers($this->handlers);
$whoopsGuard->install();

return $handler->handle($request);
}

}
141 changes: 141 additions & 0 deletions src/flextype/core/WhoopsGuard.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

declare(strict_types=1);

/**
* Flextype (https://flextype.org)
* Founded by Sergey Romanenko and maintained by Flextype Community.
*/

namespace Flextype;

use Psr\Http\Message\ServerRequestInterface;
use Whoops\Run as WhoopsRun;
use Whoops\Util\Misc;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Handler\PlainTextHandler;
use Whoops\Handler\JsonResponseHandler;
use Whoops\Handler\XmlResponseHandler;

class WhoopsGuard {

protected $settings = [];
protected $request = null;
protected $handlers = [];

/**
* Instance the whoops guard object
*
* @param array $settings
*/
public function __construct(array $settings = []) {
$this->settings = array_merge([
'enable' => true,
'editor' => '',
'title' => '',
], $settings);
}

/**
* Set the server request object
*
* @param ServerRequestInterface $request
* @return void
*/
public function setRequest(ServerRequestInterface $request): void {
$this->request = $request;
}

/**
* Set the custom handlers for whoops
*
* @param array $handlers
* @return void
*/
public function setHandlers(array $handlers): void {
$this->handlers = $handlers;
}

/**
* Install the whoops guard object
*
* @return WhoopsRun|null
*/
public function install(): ?WhoopsRun {
if ($this->settings['enable'] === false) {
return null;
}

// Enable PrettyPageHandler with editor options
$prettyPageHandler = new PrettyPageHandler();

if (empty($this->settings['editor']) === false) {
$prettyPageHandler->setEditor($this->settings['editor']);
}

if (empty($this->settings['title']) === false) {
$prettyPageHandler->setPageTitle($this->settings['title']);
}

// Add more information to the PrettyPageHandler
$contentCharset = '<none>';
if (
method_exists($this->request, 'getContentCharset') === true &&
$this->request->getContentCharset() !== null
) {
$contentCharset = $this->request->getContentCharset();
}

$prettyPageHandler->addDataTable('Flextype', [
'Version' => Flextype::VERSION,
'Accept Charset' => $this->request->getHeader('ACCEPT_CHARSET') ?: '<none>',
'Content Charset' => $contentCharset,
'HTTP Method' => $this->request->getMethod(),
'Path' => $this->request->getUri()->getPath(),
'Query String' => $this->request->getUri()->getQuery() ?: '<none>',
'Base URL' => (string) $this->request->getUri(),
'Scheme' => $this->request->getUri()->getScheme(),
'Port' => $this->request->getUri()->getPort(),
'Host' => $this->request->getUri()->getHost(),
]);

// Set Whoops to default exception handler
$whoops = new \Whoops\Run;

switch ($this->settings['handler']) {
case 'json':
$whoops->pushHandler(new JsonResponseHandler());
break;

case 'xml':
$whoops->pushHandler(new XmlResponseHandler());
break;

case 'plain':
$whoops->pushHandler(new PlainTextHandler());
break;

case 'pretty':
default:
$whoops->pushHandler($prettyPageHandler);
break;
}

// Enable JsonResponseHandler when request is AJAX
if (Misc::isAjaxRequest() === true){
$whoops->pushHandler(new JsonResponseHandler());
}

// Add each custom handler to whoops handler stack
if (empty($this->handlers) === false) {
foreach($this->handlers as $handler) {
$whoops->pushHandler($handler);
}
}

$whoops->register();

return $whoops;
}

}
38 changes: 17 additions & 21 deletions src/flextype/flextype.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use Flextype\Entries\Entries;
use Flextype\Handlers\HttpErrorHandler;
use Flextype\Handlers\ShutdownHandler;
use Flextype\Media\Media;
use Flextype\Parsers\Parsers;
use Flextype\Serializers\Serializers;
use Flextype\Tokens\Tokens;
Expand Down Expand Up @@ -57,6 +56,7 @@
use Slim\Psr7\Response;
use Slim\Psr7\Stream;
use Symfony\Component\Yaml\Yaml as SymfonyYaml;
use Flextype\Middlewares\WhoopsMiddleware;

use function app;
use function array_replace_recursive;
Expand Down Expand Up @@ -87,11 +87,11 @@
use function trim;
use function var_export;

// Init Flextype Instance
// Creates $app Application and $container Container objects
// Init Flextype Instance.
// Creates $app Application and $container Container objects.
flextype();

// Add Registry Service
// Add Registry Service.
container()->set('registry', registry());

// Init Flextype config (manifest and settings)
Expand All @@ -108,7 +108,7 @@
$f2 = file_exists($defaultFlextypeSettingsFilePath) ? filemtime($defaultFlextypeSettingsFilePath) : '';
$f3 = file_exists($customFlextypeSettingsFilePath) ? filemtime($customFlextypeSettingsFilePath) : '';

// Create Unique Cache ID
// Create Unique Cache ID.
$cacheID = md5($flextypeManifestFilePath . $defaultFlextypeSettingsFilePath . $customFlextypeSettingsFilePath . $f1 . $f2 . $f3);

if (filesystem()->file($preflightFlextypePath . '/' . $cacheID . '.php')->exists()) {
Expand Down Expand Up @@ -194,15 +194,6 @@
app()->getRouteCollector()->setCacheFile(PATH['tmp'] . '/routes/routes.php');
}

$callableResolver = app()->getCallableResolver();
$responseFactory = app()->getResponseFactory();
$serverRequestCreator = ServerRequestCreatorFactory::create();
$request = $serverRequestCreator->createServerRequestFromGlobals();

$errorHandler = new HttpErrorHandler($callableResolver, $responseFactory);
$shutdownHandler = new ShutdownHandler($request, $errorHandler, registry()->get('flextype.settings.errors.display'));
register_shutdown_function($shutdownHandler);

// Add Session Service
container()->set('session', new Session());

Expand All @@ -216,8 +207,8 @@
container()->set('slugify', new Slugify([
'separator' => registry()->get('flextype.settings.slugify.separator'),
'lowercase' => registry()->get('flextype.settings.slugify.lowercase'),
'trim' => registry()->get('flextype.settings.slugify.trim'),
'regexp' => registry()->get('flextype.settings.slugify.regexp'),
'trim' => registry()->get('flextype.settings.slugify.trim'),
'regexp' => registry()->get('flextype.settings.slugify.regexp'),
'lowercase_after_regexp' => registry()->get('flextype.settings.slugify.lowercase_after_regexp'),
'strip_tags' => registry()->get('flextype.settings.slugify.strip_tags'),
]));
Expand Down Expand Up @@ -395,8 +386,8 @@ function getDriverConfig(string $driverName): array
// Setup Glide server
$server = ServerFactory::create([
'source' => $source,
'cache' => $cache,
'api' => $api,
'cache' => $cache,
'api' => $api,
]);

// Set presets
Expand Down Expand Up @@ -482,11 +473,16 @@ function_exists('mb_internal_encoding') and mb_internal_encoding(registry()->get
// Add Routing Middleware
app()->addRoutingMiddleware();

// Add Error Handling Middleware
app()->addErrorMiddleware(registry()->get('flextype.settings.errors.display'), false, false)->setDefaultErrorHandler($errorHandler);

// Run high priority event: onFlextypeBeforeRun before Flextype Application starts.
emitter()->emit('onFlextypeBeforeRun');

// Add Whoops Error Handling Middleware
app()->add(new WhoopsMiddleware([
'enable' => registry()->get('flextype.settings.errors.display'),
'editor' => registry()->get('flextype.settings.errors.editor'),
'title' => registry()->get('flextype.settings.errors.page_title'),
'handler' => registry()->get('flextype.settings.errors.handler'),
]));

// Run Flextype Application
app()->run();
24 changes: 9 additions & 15 deletions src/flextype/settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ errors:
# Set true to display errors.
display: true

# Editor (emacs, idea, macvim, phpstorm, sublime, textmate, xdebug, vscode, atom, espresso)
editor: atom

# Error page title
page_title: Error!

# Handler (pretty, plain, json, xml)
handler: pretty

# Entries
entries:
directory: '/entries'
Expand Down Expand Up @@ -379,22 +388,8 @@ cache:
zenddisk: {}
zendshm: {}

# Whoops
#
# Error handler framework for PHP.
#
# - editor: emacs, idea, macvim, phpstorm, sublime, textmate, xdebug, vscode, atom, espresso
#
# - page_title: page title
whoops:
editor: atom
page_title: Error!

# Slim
#
# - display_error_details: When true, additional information about exceptions are
# displayed by the default error handler.
#
# - add_content_length_header: When true, Slim will add a Content-Length header to
# the response. If you are using a runtime analytics tool,
# such as New Relic, then this should be disabled.
Expand All @@ -413,7 +408,6 @@ whoops:
# If 'append' or 'prepend', then any echo or print statements
# are captured and are either appended or prepended to the Response
# returned from the route callable.
display_error_details: true
add_content_length_header: true
router_cache_file: false
determine_route_before_app_middleware: false
Expand Down

0 comments on commit 578ddbe

Please sign in to comment.