Make controllers return Response objects

This commit is contained in:
Giuseppe Criscione 2021-01-05 15:40:11 +01:00
parent 5b17bfd4f0
commit beb2c9a074
15 changed files with 140 additions and 134 deletions

View File

@ -9,6 +9,7 @@ use Formwork\Assets;
use Formwork\Formwork;
use Formwork\Page;
use Formwork\Response\JSONResponse;
use Formwork\Response\Response;
use Formwork\Router\RouteParams;
use Formwork\Router\Router;
use Formwork\Translations\Translation;
@ -97,7 +98,7 @@ final class Admin
/**
* Run the administration panel
*/
public function run(): void
public function run(): Response
{
$this->loadSchemes();
@ -122,11 +123,13 @@ final class Admin
$this->redirect('/login/');
}
$this->router->dispatch();
$response = $this->router->dispatch();
if (!$this->router->hasDispatched()) {
$this->errors->notFound();
$response = $this->errors->notFound();
}
return $response;
}
/**

View File

@ -91,7 +91,7 @@ abstract class AbstractController extends BaseAbstractController
{
if (!$this->user()->permissions()->has($permission)) {
$errors = new ErrorsController();
$errors->forbidden();
$errors->forbidden()->send();
exit;
}
}

View File

@ -5,6 +5,7 @@ namespace Formwork\Admin\Controllers;
use Formwork\Admin\Security\AccessLimiter;
use Formwork\Admin\Security\CSRFToken;
use Formwork\Formwork;
use Formwork\Response\Response;
use Formwork\Utils\HTTPRequest;
use Formwork\Utils\Log;
use Formwork\Utils\Registry;
@ -15,7 +16,7 @@ class AuthenticationController extends AbstractController
/**
* Authentication@login action
*/
public function login(): void
public function login(): Response
{
$attemptsRegistry = new Registry(Formwork::instance()->config()->get('admin.paths.logs') . 'accessAttempts.json');
@ -27,8 +28,7 @@ class AuthenticationController extends AbstractController
if ($limiter->hasReachedLimit()) {
$minutes = round(Formwork::instance()->config()->get('admin.login_reset_time') / 60);
$this->error($this->admin()->translate('admin.login.attempt.too-many', $minutes));
return;
return $this->error($this->admin()->translate('admin.login.attempt.too-many', $minutes));
}
switch (HTTPRequest::method()) {
@ -40,9 +40,9 @@ class AuthenticationController extends AbstractController
// Always generate a new CSRF token
CSRFToken::generate();
$this->view('authentication.login', [
return new Response($this->view('authentication.login', [
'title' => $this->admin()->translate('admin.login.login')
]);
], true));
break;
@ -84,7 +84,7 @@ class AuthenticationController extends AbstractController
$this->admin()->redirectToPanel();
}
$this->error($this->admin()->translate('admin.login.attempt.failed'), [
return $this->error($this->admin()->translate('admin.login.attempt.failed'), [
'username' => $data->get('username'),
'error' => true
]);
@ -116,13 +116,13 @@ class AuthenticationController extends AbstractController
* @param string $message Error message
* @param array $data Data to pass to the view
*/
protected function error(string $message, array $data = []): void
protected function error(string $message, array $data = []): Response
{
// Ensure CSRF token is re-generated
CSRFToken::generate();
$defaults = ['title' => $this->admin()->translate('admin.login.login')];
$this->admin()->notify($message, 'error');
$this->view('authentication.login', array_merge($defaults, $data));
return new Response($this->view('authentication.login', array_merge($defaults, $data), true));
}
}

View File

@ -16,36 +16,34 @@ class BackupController extends AbstractController
/**
* Backup@make action
*/
public function make(): void
public function make(): JSONResponse
{
$this->ensurePermission('backup.make');
$backupper = new Backupper();
try {
$file = $backupper->backup();
} catch (TranslatedException $e) {
JSONResponse::error($this->admin()->translate('admin.backup.error.cannot-make', $e->getTranslatedMessage()), 500)->send();
return JSONResponse::error($this->admin()->translate('admin.backup.error.cannot-make', $e->getTranslatedMessage()), 500);
}
$filename = basename($file);
JSONResponse::success($this->admin()->translate('admin.backup.ready'), 200, [
return JSONResponse::success($this->admin()->translate('admin.backup.ready'), 200, [
'filename' => $filename,
'uri' => $this->admin()->uri('/backup/download/' . urlencode(base64_encode($filename)) . '/')
])->send();
]);
}
/**
* Backup@download action
*/
public function download(RouteParams $params): void
public function download(RouteParams $params): FileResponse
{
$this->ensurePermission('backup.download');
$file = Formwork::instance()->config()->get('backup.path') . base64_decode($params->get('backup'));
try {
if (FileSystem::isFile($file, false)) {
$response = new FileResponse($file, true);
$response->send();
} else {
throw new RuntimeException($this->admin()->translate('admin.backup.error.cannot-download.invalid-filename'));
return new FileResponse($file, true);
}
throw new RuntimeException($this->admin()->translate('admin.backup.error.cannot-download.invalid-filename'));
} catch (TranslatedException $e) {
$this->admin()->notify($this->admin()->translate('admin.backup.error.cannot-download', $e->getTranslatedMessage()), 'error');
$this->admin()->redirectToReferer(302, '/dashboard/');

View File

@ -10,12 +10,12 @@ class CacheController extends AbstractController
/**
* Cache@clear action
*/
public function clear(): void
public function clear(): JSONResponse
{
$this->ensurePermission('cache.clear');
if (Formwork::instance()->config()->get('cache.enabled')) {
Formwork::instance()->cache()->clear();
}
JSONResponse::success($this->admin()->translate('admin.cache.cleared'))->send();
return JSONResponse::success($this->admin()->translate('admin.cache.cleared'));
}
}

View File

@ -4,13 +4,14 @@ namespace Formwork\Admin\Controllers;
use Formwork\Admin\Statistics;
use Formwork\Parsers\JSON;
use Formwork\Response\Response;
class DashboardController extends AbstractController
{
/**
* Dashboard@index action
*/
public function index(): void
public function index(): Response
{
$this->ensurePermission('dashboard');
@ -23,7 +24,7 @@ class DashboardController extends AbstractController
$this->modal('deletePage');
$this->view('dashboard.index', [
return new Response($this->view('dashboard.index', [
'title' => $this->admin()->translate('admin.dashboard.dashboard'),
'lastModifiedPages' => $this->view('pages.list', [
'pages' => $this->site()->descendants()->sort('lastModifiedTime', SORT_DESC)->slice(0, 5),
@ -34,6 +35,6 @@ class DashboardController extends AbstractController
'headers' => true
], true),
'statistics' => JSON::encode($statistics->getChartData())
]);
], true));
}
}

View File

@ -3,7 +3,7 @@
namespace Formwork\Admin\Controllers;
use Formwork\Formwork;
use Formwork\Utils\Header;
use Formwork\Response\Response;
use Formwork\Utils\HTTPResponse;
use Throwable;
@ -12,9 +12,9 @@ class ErrorsController extends AbstractController
/**
* Errors@notFound action
*/
public function notFound(): void
public function notFound(): Response
{
$this->displayError(404, 'not-found', [
return $this->makeErrorResponse(404, 'not-found', [
'href' => $this->admin()->uri('/dashboard/'),
'label' => $this->admin()->translate('admin.errors.action.return-to-dashboard')
]);
@ -23,9 +23,9 @@ class ErrorsController extends AbstractController
/**
* Errors@internalServerError action
*/
public function internalServerError(Throwable $exception): void
public function internalServerError(Throwable $exception): Response
{
$this->displayError(500, 'internal-server-error', [
return $this->makeErrorResponse(500, 'internal-server-error', [
'href' => $this->makeGitHubIssueUri($exception),
'label' => $this->admin()->translate('admin.errors.action.report-to-github')
]);
@ -34,34 +34,32 @@ class ErrorsController extends AbstractController
/**
* Errors@forbidden action
*/
public function forbidden(): void
public function forbidden(): Response
{
$this->displayError(403, 'forbidden', [
return $this->makeErrorResponse(403, 'forbidden', [
'href' => $this->admin()->uri('/dashboard/'),
'label' => $this->admin()->translate('admin.errors.action.return-to-dashboard')
]);
}
/**
* Display error view with error description
* Make error response with error description
*
* @param int $status HTTP error status
* @param string $name Error name
* @param array $action Action link data
*/
protected function displayError(int $status, string $name, array $action): void
protected function makeErrorResponse(int $status, string $name, array $action): Response
{
HTTPResponse::cleanOutputBuffers();
Header::status($status);
$this->view('errors.error', [
return new Response($this->view('errors.error', [
'title' => $this->admin()->translate('admin.errors.error.' . $name . '.status'),
'code' => $status,
'status' => $this->admin()->translate('admin.errors.error.' . $name . '.status'),
'heading' => $this->admin()->translate('admin.errors.error.' . $name . '.heading'),
'description' => $this->admin()->translate('admin.errors.error.' . $name . '.description'),
'action' => $action
]);
// Don't exit, otherwise the error will not be logged
], true), $status);
}
/**

View File

@ -8,6 +8,7 @@ use Formwork\Fields\Validator;
use Formwork\Formwork;
use Formwork\Parsers\JSON;
use Formwork\Parsers\YAML;
use Formwork\Response\Response;
use Formwork\Utils\Arr;
use Formwork\Utils\FileSystem;
use Formwork\Utils\HTTPRequest;
@ -34,7 +35,7 @@ class OptionsController extends AbstractController
/**
* Options@systemOptions action
*/
public function systemOptions(): void
public function systemOptions(): Response
{
$this->ensurePermission('options.system');
@ -59,20 +60,20 @@ class OptionsController extends AbstractController
$this->modal('changes');
$this->view('options.system', [
return new Response($this->view('options.system', [
'title' => $this->admin()->translate('admin.options.options'),
'tabs' => $this->view('options.tabs', [
'tabs' => $this->tabs,
'current' => 'system'
], true),
'fields' => $fields->render(true)
]);
], true));
}
/**
* Options@siteOptions action
*/
public function siteOptions(): void
public function siteOptions(): Response
{
$this->ensurePermission('options.site');
@ -97,37 +98,37 @@ class OptionsController extends AbstractController
$this->modal('changes');
$this->view('options.site', [
return new Response($this->view('options.site', [
'title' => $this->admin()->translate('admin.options.options'),
'tabs' => $this->view('options.tabs', [
'tabs' => $this->tabs,
'current' => 'site'
], true),
'fields' => $fields->render(true)
]);
], true));
}
/**
* Options@updates action
*/
public function updates(): void
public function updates(): Response
{
$this->ensurePermission('options.updates');
$this->view('options.updates', [
return new Response($this->view('options.updates', [
'title' => $this->admin()->translate('admin.options.updates'),
'tabs' => $this->view('options.tabs', [
'tabs' => $this->tabs,
'current' => 'updates'
], true),
'currentVersion' => Formwork::VERSION
]);
], true));
}
/**
* Options@info action
*/
public function info(): void
public function info(): Response
{
$this->ensurePermission('options.info');
@ -210,14 +211,14 @@ class OptionsController extends AbstractController
ksort($data['HTTP Request Headers']);
ksort($data['HTTP Response Headers']);
$this->view('options.info', [
return new Response($this->view('options.info', [
'title' => $this->admin()->translate('admin.options.options'),
'tabs' => $this->view('options.tabs', [
'tabs' => $this->tabs,
'current' => 'info'
], true),
'info' => $data
]);
], true));
}
/**

View File

@ -12,6 +12,7 @@ use Formwork\Languages\LanguageCodes;
use Formwork\Page;
use Formwork\Parsers\YAML;
use Formwork\Response\JSONResponse;
use Formwork\Response\Response;
use Formwork\Router\RouteParams;
use Formwork\Site;
use Formwork\Utils\FileSystem;
@ -41,7 +42,7 @@ class PagesController extends AbstractController
/**
* Pages@index action
*/
public function index(): void
public function index(): Response
{
$this->ensurePermission('pages.index');
@ -52,7 +53,7 @@ class PagesController extends AbstractController
$this->modal('deletePage');
$this->view('pages.index', [
return new Response($this->view('pages.index', [
'title' => $this->admin()->translate('admin.pages.pages'),
'pagesList' => $this->view('pages.list', [
'pages' => $this->site()->pages(),
@ -62,7 +63,7 @@ class PagesController extends AbstractController
'sortable' => $this->user()->permissions()->has('pages.reorder'),
'headers' => true
], true)
]);
], true));
}
/**
@ -90,7 +91,7 @@ class PagesController extends AbstractController
/**
* Pages@edit action
*/
public function edit(RouteParams $params): void
public function edit(RouteParams $params): Response
{
$this->ensurePermission('pages.edit');
@ -182,7 +183,7 @@ class PagesController extends AbstractController
$this->modal('deleteFile');
$this->view('pages.editor', [
return new Response($this->view('pages.editor', [
'title' => $this->admin()->translate('admin.pages.edit-page', $page->title()),
'page' => $page,
'fields' => $fields->render(true),
@ -190,29 +191,29 @@ class PagesController extends AbstractController
'parents' => $this->site()->descendants()->sort('path'),
'currentLanguage' => $params->get('language', $page->language()),
'availableLanguages' => $this->availableSiteLanguages()
]);
], true));
}
/**
* Pages@reorder action
*/
public function reorder(): void
public function reorder(): JSONResponse
{
$this->ensurePermission('pages.reorder');
$data = HTTPRequest::postData();
if (!$data->hasMultiple(['parent', 'from', 'to'])) {
JSONResponse::error($this->admin()->translate('admin.pages.page.cannot-move'))->send();
return JSONResponse::error($this->admin()->translate('admin.pages.page.cannot-move'));
}
if (!is_numeric($data->get('from')) || !is_numeric($data->get('to'))) {
JSONResponse::error($this->admin()->translate('admin.pages.page.cannot-move'))->send();
return JSONResponse::error($this->admin()->translate('admin.pages.page.cannot-move'));
}
$parent = $this->resolveParent($data->get('parent'));
if ($parent === null || !$parent->hasChildren()) {
JSONResponse::error($this->admin()->translate('admin.pages.page.cannot-move'))->send();
return JSONResponse::error($this->admin()->translate('admin.pages.page.cannot-move'));
}
$pages = $parent->children()->toArray();
@ -236,7 +237,7 @@ class PagesController extends AbstractController
}
}
JSONResponse::success($this->admin()->translate('admin.pages.page.moved'))->send();
return JSONResponse::success($this->admin()->translate('admin.pages.page.moved'));
}
/**

View File

@ -6,6 +6,7 @@ use Formwork\Admin\Security\CSRFToken;
use Formwork\Admin\Security\Password;
use Formwork\Formwork;
use Formwork\Parsers\YAML;
use Formwork\Response\Response;
use Formwork\Utils\HTTPRequest;
use Formwork\Utils\Log;
use Formwork\Utils\Registry;
@ -16,15 +17,15 @@ class RegisterController extends AbstractController
/**
* Register@register action
*/
public function register(): void
public function register(): Response
{
CSRFToken::generate();
switch (HTTPRequest::method()) {
case 'GET':
$this->view('register.register', [
return new Response($this->view('register.register', [
'title' => $this->admin()->translate('admin.register.register')
]);
], true));
break;

View File

@ -14,33 +14,32 @@ class UpdatesController extends AbstractController
/**
* Updates@check action
*/
public function check(): void
public function check(): JSONResponse
{
$this->ensurePermission('updates.check');
$updater = new Updater(['preferDistAssets' => true]);
try {
$upToDate = $updater->checkUpdates();
} catch (RuntimeException $e) {
JSONResponse::error($this->admin()->translate('admin.updates.status.cannot-check'), 500, [
return JSONResponse::error($this->admin()->translate('admin.updates.status.cannot-check'), 500, [
'status' => $this->admin()->translate('admin.updates.status.cannot-check')
])->send();
]);
}
if ($upToDate) {
JSONResponse::success($this->admin()->translate('admin.updates.status.up-to-date'), 200, [
return JSONResponse::success($this->admin()->translate('admin.updates.status.up-to-date'), 200, [
'uptodate' => true
])->send();
} else {
JSONResponse::success($this->admin()->translate('admin.updates.status.found'), 200, [
'uptodate' => false,
'release' => $updater->latestRelease()
])->send();
]);
}
return JSONResponse::success($this->admin()->translate('admin.updates.status.found'), 200, [
'uptodate' => false,
'release' => $updater->latestRelease()
]);
}
/**
* Updates@update action
*/
public function update(): void
public function update(): JSONResponse
{
$this->ensurePermission('updates.update');
$updater = new Updater(['force' => true, 'preferDistAssets' => true, 'cleanupAfterInstall' => true]);
@ -49,23 +48,23 @@ class UpdatesController extends AbstractController
try {
$backupper->backup();
} catch (TranslatedException $e) {
JSONResponse::error($this->admin()->translate('admin.updates.status.cannot-make-backup'), 500, [
return JSONResponse::error($this->admin()->translate('admin.updates.status.cannot-make-backup'), 500, [
'status' => $this->admin()->translate('admin.updates.status.cannot-make-backup')
])->send();
]);
}
}
try {
$updater->update();
} catch (RuntimeException $e) {
JSONResponse::error($this->admin()->translate('admin.updates.status.cannot-install'), 500, [
return JSONResponse::error($this->admin()->translate('admin.updates.status.cannot-install'), 500, [
'status' => $this->admin()->translate('admin.updates.status.cannot-install')
])->send();
]);
}
if (Formwork::instance()->config()->get('cache.enabled')) {
Formwork::instance()->cache()->clear();
}
JSONResponse::success($this->admin()->translate('admin.updates.installed'), 200, [
return JSONResponse::success($this->admin()->translate('admin.updates.installed'), 200, [
'status' => $this->admin()->translate('admin.updates.status.up-to-date')
])->send();
]);
}
}

View File

@ -12,6 +12,7 @@ use Formwork\Fields\Fields;
use Formwork\Files\Image;
use Formwork\Formwork;
use Formwork\Parsers\YAML;
use Formwork\Response\Response;
use Formwork\Router\RouteParams;
use Formwork\Utils\FileSystem;
use Formwork\Utils\HTTPRequest;
@ -22,7 +23,7 @@ class UsersController extends AbstractController
/**
* Users@index action
*/
public function index(): void
public function index(): Response
{
$this->ensurePermission('users.index');
@ -30,10 +31,10 @@ class UsersController extends AbstractController
$this->modal('deleteUser');
$this->view('users.index', [
return new Response($this->view('users.index', [
'title' => $this->admin()->translate('admin.users.users'),
'users' => $this->admin()->users()
]);
], true));
}
/**
@ -109,7 +110,7 @@ class UsersController extends AbstractController
/**
* Users@profile action
*/
public function profile(RouteParams $params): void
public function profile(RouteParams $params): Response
{
$fields = new Fields(Formwork::instance()->schemes()->get('admin', 'user')->get('fields'));
@ -144,11 +145,11 @@ class UsersController extends AbstractController
$this->modal('deleteUser');
$this->view('users.profile', [
return new Response($this->view('users.profile', [
'title' => $this->admin()->translate('admin.users.user-profile', $user->username()),
'user' => $user,
'fields' => $fields->render(true)
]);
], true));
}
/**

View File

@ -5,6 +5,7 @@ namespace Formwork\Controllers;
use Formwork\Formwork;
use Formwork\Page;
use Formwork\Response\FileResponse;
use Formwork\Response\Response;
use Formwork\Router\RouteParams;
use Formwork\Utils\Date;
use Formwork\Utils\FileSystem;
@ -12,58 +13,77 @@ use Formwork\Utils\Header;
class PageController extends AbstractController
{
public function load(RouteParams $params)
public function load(RouteParams $params): Response
{
$config = Formwork::instance()->config();
$router = Formwork::instance()->router();
$cache = Formwork::instance()->cache();
$site = Formwork::instance()->site();
$formwork = Formwork::instance();
$route = $params->get('page', $config->get('pages.index'));
$route = $params->get('page', $formwork->config()->get('pages.index'));
if ($site->has('aliases') && $alias = $site->alias($route)) {
if ($formwork->site()->has('aliases') && $alias = $formwork->site()->alias($route)) {
$route = trim($alias, '/');
}
if ($page = $site->findPage($route)) {
if ($page = $formwork->site()->findPage($route)) {
if ($page->has('canonical')) {
$canonical = trim($page->canonical(), '/');
if ($params->get('page', '') !== $canonical) {
$route = empty($canonical) ? '' : $router->rewrite(['page' => $canonical]);
Header::redirect($site->uri($route), 301);
$route = empty($canonical) ? '' : $formwork->router()->rewrite(['page' => $canonical]);
Header::redirect($formwork->site()->uri($route), 301);
}
}
if (($params->has('tagName') || $params->has('paginationPage')) && $page->scheme()->get('type') !== 'listing') {
return $site->errorPage();
return $this->getPageResponse($formwork->site()->errorPage());
}
if ($config->get('cache.enabled') && ($page->has('publish-date') || $page->has('unpublish-date'))) {
if (($page->published() && !$site->modifiedSince(Date::toTimestamp($page->get('publish-date'))))
|| (!$page->published() && !$site->modifiedSince(Date::toTimestamp($page->get('unpublish-date'))))) {
if ($formwork->config()->get('cache.enabled') && ($page->has('publish-date') || $page->has('unpublish-date'))) {
if (($page->published() && !$formwork->site()->modifiedSince(Date::toTimestamp($page->get('publish-date'))))
|| (!$page->published() && !$formwork->site()->modifiedSince(Date::toTimestamp($page->get('unpublish-date'))))) {
// Clear cache if the site was not modified since the page has been published or unpublished
$cache->clear();
FileSystem::touch($config->get('content.path'));
$formwork->cache()->clear();
FileSystem::touch($formwork->config()->get('content.path'));
}
}
if ($page->routable() && $page->published()) {
return $page;
return $this->getPageResponse($page);
}
} else {
$filename = basename($route);
$upperLevel = dirname($route);
if ($upperLevel === '.') {
$upperLevel = $config->get('pages.index');
$upperLevel = $formwork->config()->get('pages.index');
}
if (($parent = $site->findPage($upperLevel)) && $parent->files()->has($filename)) {
$response = new FileResponse($parent->files()->get($filename)->path());
return $response->send();
if (($parent = $formwork->site()->findPage($upperLevel)) && $parent->files()->has($filename)) {
return new FileResponse($parent->files()->get($filename)->path());
}
}
return $site->errorPage();
return $this->getPageResponse($formwork->site()->errorPage());
}
protected function getPageResponse(Page $page): Response
{
$formwork = Formwork::instance();
if ($formwork->site()->currentPage() === null) {
$formwork->site()->setCurrentPage($page);
}
$page = $formwork->site()->currentPage();
if ($formwork->config()->get('cache.enabled') && $formwork->cache()->has($formwork->request())) {
return $formwork->cache()->fetch($formwork->request());
}
$response = new Response($page->renderToString(), (int) $page->get('response_status', 200), $page->headers());
if ($formwork->config()->get('cache.enabled') && $page->cacheable()) {
$formwork->cache()->save($formwork->request(), $response);
}
return $response;
}
}

View File

@ -6,6 +6,7 @@ use Formwork\Utils\Header;
use Formwork\Utils\HTTPResponse;
use Formwork\View\View;
use ErrorException;
use Formwork\Response\Response;
use Throwable;
class Errors
@ -28,9 +29,9 @@ class Errors
public static function displayErrorPage(int $status = 500): void
{
HTTPResponse::cleanOutputBuffers();
Header::status($status);
$view = new View('error', ['status' => $status, 'message' => Header::HTTP_STATUS[$status]]);
$view->render();
$response = new Response($view->render(true), $status);
$response->send();
// Don't exit, otherwise the error will not be logged
}

View File

@ -8,7 +8,6 @@ use Formwork\Cache\SiteCache;
use Formwork\Languages\Languages;
use Formwork\Parsers\PHP;
use Formwork\Parsers\YAML;
use Formwork\Response\Response;
use Formwork\Router\Router;
use Formwork\Schemes\Schemes;
use Formwork\Traits\SingletonTrait;
@ -193,28 +192,11 @@ final class Formwork
*/
public function run(): void
{
$resource = $this->router->dispatch();
$response = $this->router->dispatch();
if ($resource instanceof Page) {
if ($this->site->currentPage() === null) {
$this->site->setCurrentPage($resource);
}
$response->send();
$page = $this->site->currentPage();
if ($this->config()->get('cache.enabled') && $this->cache->has($this->request)) {
$response = $this->cache->fetch($this->request);
$response->send();
} else {
$response = new Response($page->renderToString(), $page->get('response_status', 200), $page->headers());
$response->send();
if ($this->config()->get('cache.enabled') && $page->cacheable()) {
$this->cache->save($this->request, $response);
}
}
}
if ($this->config()->get('statistics.enabled') && isset($page) && !$page->isErrorPage()) {
if ($this->config()->get('statistics.enabled') && $this->site->currentPage() !== null && !$this->site->currentPage()->isErrorPage()) {
$statistics = new Statistics();
$statistics->trackVisit();
}
@ -327,7 +309,7 @@ final class Formwork
],
function () {
$this->admin = new Admin();
$this->admin->run();
return $this->admin->run();
},
['GET', 'POST'],
['HTTP', 'XHR']