From 1f263d883926ceb974b7d7e689f3a2b2f6c9b2c7 Mon Sep 17 00:00:00 2001 From: Oliver Klee Date: Thu, 22 Jun 2023 13:17:51 +0200 Subject: [PATCH] [FEATURE] Add a list view for the FE tea editor (#864) This is one more part of building CRUD functionality. --- CHANGELOG.md | 1 + .../Controller/FrontEndEditorController.php | 44 +++++++ Configuration/TCA/Overrides/tt_content.php | 8 ++ Resources/Private/Language/de.locallang.xlf | 20 +++ Resources/Private/Language/locallang.xlf | 15 +++ Resources/Private/Layouts/FrontEndEditor.html | 12 ++ .../Templates/FrontEndEditor/Index.html | 40 ++++++ .../FrontEndEditorControllerTest.php | 121 ++++++++++++++++++ ext_localconf.php | 19 +++ 9 files changed, 280 insertions(+) create mode 100644 Classes/Controller/FrontEndEditorController.php create mode 100644 Resources/Private/Layouts/FrontEndEditor.html create mode 100644 Resources/Private/Templates/FrontEndEditor/Index.html create mode 100644 Tests/Unit/Controller/FrontEndEditorControllerTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 90256ec..78f0838 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ This project adheres to [Semantic Versioning](https://semver.org/). ## x.y.z ### Added +- Add a FE editor (#864) - Add automerging of green Dependabot PRs (#756) ### Changed diff --git a/Classes/Controller/FrontEndEditorController.php b/Classes/Controller/FrontEndEditorController.php new file mode 100644 index 0000000..f71cbbc --- /dev/null +++ b/Classes/Controller/FrontEndEditorController.php @@ -0,0 +1,44 @@ +context = $context; + $this->teaRepository = $teaRepository; + } + + public function indexAction(): ResponseInterface + { + $userUid = $this->getUidOfLoggedInUser(); + if ($userUid > 0) { + $this->view->assign('teas', $this->teaRepository->findByOwnerUid($userUid)); + } + + return $this->htmlResponse(); + } + + /** + * @return int<0, max> + */ + private function getUidOfLoggedInUser(): int + { + return $this->context->getPropertyFromAspect('frontend.user', 'id'); + } +} diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php index cd25ffb..638d902 100644 --- a/Configuration/TCA/Overrides/tt_content.php +++ b/Configuration/TCA/Overrides/tt_content.php @@ -23,9 +23,17 @@ call_user_func( 'EXT:tea/Resources/Public/Icons/Extension.svg' ); + \TYPO3\CMS\Extbase\Utility\ExtensionUtility::registerPlugin( + 'Tea', + 'TeaFrontEndEditor', + 'LLL:EXT:tea/Resources/Private/Language/locallang.xlf:plugin.tea_frontend_editor', + 'EXT:tea/Resources/Public/Icons/Extension.svg' + ); + // This removes the default controls from the plugin. $controlsToRemove = 'recursive,select_key,pages'; $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist']['tea_teaindex'] = $controlsToRemove; $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist']['tea_teashow'] = $controlsToRemove; + $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_excludelist']['tea_teafrontendeditor'] = $controlsToRemove; } ); diff --git a/Resources/Private/Language/de.locallang.xlf b/Resources/Private/Language/de.locallang.xlf index 5f0491b..9875a07 100644 --- a/Resources/Private/Language/de.locallang.xlf +++ b/Resources/Private/Language/de.locallang.xlf @@ -11,6 +11,10 @@ Tea single view Tee-Einzelansicht + + Tea front-end editor + Frontend-Editor für Tee + Our selection of assorted teas Unsere Auswahl an erlesenen Tees @@ -23,6 +27,22 @@ Title Titel + + My teas + Meine Tees + + + You have not created any teas yet. + Du hast noch keine Tees angelegt. + + + UID + UID + + + Title + Titel + diff --git a/Resources/Private/Language/locallang.xlf b/Resources/Private/Language/locallang.xlf index 75b3147..1f2eb1a 100644 --- a/Resources/Private/Language/locallang.xlf +++ b/Resources/Private/Language/locallang.xlf @@ -9,6 +9,9 @@ Tea single view + + Tea front-end editor + Our selection of assorted teas @@ -18,6 +21,18 @@ Title + + My teas + + + You have not created any teas yet. + + + UID + + + Title + diff --git a/Resources/Private/Layouts/FrontEndEditor.html b/Resources/Private/Layouts/FrontEndEditor.html new file mode 100644 index 0000000..f92edfc --- /dev/null +++ b/Resources/Private/Layouts/FrontEndEditor.html @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/Resources/Private/Templates/FrontEndEditor/Index.html b/Resources/Private/Templates/FrontEndEditor/Index.html new file mode 100644 index 0000000..a4bf144 --- /dev/null +++ b/Resources/Private/Templates/FrontEndEditor/Index.html @@ -0,0 +1,40 @@ + + + + + +

+ +

+ + + + + + + + + + + + + + +
+ + + +
+ {tea.uid} + + {tea.title} +
+
+ + + +
+
+ diff --git a/Tests/Unit/Controller/FrontEndEditorControllerTest.php b/Tests/Unit/Controller/FrontEndEditorControllerTest.php new file mode 100644 index 0000000..e580626 --- /dev/null +++ b/Tests/Unit/Controller/FrontEndEditorControllerTest.php @@ -0,0 +1,121 @@ +context = new Context(); + $this->teaRepositoryMock = $this->createMock(TeaRepository::class); + + // We need to create an accessible mock in order to be able to set the protected `view`. + $methodsToMock = ['htmlResponse', 'redirect', 'redirectToUri']; + if ((new Typo3Version())->getMajorVersion() <= 11) { + $methodsToMock[] = 'forward'; + } + $this->subject = $this->getAccessibleMock( + FrontEndEditorController::class, + $methodsToMock, + [$this->context, $this->teaRepositoryMock] + ); + + $this->viewMock = $this->createMock(TemplateView::class); + $this->subject->_set('view', $this->viewMock); + + $responseStub = $this->createStub(HtmlResponse::class); + $this->subject->method('htmlResponse')->willReturn($responseStub); + } + + /** + * @param int<0, max> $userUid + */ + private function setUidOfLoggedInUser(int $userUid): void + { + $userAspectMock = $this->createMock(UserAspect::class); + $userAspectMock->method('get')->with('id')->willReturn($userUid); + $this->context->setAspect('frontend.user', $userAspectMock); + } + + /** + * @test + */ + public function isActionController(): void + { + self::assertInstanceOf(ActionController::class, $this->subject); + } + + /** + * @test + */ + public function indexActionForNoLoggedInUserAssignsNothingToView(): void + { + $this->setUidOfLoggedInUser(0); + + $this->viewMock->expects(self::never())->method('assign'); + + $this->subject->indexAction(); + } + + /** + * @test + */ + public function indexActionForLoggedInUserAssignsTeasOwnedByTheLoggedInUserToView(): void + { + $userUid = 5; + $this->setUidOfLoggedInUser($userUid); + + $teas = $this->createMock(QueryResultInterface::class); + $this->teaRepositoryMock->method('findByOwnerUid')->with($userUid)->willReturn($teas); + $this->viewMock->expects(self::once())->method('assign')->with('teas', $teas); + + $this->subject->indexAction(); + } + + /** + * @test + */ + public function indexActionReturnsHtmlResponse(): void + { + $result = $this->subject->indexAction(); + + self::assertInstanceOf(HtmlResponse::class, $result); + } +} diff --git a/ext_localconf.php b/ext_localconf.php index 74d7164..9e54675 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use TTN\Tea\Controller\FrontEndEditorController; use TTN\Tea\Controller\TeaController; use TYPO3\CMS\Extbase\Utility\ExtensionUtility; @@ -32,3 +33,21 @@ ExtensionUtility::configurePlugin( TeaController::class => '', ] ); + +// This makes the plugin available for front-end rendering. +ExtensionUtility::configurePlugin( + // extension name, matching the PHP namespaces (but without the vendor) + 'Tea', + // arbitrary, but unique plugin name (not visible in the BE) + 'TeaFrontEndEditor', + // all actions + [ + FrontEndEditorController::class => 'index', + ], + // non-cacheable actions + [ + // All actions need to be non-cacheable because they either contain dynamic data, + // or because they are specific to the logged-in FE user (while FE content is cached by FE groups). + FrontEndEditorController::class => 'index', + ] +);