mirror of https://github.com/FriendsOfTYPO3/tea.git synced 2024-11-10 00:36:13 +01:00

[FEATURE] Allow creating a new tea in the FE (#874)

Part of #871
This commit is contained in:
Oliver Klee 2023-06-22 20:30:12 +02:00 committed by GitHub
parent ad460b20b3
commit 82e7e95487
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 168 additions and 4 deletions

View file

@ -6,7 +6,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
## x.y.z ## x.y.z
### Added ### Added
- Add a FE editor (#864) - Add an FE editor (#864, #872, #874)
- Add automerging of green Dependabot PRs (#756) - Add automerging of green Dependabot PRs (#756)
### Changed ### Changed

View file

@ -8,6 +8,7 @@ use Psr\Http\Message\ResponseInterface;
use TTN\Tea\Domain\Model\Product\Tea; use TTN\Tea\Domain\Model\Product\Tea;
use TTN\Tea\Domain\Repository\Product\TeaRepository; use TTN\Tea\Domain\Repository\Product\TeaRepository;
use TYPO3\CMS\Core\Context\Context; use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
/** /**
@ -70,4 +71,22 @@ class FrontEndEditorController extends ActionController
return $this->redirect('index'); return $this->redirect('index');
} }
public function newAction(?Tea $tea = null): ResponseInterface
{
// Note: We are using `makeInstance` here instead of `new` to allow for XCLASSing.
$teaToAssign = $tea ?? GeneralUtility::makeInstance(Tea::class);
$this->view->assign('tea', $teaToAssign);
return $this->htmlResponse();
}
public function createAction(Tea $tea): ResponseInterface
{
$tea->setOwnerUid($this->getUidOfLoggedInUser());
$this->teaRepository->add($tea);
return $this->redirect('index');
}
} }

View file

@ -67,6 +67,14 @@
<source>Save</source> <source>Save</source>
<target>Speichern</target> <target>Speichern</target>
</trans-unit> </trans-unit>
<trans-unit id="plugin.frontEndEditor.action.new">
<source>Create new tea</source>
<target>Neuen Tee anlegen</target>
</trans-unit>
<trans-unit id="plugin.frontEndEditor.new.heading">
<source>Create new tea</source>
<target>Neuen Tee anlegen</target>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -51,6 +51,12 @@
<trans-unit id="plugin.frontEndEditor.action.save"> <trans-unit id="plugin.frontEndEditor.action.save">
<source>Save</source> <source>Save</source>
</trans-unit> </trans-unit>
<trans-unit id="plugin.frontEndEditor.action.new">
<source>Create new tea</source>
</trans-unit>
<trans-unit id="plugin.frontEndEditor.new.heading">
<source>Create new tea</source>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View file

@ -7,6 +7,12 @@
<f:translate key="plugin.frontEndEditor.index.heading"/> <f:translate key="plugin.frontEndEditor.index.heading"/>
</h2> </h2>
<p class="btn btn-link">
<f:link.action action="new">
<f:translate key="plugin.frontEndEditor.action.new"/>
</f:link.action>
</p>
<f:if condition="{teas}"> <f:if condition="{teas}">
<f:then> <f:then>
<table class="table table-striped table-hover"> <table class="table table-striped table-hover">

View file

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:layout name="FrontEndEditor"/>
<f:section name="main">
<h2>
<f:translate key="plugin.frontEndEditor.new.heading"/>
</h2>
<f:form action="create" name="tea" object="{tea}">
<f:render partial="FrontEndEditor/Form" arguments="{_all}"/>
</f:form>
</f:section>
</html>

View file

@ -13,6 +13,7 @@ use TYPO3\CMS\Core\Context\UserAspect;
use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\HtmlResponse;
use TYPO3\CMS\Core\Http\RedirectResponse; use TYPO3\CMS\Core\Http\RedirectResponse;
use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Information\Typo3Version;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException; use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
use TYPO3\CMS\Extbase\Persistence\QueryResultInterface; use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
@ -67,6 +68,14 @@ final class FrontEndEditorControllerTest extends UnitTestCase
$this->subject->method('htmlResponse')->willReturn($responseStub); $this->subject->method('htmlResponse')->willReturn($responseStub);
} }
protected function tearDown(): void
{
// empty FIFO queue
GeneralUtility::makeInstance(Tea::class);
parent::tearDown();
}
/** /**
* @param int<0, max> $userUid * @param int<0, max> $userUid
*/ */
@ -193,7 +202,7 @@ final class FrontEndEditorControllerTest extends UnitTestCase
$this->setUidOfLoggedInUser($userUid); $this->setUidOfLoggedInUser($userUid);
$tea = new Tea(); $tea = new Tea();
$tea->setOwnerUid($userUid); $tea->setOwnerUid($userUid);
$this->mockRedirect('index'); $this->stubRedirect('index');
$this->teaRepositoryMock->expects(self::once())->method('update')->with($tea); $this->teaRepositoryMock->expects(self::once())->method('update')->with($tea);
@ -216,6 +225,20 @@ final class FrontEndEditorControllerTest extends UnitTestCase
} }
} }
private function stubRedirect(string $actionName): void
{
if ((new Typo3Version())->getMajorVersion() <= 11) {
$this->subject->method('redirect')
// @phpstan-ignore-next-line This class does not exist in V12 anymore, but this branch is V11-only.
->willThrowException(new StopActionException('redirectToUri', 1476045828));
// @phpstan-ignore-next-line This class does not exist in V12 anymore, but this branch is V11-only.
$this->expectException(StopActionException::class);
} else {
$redirectResponse = $this->createStub(RedirectResponse::class);
$this->subject->method('redirect')->willReturn($redirectResponse);
}
}
/** /**
* @test * @test
*/ */
@ -262,4 +285,92 @@ final class FrontEndEditorControllerTest extends UnitTestCase
$this->subject->updateAction($tea); $this->subject->updateAction($tea);
} }
/**
* @test
*/
public function newActionWithTeaAssignsProvidedTeaToView(): void
{
$tea = new Tea();
$this->viewMock->expects(self::once())->method('assign')->with('tea', $tea);
$this->subject->newAction($tea);
}
/**
* @test
*/
public function newActionWithNullTeaAssignsProvidedNewTeaToView(): void
{
$tea = new Tea();
GeneralUtility::addInstance(Tea::class, $tea);
$this->viewMock->expects(self::once())->method('assign')->with('tea', $tea);
$this->subject->newAction(null);
}
/**
* @test
*/
public function newActionWithoutTeaAssignsProvidedNewTeaToView(): void
{
$tea = new Tea();
GeneralUtility::addInstance(Tea::class, $tea);
$this->viewMock->expects(self::once())->method('assign')->with('tea', $tea);
$this->subject->newAction();
}
/**
* @test
*/
public function newActionReturnsHtmlResponse(): void
{
$result = $this->subject->newAction();
self::assertInstanceOf(HtmlResponse::class, $result);
}
/**
* @test
*/
public function createActionSetsLoggedInUserAsOwnerOfProvidedTea(): void
{
$userUid = 5;
$this->setUidOfLoggedInUser($userUid);
$tea = new Tea();
$this->stubRedirect('index');
$this->subject->createAction($tea);
self::assertSame($userUid, $tea->getOwnerUid());
}
/**
* @test
*/
public function createActionPersistsProvidedTea(): void
{
$tea = new Tea();
$this->stubRedirect('index');
$this->teaRepositoryMock->expects(self::once())->method('add')->with($tea);
$this->subject->createAction($tea);
}
/**
* @test
*/
public function createActionRedirectsToIndexAction(): void
{
$tea = new Tea();
$this->mockRedirect('index');
$this->subject->updateAction($tea);
}
} }

View file

@ -42,12 +42,12 @@ ExtensionUtility::configurePlugin(
'TeaFrontEndEditor', 'TeaFrontEndEditor',
// all actions // all actions
[ [
FrontEndEditorController::class => 'index, edit, update', FrontEndEditorController::class => 'index, edit, update, create, new',
], ],
// non-cacheable actions // non-cacheable actions
[ [
// All actions need to be non-cacheable because they either contain dynamic data, // 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). // or because they are specific to the logged-in FE user (while FE content is cached by FE groups).
FrontEndEditorController::class => 'index, edit, update', FrontEndEditorController::class => 'index, edit, update, create, new',
] ]
); );