Merge pull request #594 from getformwork/refactor/refactor-controllers

Remove useless controller methods and move redirection to parent
This commit is contained in:
Giuseppe Criscione 2024-10-25 23:24:00 +02:00 committed by GitHub
commit ff6f5c5c57
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 285 additions and 233 deletions

View File

@ -4,10 +4,14 @@ namespace Formwork\Controllers;
use Formwork\App;
use Formwork\Config\Config;
use Formwork\Http\RedirectResponse;
use Formwork\Http\Request;
use Formwork\Http\Response;
use Formwork\Http\ResponseStatus;
use Formwork\Services\Container;
use Formwork\Utils\Path;
use Formwork\Utils\Str;
use Formwork\Utils\Uri;
use Formwork\View\ViewFactory;
use InvalidArgumentException;
@ -16,14 +20,14 @@ abstract class AbstractController
/**
* Controller name
*/
protected string $name;
protected readonly string $name;
public function __construct(
private readonly Container $container,
protected App $app,
protected Config $config,
protected ViewFactory $viewFactory,
protected Request $request,
protected readonly App $app,
protected readonly Config $config,
protected readonly ViewFactory $viewFactory,
protected readonly Request $request,
) {
$this->name = strtolower(Str::beforeLast(Str::afterLast(static::class, '\\'), 'Controller'));
}
@ -38,6 +42,35 @@ abstract class AbstractController
return $this->viewFactory->make($name, $data)->render();
}
/**
* @param array<string, string> $headers
*/
protected function redirect(string $route, ResponseStatus $responseStatus = ResponseStatus::Found, array $headers = []): RedirectResponse
{
$uri = Uri::make([], Path::join([$this->app->request()->root(), $route]));
return new RedirectResponse($uri, $responseStatus, $headers);
}
/**
* Redirect to the referer page
*
* @param array<string, string> $headers
*/
protected function redirectToReferer(
ResponseStatus $responseStatus = ResponseStatus::Found,
array $headers = [],
string $default = '/',
string $base = '/'
): RedirectResponse {
if (
!in_array($this->request->referer(), [null, Uri::current()], true)
&& $this->request->validateReferer(Path::join([$this->app->request()->root(), $base]))
) {
return new RedirectResponse($this->request->referer(), $responseStatus, $headers);
}
return $this->redirect($default, $responseStatus, $headers);
}
/**
* Forward the request to another controller
*

View File

@ -4,7 +4,6 @@ namespace Formwork\Controllers;
use Formwork\Cache\FilesCache;
use Formwork\Http\FileResponse;
use Formwork\Http\RedirectResponse;
use Formwork\Http\Response;
use Formwork\Http\ResponseStatus;
use Formwork\Pages\Page;
@ -19,9 +18,9 @@ class PageController extends AbstractController
{
public function __construct(
private readonly Container $container,
protected Router $router,
protected Site $site,
protected FilesCache $filesCache
protected readonly Router $router,
protected readonly Site $site,
protected readonly FilesCache $filesCache
) {
$this->container->call(parent::__construct(...));
}
@ -51,7 +50,7 @@ class PageController extends AbstractController
if ($routeParams->get('page', '/') !== $canonical) {
$route = $this->router->rewrite(['page' => $canonical]);
return new RedirectResponse($this->site->uri($route), ResponseStatus::MovedPermanently);
return $this->redirect($route, ResponseStatus::MovedPermanently);
}
}

View File

@ -3,8 +3,6 @@
namespace Formwork\Panel\Controllers;
use Formwork\Controllers\AbstractController as BaseAbstractController;
use Formwork\Http\RedirectResponse;
use Formwork\Http\ResponseStatus;
use Formwork\Panel\Modals\Modal;
use Formwork\Panel\Modals\ModalCollection;
use Formwork\Panel\Modals\ModalFactory;
@ -15,9 +13,7 @@ use Formwork\Security\CsrfToken;
use Formwork\Services\Container;
use Formwork\Site;
use Formwork\Translations\Translations;
use Formwork\Users\User;
use Formwork\Utils\Date;
use Formwork\Utils\Uri;
use Stringable;
abstract class AbstractController extends BaseAbstractController
@ -26,30 +22,16 @@ abstract class AbstractController extends BaseAbstractController
public function __construct(
private readonly Container $container,
protected Router $router,
protected CsrfToken $csrfToken,
protected Translations $translations,
protected ModalFactory $modalFactory,
protected Site $site,
protected Panel $panel
protected readonly Router $router,
protected readonly CsrfToken $csrfToken,
protected readonly Translations $translations,
protected readonly ModalFactory $modalFactory,
protected readonly Site $site,
protected readonly Panel $panel
) {
$this->container->call(parent::__construct(...));
}
/**
* Return panel instance
*/
protected function panel(): Panel
{
return $this->panel;
}
/**
* Return site instance
*/
protected function site(): Site
{
return $this->site;
$this->modals = new ModalCollection();
}
/**
@ -60,29 +42,43 @@ abstract class AbstractController extends BaseAbstractController
return $this->router->generate($name, $params);
}
protected function redirect(string $route, ResponseStatus $responseStatus = ResponseStatus::Found): RedirectResponse
{
return new RedirectResponse($this->site->uri($route, includeLanguage: false), $responseStatus);
}
/**
* Redirect to the referer page
*
* @param string $default Default route if HTTP referer is not available
*/
protected function redirectToReferer(ResponseStatus $responseStatus = ResponseStatus::Found, string $default = '/'): RedirectResponse
{
if (!in_array($this->request->referer(), [null, Uri::current()], true) && $this->request->validateReferer($this->panel()->uri('/'))) {
return new RedirectResponse($this->request->referer(), $responseStatus);
}
return new RedirectResponse($this->panel()->uri($default), $responseStatus);
}
protected function translate(string $key, int|float|string|Stringable ...$arguments): string
{
return $this->translations->getCurrent()->translate($key, ...$arguments);
}
/**
* Get if current user has a permission
*/
protected function hasPermission(string $permission): bool
{
return $this->panel->user()->permissions()->has($permission);
}
/**
* Load a modal to be rendered later
*/
protected function modal(string $name): Modal
{
$this->modals->add($modal = $this->modalFactory->make($name));
return $modal;
}
/**
* Render a view
*
* @param array<string, mixed> $data
*/
protected function view(string $name, array $data = []): string
{
$view = $this->viewFactory->make(
$name,
[...$this->defaults(), ...$data],
$this->config->get('system.views.paths.panel'),
);
return $view->render();
}
/**
* Return default data passed to views
*
@ -92,10 +88,10 @@ abstract class AbstractController extends BaseAbstractController
{
return [
'location' => $this->name,
'site' => $this->site(),
'panel' => $this->panel(),
'csrfToken' => $this->csrfToken->get($this->panel()->getCsrfTokenName()),
'modals' => $this->modals(),
'site' => $this->site,
'panel' => $this->panel,
'csrfToken' => $this->csrfToken->get($this->panel->getCsrfTokenName()),
'modals' => $this->modals,
'navigation' => [
'dashboard' => [
'label' => $this->translate('panel.dashboard.dashboard'),
@ -141,7 +137,7 @@ abstract class AbstractController extends BaseAbstractController
],
],
'appConfig' => Json::encode([
'baseUri' => $this->panel()->panelUri(),
'baseUri' => $this->panel->panelUri(),
'DateInput' => [
'weekStarts' => $this->config->get('system.date.weekStarts'),
'format' => Date::formatToPattern($this->config->get('system.date.datetimeFormat')),
@ -199,49 +195,4 @@ abstract class AbstractController extends BaseAbstractController
]),
];
}
/**
* Get logged user
*/
protected function user(): User
{
return $this->panel()->user();
}
/**
* Get if current user has a permission
*/
protected function hasPermission(string $permission): bool
{
return $this->user()->permissions()->has($permission);
}
protected function modals(): ModalCollection
{
return $this->modals ??= new ModalCollection();
}
/**
* Load a modal to be rendered later
*/
protected function modal(string $name): Modal
{
$this->modals()->add($modal = $this->modalFactory->make($name));
return $modal;
}
/**
* Render a view
*
* @param array<string, mixed> $data
*/
protected function view(string $name, array $data = []): string
{
$view = $this->viewFactory->make(
$name,
[...$this->defaults(), ...$data],
$this->config->get('system.views.paths.panel'),
);
return $view->render();
}
}

View File

@ -22,11 +22,11 @@ class AuthenticationController extends AbstractController
*/
public function login(AccessLimiter $accessLimiter): Response
{
if ($this->panel()->isLoggedIn()) {
if ($this->panel->isLoggedIn()) {
return $this->redirect($this->generateRoute('panel.index'));
}
$csrfTokenName = $this->panel()->getCsrfTokenName();
$csrfTokenName = $this->panel->getCsrfTokenName();
if ($accessLimiter->hasReachedLimit()) {
$minutes = round($this->config->get('system.panel.loginResetTime') / 60);
@ -103,13 +103,13 @@ class AuthenticationController extends AbstractController
{
try {
$this->panel->user()->logout();
$this->csrfToken->destroy($this->panel()->getCsrfTokenName());
$this->csrfToken->destroy($this->panel->getCsrfTokenName());
if ($this->config->get('system.panel.logoutRedirect') === 'home') {
return $this->redirect('/');
}
$this->panel()->notify($this->translate('panel.login.loggedOut'), 'info');
$this->panel->notify($this->translate('panel.login.loggedOut'), 'info');
} catch (UserNotLoggedException) {
// Do nothing if user is not logged, the user will be redirected to the login page
}
@ -125,7 +125,7 @@ class AuthenticationController extends AbstractController
protected function error(string $message, array $data = []): Response
{
$defaults = ['title' => $this->translate('panel.login.login')];
$this->panel()->notify($message, 'error');
$this->panel->notify($message, 'error');
return new Response($this->view('authentication.login', [...$defaults, ...$data]));
}
}

View File

@ -34,10 +34,10 @@ class BackupController extends AbstractController
$uriName = urlencode(base64_encode($filename));
return JsonResponse::success($this->translate('panel.backup.ready'), data: [
'filename' => $filename,
'uri' => $this->panel()->uri('/backup/download/' . $uriName . '/'),
'uri' => $this->panel->uri('/backup/download/' . $uriName . '/'),
'date' => Date::formatTimestamp(FileSystem::lastModifiedTime($file), $this->config->get('system.date.datetimeFormat')),
'size' => FileSystem::formatSize(FileSystem::size($file)),
'deleteUri' => $this->panel()->uri('/backup/delete/' . $uriName . '/'),
'deleteUri' => $this->panel->uri('/backup/delete/' . $uriName . '/'),
'maxFiles' => $this->config->get('system.backup.maxFiles'),
]);
}
@ -58,8 +58,11 @@ class BackupController extends AbstractController
}
throw new RuntimeException($this->translate('panel.backup.error.cannotDownload.invalidFilename'));
} catch (TranslatedException $e) {
$this->panel()->notify($this->translate('panel.backup.error.cannotDownload', $e->getTranslatedMessage()), 'error');
return $this->redirectToReferer(default: '/dashboard/');
$this->panel->notify($this->translate('panel.backup.error.cannotDownload', $e->getTranslatedMessage()), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.tools.backups'),
base: $this->panel->panelRoot()
);
}
}
@ -76,13 +79,19 @@ class BackupController extends AbstractController
try {
if (FileSystem::isFile($file, assertExists: false)) {
FileSystem::delete($file);
$this->panel()->notify($this->translate('panel.backup.deleted'), 'success');
return $this->redirectToReferer(default: '/dashboard/');
$this->panel->notify($this->translate('panel.backup.deleted'), 'success');
return $this->redirectToReferer(
default: $this->generateRoute('panel.tools.backups'),
base: $this->generateRoute('panel.index'),
);
}
throw new RuntimeException($this->translate('panel.backup.error.cannotDelete.invalidFilename'));
} catch (TranslatedException $e) {
$this->panel()->notify($this->translate('panel.backup.error.cannotDelete', $e->getTranslatedMessage()), 'error');
return $this->redirectToReferer(default: '/dashboard/');
$this->panel->notify($this->translate('panel.backup.error.cannotDelete', $e->getTranslatedMessage()), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.tools.backups'),
base: $this->panel->panelRoot()
);
}
}
}

View File

@ -24,7 +24,7 @@ class DashboardController extends AbstractController
return new Response($this->view('dashboard.index', [
'title' => $this->translate('panel.dashboard.dashboard'),
'lastModifiedPages' => $this->view('pages.tree', [
'pages' => $this->site()->descendants()->sortBy('lastModifiedTime', direction: SORT_DESC)->limit(5),
'pages' => $this->site->descendants()->sortBy('lastModifiedTime', direction: SORT_DESC)->limit(5),
'includeChildren' => false,
'class' => 'pages-tree-root',
'parent' => null,

View File

@ -24,7 +24,7 @@ class ErrorsController extends AbstractController implements ErrorsControllerInt
public function notFound(): Response
{
return $this->makeErrorResponse(ResponseStatus::NotFound, 'notFound', [
'href' => $this->panel()->uri('/dashboard/'),
'href' => $this->panel->uri('/dashboard/'),
'label' => $this->translate('panel.errors.action.returnToDashboard'),
]);
}
@ -46,7 +46,7 @@ class ErrorsController extends AbstractController implements ErrorsControllerInt
public function forbidden(): Response
{
return $this->makeErrorResponse(ResponseStatus::Forbidden, 'forbidden', [
'href' => $this->panel()->uri('/dashboard/'),
'href' => $this->panel->uri('/dashboard/'),
'label' => $this->translate('panel.errors.action.returnToDashboard'),
]);
}

View File

@ -54,13 +54,13 @@ class OptionsController extends AbstractController
// Touch content folder to invalidate cache
if ($differ) {
if ($this->site()->contentPath() === null) {
if ($this->site->contentPath() === null) {
throw new UnexpectedValueException('Unexpected missing site path');
}
FileSystem::touch($this->site()->contentPath());
FileSystem::touch($this->site->contentPath());
}
$this->panel()->notify($this->translate('panel.options.updated'), 'success');
$this->panel->notify($this->translate('panel.options.updated'), 'success');
return $this->redirect($this->generateRoute('panel.options.system'));
}
@ -92,24 +92,24 @@ class OptionsController extends AbstractController
if ($this->request->method() === RequestMethod::POST) {
$data = $this->request->input();
$options = $this->site()->data();
$defaults = $this->site()->defaults();
$options = $this->site->data();
$defaults = $this->site->defaults();
$fields->setValues($data, null)->validate();
$differ = $this->updateOptions('site', $fields, $options, $defaults);
// Touch content folder to invalidate cache
if ($differ) {
if ($this->site()->contentPath() === null) {
if ($this->site->contentPath() === null) {
throw new UnexpectedValueException('Unexpected missing site path');
}
FileSystem::touch($this->site()->contentPath());
FileSystem::touch($this->site->contentPath());
}
$this->panel()->notify($this->translate('panel.options.updated'), 'success');
$this->panel->notify($this->translate('panel.options.updated'), 'success');
return $this->redirect($this->generateRoute('panel.options.site'));
}
$fields->setValues($this->site()->data());
$fields->setValues($this->site->data());
$this->modal('changes');

View File

@ -55,9 +55,9 @@ class PagesController extends AbstractController
$this->modal('deletePage');
$pages = $this->site()->pages();
$pages = $this->site->pages();
$indexOffset = $pages->indexOf($this->site()->indexPage());
$indexOffset = $pages->indexOf($this->site->indexPage());
if ($indexOffset !== null) {
$pages->moveItem($indexOffset, 0);
@ -70,7 +70,7 @@ class PagesController extends AbstractController
'includeChildren' => true,
'class' => 'pages-tree-root',
'parent' => '.',
'orderable' => $this->user()->permissions()->has('pages.reorder'),
'orderable' => $this->panel->user()->permissions()->has('pages.reorder'),
'headers' => true,
]),
]));
@ -92,17 +92,23 @@ class PagesController extends AbstractController
try {
$fields->setValues($requestData)->validate();
} catch (ValidationException) {
$this->panel()->notify($this->translate('panel.pages.page.cannotCreate.varMissing'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotCreate.varMissing'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
// Let's create the page
try {
$page = $this->createPage($fields);
$this->panel()->notify($this->translate('panel.pages.page.created'), 'success');
$this->panel->notify($this->translate('panel.pages.page.created'), 'success');
} catch (TranslatedException $e) {
$this->panel()->notify($e->getTranslatedMessage(), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($e->getTranslatedMessage(), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if ($page->route() === null) {
@ -121,11 +127,14 @@ class PagesController extends AbstractController
return $this->forward(ErrorsController::class, 'forbidden');
}
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotEdit.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotEdit.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if ($routeParams->has('language')) {
@ -139,11 +148,11 @@ class PagesController extends AbstractController
$language = $routeParams->get('language');
if (!in_array($language, $this->config->get('system.languages.available'), true)) {
$this->panel()->notify($this->translate('panel.pages.page.cannotEdit.invalidLanguage', $language), 'error');
$this->panel->notify($this->translate('panel.pages.page.cannotEdit.invalidLanguage', $language), 'error');
if ($page->route() === null) {
throw new UnexpectedValueException('Unexpected missing page route');
}
return $this->redirect($this->generateRoute('panel.pages.edit.lang', ['page' => trim($page->route(), '/'), 'language' => $this->site()->languages()->default()]));
return $this->redirect($this->generateRoute('panel.pages.edit.lang', ['page' => trim($page->route(), '/'), 'language' => $this->site->languages()->default()]));
}
if ($page->languages()->available()->has($language)) {
@ -188,9 +197,9 @@ class PagesController extends AbstractController
// Update the page
$page = $this->updatePage($page, $data, $fields, force: $forceUpdate);
$this->panel()->notify($this->translate('panel.pages.page.edited'), 'success');
$this->panel->notify($this->translate('panel.pages.page.edited'), 'success');
} catch (TranslatedException $e) {
$this->panel()->notify($e->getTranslatedMessage(), 'error');
$this->panel->notify($e->getTranslatedMessage(), 'error');
}
if ($page->route() === null) {
@ -237,14 +246,17 @@ class PagesController extends AbstractController
*/
public function preview(RouteParams $routeParams): Response
{
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotPreview.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotPreview.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
$this->site()->setCurrentPage($page);
$this->site->setCurrentPage($page);
// Load data from POST variables
$requestData = $this->request->input();
@ -253,12 +265,15 @@ class PagesController extends AbstractController
$page->fields()->setValues($requestData)->validate();
if ($page->template()->name() !== ($template = $requestData->get('template'))) {
$page->reload(['template' => $this->site()->templates()->get($template)]);
$page->reload(['template' => $this->site->templates()->get($template)]);
}
if ($page->parent() !== ($parent = $this->resolveParent($requestData->get('parent')))) {
$this->panel()->notify($this->translate('panel.pages.page.cannotPreview.parentChanged'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotPreview.parentChanged'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
return new Response($page->render(), $page->responseStatus(), $page->headers());
@ -318,11 +333,14 @@ class PagesController extends AbstractController
return $this->forward(ErrorsController::class, 'forbidden');
}
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotDelete.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotDelete.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if ($routeParams->has('language')) {
@ -330,14 +348,20 @@ class PagesController extends AbstractController
if ($page->languages()->available()->has($language)) {
$page->setLanguage($language);
} else {
$this->panel()->notify($this->translate('panel.pages.page.cannotDelete.invalidLanguage', $language), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotDelete.invalidLanguage', $language), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
}
if (!$page->isDeletable()) {
$this->panel()->notify($this->translate('panel.pages.page.cannotDelete.notDeletable'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotDelete.notDeletable'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if ($page->contentPath() !== null) {
@ -349,11 +373,14 @@ class PagesController extends AbstractController
}
}
$this->panel()->notify($this->translate('panel.pages.page.deleted'), 'success');
$this->panel->notify($this->translate('panel.pages.page.deleted'), 'success');
// Try to redirect to referer unless it's to Pages@edit
if ($this->request->referer() !== null && !Str::startsWith(Uri::normalize($this->request->referer()), Uri::make(['path' => $this->panel()->uri('/pages/' . $routeParams->get('page') . '/edit/')]))) {
return $this->redirectToReferer(default: '/pages/');
if ($this->request->referer() !== null && !Str::startsWith(Uri::normalize($this->request->referer()), Uri::make(['path' => $this->panel->uri('/pages/' . $routeParams->get('page') . '/edit/')]))) {
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
return $this->redirect($this->generateRoute('panel.pages'));
}
@ -367,23 +394,26 @@ class PagesController extends AbstractController
return $this->forward(ErrorsController::class, 'forbidden');
}
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotUploadFile.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotUploadFile.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if (!$this->request->files()->isEmpty()) {
try {
$this->processPageUploads($this->request->files()->getAll(), $page);
} catch (TranslatedException $e) {
$this->panel()->notify($this->translate('upload.error', $e->getTranslatedMessage()), 'error');
$this->panel->notify($this->translate('upload.error', $e->getTranslatedMessage()), 'error');
return $this->redirect($this->generateRoute('panel.pages.edit', ['page' => $routeParams->get('page')]));
}
}
$this->panel()->notify($this->translate('panel.uploader.uploaded'), 'success');
$this->panel->notify($this->translate('panel.uploader.uploaded'), 'success');
return $this->redirect($this->generateRoute('panel.pages.edit', ['page' => $routeParams->get('page')]));
}
@ -396,21 +426,24 @@ class PagesController extends AbstractController
return $this->forward(ErrorsController::class, 'forbidden');
}
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotDeleteFile.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotDeleteFile.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if (!$page->files()->has($routeParams->get('filename'))) {
$this->panel()->notify($this->translate('panel.pages.page.cannotDeleteFile.fileNotFound'), 'error');
$this->panel->notify($this->translate('panel.pages.page.cannotDeleteFile.fileNotFound'), 'error');
return $this->redirect($this->generateRoute('panel.pages.edit', ['page' => $routeParams->get('page')]));
}
FileSystem::delete($page->contentPath() . $routeParams->get('filename'));
$this->panel()->notify($this->translate('panel.pages.page.fileDeleted'), 'success');
$this->panel->notify($this->translate('panel.pages.page.fileDeleted'), 'success');
return $this->redirect($this->generateRoute('panel.pages.edit', ['page' => $routeParams->get('page')]));
}
@ -423,15 +456,18 @@ class PagesController extends AbstractController
return $this->forward(ErrorsController::class, 'forbidden');
}
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotRenameFile.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotRenameFile.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if (!$page->files()->has($routeParams->get('filename'))) {
$this->panel()->notify($this->translate('panel.pages.page.cannotRenameFile.fileNotFound'), 'error');
$this->panel->notify($this->translate('panel.pages.page.cannotRenameFile.fileNotFound'), 'error');
return $this->redirect($this->generateRoute('panel.pages.edit', ['page' => $routeParams->get('page')]));
}
@ -444,16 +480,16 @@ class PagesController extends AbstractController
if ($newName !== $previousName) {
if ($page->files()->has($newName)) {
$this->panel()->notify($this->translate('panel.pages.page.cannotRenameFile.fileAlreadyExists'), 'error');
$this->panel->notify($this->translate('panel.pages.page.cannotRenameFile.fileAlreadyExists'), 'error');
} else {
FileSystem::move($page->contentPath() . $previousName, $page->contentPath() . $newName);
$this->panel()->notify($this->translate('panel.pages.page.fileRenamed'), 'success');
$this->panel->notify($this->translate('panel.pages.page.fileRenamed'), 'success');
}
}
$previousFileRoute = $this->generateRoute('panel.pages.file', ['page' => $routeParams->get('page'), 'filename' => $previousName]);
if (Str::removeEnd((string) Uri::path($this->request->referer()), '/') === $this->site()->uri($previousFileRoute)) {
if (Str::removeEnd((string) Uri::path($this->request->referer()), '/') === $this->site->uri($previousFileRoute)) {
return $this->redirect($this->generateRoute('panel.pages.file', ['page' => $routeParams->get('page'), 'filename' => $newName]));
}
@ -469,38 +505,50 @@ class PagesController extends AbstractController
return $this->forward(ErrorsController::class, 'forbidden');
}
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
$filename = $routeParams->get('filename');
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotReplaceFile.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotReplaceFile.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if (!$page->files()->has($filename)) {
$this->panel()->notify($this->translate('panel.pages.page.cannotReplaceFile.fileNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotReplaceFile.fileNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if (!$this->request->files()->isEmpty()) {
$files = $this->request->files()->getAll();
if (count($files) > 1) {
$this->panel()->notify($this->translate('panel.pages.page.cannotReplaceFile.multipleFiles'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotReplaceFile.multipleFiles'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
try {
$this->processPageUploads($this->request->files()->getAll(), $page, [$page->files()->get($filename)->mimeType()], FileSystem::name($filename), true);
} catch (TranslatedException $e) {
$this->panel()->notify($this->translate('upload.error', $e->getTranslatedMessage()), 'error');
$this->panel->notify($this->translate('upload.error', $e->getTranslatedMessage()), 'error');
return $this->redirect($this->generateRoute('panel.pages.edit', ['page' => $routeParams->get('page')]));
}
}
$this->panel()->notify($this->translate('panel.uploader.uploaded'), 'success');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.uploader.uploaded'), 'success');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
/**
@ -512,17 +560,20 @@ class PagesController extends AbstractController
return $this->forward(ErrorsController::class, 'forbidden');
}
$page = $this->site()->findPage($routeParams->get('page'));
$page = $this->site->findPage($routeParams->get('page'));
$filename = $routeParams->get('filename');
if ($page === null) {
$this->panel()->notify($this->translate('panel.pages.page.cannotGetFileInfo.pageNotFound'), 'error');
return $this->redirectToReferer(default: '/pages/');
$this->panel->notify($this->translate('panel.pages.page.cannotGetFileInfo.pageNotFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.pages'),
base: $this->panel->panelRoot()
);
}
if (!$page->files()->has($filename)) {
$this->panel()->notify($this->translate('panel.pages.page.cannotGetFileInfo.fileNotFound'), 'error');
$this->panel->notify($this->translate('panel.pages.page.cannotGetFileInfo.fileNotFound'), 'error');
return $this->redirect($this->generateRoute('panel.pages.edit', ['page' => $routeParams->get('page')]));
}
@ -545,7 +596,7 @@ class PagesController extends AbstractController
$this->updateFileMetadata($file, $file->fields());
$this->panel()->notify($this->translate('panel.files.metadata.updated'), 'success');
$this->panel->notify($this->translate('panel.files.metadata.updated'), 'success');
return $this->redirect($this->generateRoute('panel.pages.file', ['page' => $page->route(), 'filename' => $filename]));
}
@ -585,12 +636,12 @@ class PagesController extends AbstractController
$route = $parent->route() . $fieldCollection->get('slug')->value() . '/';
// Ensure there isn't a page with the same route
if ($this->site()->findPage($route) !== null) {
if ($this->site->findPage($route) !== null) {
throw new TranslatedException('A page with the same route already exists', 'panel.pages.page.cannotCreate.alreadyExists');
}
// Validate page template
if (!$this->site()->templates()->has($fieldCollection->get('template'))) {
if (!$this->site->templates()->has($fieldCollection->get('template'))) {
throw new TranslatedException('Invalid page template', 'panel.pages.page.cannotCreate.invalidTemplate');
}
@ -604,7 +655,7 @@ class PagesController extends AbstractController
FileSystem::createDirectory($path, recursive: true);
$language = $this->site()->languages()->default();
$language = $this->site->languages()->default();
$filename = $fieldCollection->get('template')->value();
$filename .= $language !== null ? '.' . $language : '';
@ -623,10 +674,10 @@ class PagesController extends AbstractController
$contentHistory = new ContentHistory($path);
$contentHistory->update(ContentHistoryEvent::Created, $this->user()->username(), time());
$contentHistory->update(ContentHistoryEvent::Created, $this->panel->user()->username(), time());
$contentHistory->save();
return $this->site()->retrievePage($path);
return $this->site->retrievePage($path);
}
protected function updateFileMetadata(File $file, FieldCollection $fieldCollection): void
@ -724,16 +775,16 @@ class PagesController extends AbstractController
throw new UnexpectedValueException('Unexpected missing page path');
}
if ($this->site()->contentPath() === null) {
if ($this->site->contentPath() === null) {
throw new UnexpectedValueException('Unexpected missing site path');
}
FileSystem::write($page->contentPath() . $filename, $fileContent);
FileSystem::touch($this->site()->contentPath());
FileSystem::touch($this->site->contentPath());
$contentHistory = new ContentHistory($page->contentPath());
$contentHistory->update(ContentHistoryEvent::Edited, $this->user()->username(), time());
$contentHistory->update(ContentHistoryEvent::Edited, $this->panel->user()->username(), time());
$contentHistory->save();
// Update page with the new data
@ -781,7 +832,7 @@ class PagesController extends AbstractController
// Check if page template has to change
if ($page->template()->name() !== ($template = $requestData->get('template'))) {
if (!$this->site()->templates()->has($template)) {
if (!$this->site->templates()->has($template)) {
throw new TranslatedException('Invalid page template', 'panel.pages.page.cannotEdit.invalidTemplate');
}
$page = $this->changePageTemplate($page, $template);
@ -796,7 +847,7 @@ class PagesController extends AbstractController
if ($page->isIndexPage() || $page->isErrorPage()) {
throw new TranslatedException('Cannot change slug of index or error pages', 'panel.pages.page.cannotEdit.indexOrErrorPageSlug');
}
if ($this->site()->findPage($page->parent()?->route() . $slug . '/') !== null) {
if ($this->site->findPage($page->parent()?->route() . $slug . '/') !== null) {
throw new TranslatedException('A page with the same route already exists', 'panel.pages.page.cannotEdit.alreadyExists');
}
$page = $this->changePageName($page, ltrim($page->num() . '-', '-') . $slug);
@ -850,7 +901,7 @@ class PagesController extends AbstractController
$directory = dirname($page->contentPath());
$destination = FileSystem::joinPaths($directory, $name, DS);
FileSystem::moveDirectory($page->contentPath(), $destination);
return $this->site()->retrievePage($destination);
return $this->site->retrievePage($destination);
}
/**
@ -877,7 +928,7 @@ class PagesController extends AbstractController
$destination = FileSystem::joinPaths($parent->contentPath(), basename($page->contentRelativePath()), DS);
FileSystem::moveDirectory($page->contentPath(), $destination);
return $this->site()->retrievePage($destination);
return $this->site->retrievePage($destination);
}
/**
@ -907,9 +958,9 @@ class PagesController extends AbstractController
protected function resolveParent(string $parent): Page|Site
{
if ($parent === '.') {
return $this->site();
return $this->site;
}
return $this->site()->findPage($parent) ?? throw new RuntimeException('Invalid parent');
return $this->site->findPage($parent) ?? throw new RuntimeException('Invalid parent');
}
/**
@ -931,7 +982,7 @@ class PagesController extends AbstractController
$inclusiveSiblings = $inclusiveSiblings->reverse();
}
$indexOffset = $inclusiveSiblings->indexOf($this->site()->indexPage());
$indexOffset = $inclusiveSiblings->indexOf($this->site->indexPage());
if ($indexOffset !== null) {
$inclusiveSiblings->moveItem($indexOffset, 0);

View File

@ -22,10 +22,13 @@ class RegisterController extends AbstractController
public function register(Schemes $schemes): Response
{
if (!$this->site->users()->isEmpty()) {
return $this->redirectToReferer();
return $this->redirectToReferer(
default: $this->generateRoute('panel.index'),
base: $this->panel->panelRoot()
);
}
$this->csrfToken->generate($this->panel()->getCsrfTokenName());
$this->csrfToken->generate($this->panel->getCsrfTokenName());
$fields = $schemes->get('forms.register')->fields();
@ -40,7 +43,7 @@ class RegisterController extends AbstractController
try {
$fields->setValues($this->request->input())->validate();
} catch (ValidationException) {
$this->panel()->notify($this->translate('panel.users.user.cannotCreate.varMissing'), 'error');
$this->panel->notify($this->translate('panel.users.user.cannotCreate.varMissing'), 'error');
return $this->redirect($this->generateRoute('panel.index'));
}

View File

@ -58,13 +58,13 @@ class UsersController extends AbstractController
try {
$fields->setValues($requestData)->validate();
} catch (ValidationException) {
$this->panel()->notify($this->translate('panel.users.user.cannotCreate.varMissing'), 'error');
$this->panel->notify($this->translate('panel.users.user.cannotCreate.varMissing'), 'error');
return $this->redirect($this->generateRoute('panel.users'));
}
// Ensure there isn't a user with the same username
if ($this->site->users()->has($requestData->get('username'))) {
$this->panel()->notify($this->translate('panel.users.user.cannotCreate.alreadyExists'), 'error');
$this->panel->notify($this->translate('panel.users.user.cannotCreate.alreadyExists'), 'error');
return $this->redirect($this->generateRoute('panel.users'));
}
@ -78,7 +78,7 @@ class UsersController extends AbstractController
Yaml::encodeToFile($userData, FileSystem::joinPaths($this->config->get('system.users.paths.accounts'), $requestData->get('username') . '.yaml'));
$this->panel()->notify($this->translate('panel.users.user.created'), 'success');
$this->panel->notify($this->translate('panel.users.user.created'), 'success');
return $this->redirect($this->generateRoute('panel.users'));
}
@ -97,7 +97,7 @@ class UsersController extends AbstractController
if (!$user) {
throw new TranslatedException(sprintf('User "%s" not found', $routeParams->get('user')), 'panel.users.user.notFound');
}
if (!$this->user()->canDeleteUser($user)) {
if (!$this->panel->user()->canDeleteUser($user)) {
throw new TranslatedException(
sprintf('Cannot delete user "%s", you must be an administrator and the user must not be logged in', $user->username()),
'users.user.cannotDelete'
@ -109,8 +109,11 @@ class UsersController extends AbstractController
$this->deleteUserImage($user);
}
} catch (TranslatedException $e) {
$this->panel()->notify($e->getTranslatedMessage(), 'error');
return $this->redirectToReferer(default: '/users/');
$this->panel->notify($e->getTranslatedMessage(), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.users'),
base: $this->panel->panelRoot()
);
}
$lastAccessRegistry = new Registry(FileSystem::joinPaths($this->config->get('system.panel.paths.logs'), 'lastAccess.json'));
@ -118,7 +121,7 @@ class UsersController extends AbstractController
// Remove user last access from registry
$lastAccessRegistry->remove($user->username());
$this->panel()->notify($this->translate('panel.users.user.deleted'), 'success');
$this->panel->notify($this->translate('panel.users.user.deleted'), 'success');
return $this->redirect($this->generateRoute('panel.users'));
}
@ -134,11 +137,14 @@ class UsersController extends AbstractController
$user = $this->site->users()->get($routeParams->get('user'));
if ($user === null) {
$this->panel()->notify($this->translate('panel.users.user.notFound'), 'error');
return $this->redirectToReferer(default: '/users/');
$this->panel->notify($this->translate('panel.users.user.notFound'), 'error');
return $this->redirectToReferer(
default: $this->generateRoute('panel.users'),
base: $this->panel->panelRoot()
);
}
if ($this->user()->canChangeOptionsOf($user)) {
if ($this->panel->user()->canChangeOptionsOf($user)) {
try {
$this->deleteUserImage($user);
@ -146,12 +152,12 @@ class UsersController extends AbstractController
Arr::remove($userData, 'image');
Yaml::encodeToFile($userData, FileSystem::joinPaths($this->config->get('system.users.paths.accounts'), $user->username() . '.yaml'));
$this->panel()->notify($this->translate('panel.user.image.deleted'), 'success');
$this->panel->notify($this->translate('panel.user.image.deleted'), 'success');
} catch (TranslatedException $e) {
$this->panel()->notify($e->getTranslatedMessage(), 'error');
$this->panel->notify($e->getTranslatedMessage(), 'error');
}
} else {
$this->panel()->notify($this->translate('panel.users.user.cannotEdit', $user->username()), 'error');
$this->panel->notify($this->translate('panel.users.user.cannotEdit', $user->username()), 'error');
}
return $this->redirect($this->generateRoute('panel.users.profile', ['user' => $user->username()]));
@ -169,29 +175,29 @@ class UsersController extends AbstractController
$user = $this->site->users()->get($routeParams->get('user'));
if ($user === null) {
$this->panel()->notify($this->translate('panel.users.user.notFound'), 'error');
$this->panel->notify($this->translate('panel.users.user.notFound'), 'error');
return $this->redirect($this->generateRoute('panel.users'));
}
$fields->setModel($user);
// Disable password and/or role fields if they cannot be changed
$fields->get('password')->set('disabled', !$this->user()->canChangePasswordOf($user));
$fields->get('role')->set('disabled', !$this->user()->canChangeRoleOf($user));
$fields->get('password')->set('disabled', !$this->panel->user()->canChangePasswordOf($user));
$fields->get('role')->set('disabled', !$this->panel->user()->canChangeRoleOf($user));
if ($this->request->method() === RequestMethod::POST) {
// Ensure that options can be changed
if ($this->user()->canChangeOptionsOf($user)) {
if ($this->panel->user()->canChangeOptionsOf($user)) {
$fields->setValuesFromRequest($this->request, null)->validate();
try {
$this->updateUser($user, $fields);
$this->panel()->notify($this->translate('panel.users.user.edited'), 'success');
$this->panel->notify($this->translate('panel.users.user.edited'), 'success');
} catch (TranslatedException $e) {
$this->panel()->notify($this->translate($e->getLanguageString(), $user->username()), 'error');
$this->panel->notify($this->translate($e->getLanguageString(), $user->username()), 'error');
}
} else {
$this->panel()->notify($this->translate('panel.users.user.cannotEdit', $user->username()), 'error');
$this->panel->notify($this->translate('panel.users.user.cannotEdit', $user->username()), 'error');
}
return $this->redirect($this->generateRoute('panel.users.profile', ['user' => $user->username()]));
@ -238,7 +244,7 @@ class UsersController extends AbstractController
if ($field->name() === 'password') {
// Ensure that password can be changed
if (!$this->user()->canChangePasswordOf($user)) {
if (!$this->panel->user()->canChangePasswordOf($user)) {
throw new TranslatedException(sprintf('Cannot change the password of %s', $user->username()), 'panel.users.user.cannotChangePassword');
}
// Hash the new password
@ -248,7 +254,7 @@ class UsersController extends AbstractController
if ($field->name() === 'role') {
// Ensure that user role can be changed
if ($field->value() !== $user->role() && !$this->user()->canChangeRoleOf($user)) {
if ($field->value() !== $user->role() && !$this->panel->user()->canChangeRoleOf($user)) {
throw new TranslatedException(sprintf('Cannot change the role of %s', $user->username()), 'panel.users.user.cannotChangeRole');
}
Arr::set($userData, 'role', $field->value());
@ -297,7 +303,7 @@ class UsersController extends AbstractController
$this->deleteUserImage($user);
}
$this->panel()->notify($this->translate('panel.user.image.uploaded'), 'success');
$this->panel->notify($this->translate('panel.user.image.uploaded'), 'success');
return $file->name();
}