diff --git a/module/Olcs/src/Controller/ConversationsController.php b/module/Olcs/src/Controller/ConversationsController.php index 92185cc4b..f027cf303 100644 --- a/module/Olcs/src/Controller/ConversationsController.php +++ b/module/Olcs/src/Controller/ConversationsController.php @@ -7,14 +7,18 @@ use Common\Controller\Interfaces\ToggleAwareInterface; use Common\Controller\Lva\AbstractController; use Common\FeatureToggle; +use Common\Form\Form; use Common\Service\Helper\FlashMessengerHelperService; +use Common\Service\Helper\FormHelperService; use Common\Service\Table\TableFactory; +use Dvsa\Olcs\Transfer\Command\Messaging\Message\Create as CreateMessageCommand; use Dvsa\Olcs\Transfer\Query\Messaging\Messages\ByConversation as ByConversationQuery; use Dvsa\Olcs\Transfer\Query\Messaging\Conversations\ByOrganisation as ByOrganisationQuery; use Dvsa\Olcs\Utils\Translation\NiTextTranslation; +use Laminas\Http\Response; use Laminas\View\Model\ViewModel; -use Laminas\View\View; use LmcRbacMvc\Service\AuthorizationService; +use Olcs\Form\Model\Form\Message\Reply as ReplyForm; class ConversationsController extends AbstractController implements ToggleAwareInterface { @@ -25,17 +29,19 @@ class ConversationsController extends AbstractController implements ToggleAwareI ]; protected FlashMessengerHelperService $flashMessengerHelper; - protected TableFactory $tableFactory; + protected TableFactory $tableFactory; + protected FormHelperService $formHelperService; public function __construct( - NiTextTranslation $niTextTranslationUtil, - AuthorizationService $authService, + NiTextTranslation $niTextTranslationUtil, + AuthorizationService $authService, FlashMessengerHelperService $flashMessengerHelper, - TableFactory $tableFactory - ) - { + TableFactory $tableFactory, + FormHelperService $formHelperService + ) { $this->flashMessengerHelper = $flashMessengerHelper; $this->tableFactory = $tableFactory; + $this->formHelperService = $formHelperService; parent::__construct($niTextTranslationUtil, $authService); } @@ -77,7 +83,8 @@ public function addAction(): ViewModel return $view; } - public function viewAction(): ViewModel + /** @return ViewModel|Response */ + public function viewAction() { $params = [ 'page' => $this->params()->fromQuery('page', 1), @@ -95,12 +102,53 @@ public function viewAction(): ViewModel $messages = []; } + $form = $this->formHelperService->createForm(ReplyForm::class, true, false); + $this->formHelperService->setFormActionFromRequest($form, $this->getRequest()); + $table = $this->tableFactory ->buildTable('messages-view', $messages, $params); - $view = new ViewModel(['table' => $table]); + $view = new ViewModel( + [ + 'table' => $table, + 'form' => $form, + ], + ); $view->setTemplate('messages-view'); + if ($this->getRequest()->isPost() && $this->params()->fromPost('action') === 'reply') { + return $this->parseReply($view, $form); + } + return $view; } + + /** @return Response|ViewModel */ + protected function parseReply(ViewModel $view, Form $form) + { + $form->setData((array)$this->params()->fromPost()); + $form->get('id')->setValue($this->params()->fromRoute('conversation')); + + if (!$form->isValid()) { + return $view; + } + + $response = $this->handleCommand( + CreateMessageCommand::create( + [ + 'conversation' => $this->params()->fromRoute('conversationId'), + 'messageContent' => $form->get('form-actions')->get('reply')->getValue(), + ], + ), + ); + + if ($response->isOk()) { + $this->flashMessengerHelper->addSuccessMessage('Reply submitted successfully'); + return $this->redirect()->toRoute('conversations/view', $this->params()->fromRoute()); + } + + $this->handleErrors($response->getResult()); + + return parent::indexAction(); + } } diff --git a/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php b/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php index ec05a471f..96e6cb6ad 100644 --- a/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php +++ b/module/Olcs/src/Controller/Factory/ConversationsControllerFactory.php @@ -5,6 +5,7 @@ namespace Olcs\Controller\Factory; use Common\Service\Helper\FlashMessengerHelperService; +use Common\Service\Helper\FormHelperService; use Common\Service\Table\TableFactory; use Dvsa\Olcs\Utils\Translation\NiTextTranslation; use Interop\Container\ContainerInterface; @@ -15,18 +16,23 @@ class ConversationsControllerFactory implements FactoryInterface { - public function __invoke(ContainerInterface $container, $requestedName, array $options = null): ConversationsController - { + public function __invoke( + ContainerInterface $container, + $requestedName, + array $options = null + ): ConversationsController { $niTextTranslationUtil = $container->get(NiTextTranslation::class); $authService = $container->get(AuthorizationService::class); $flashMessengerHelper = $container->get(FlashMessengerHelperService::class); $tableFactory = $container->get(TableFactory::class); + $formHelperService = $container->get(FormHelperService::class); return new ConversationsController( $niTextTranslationUtil, $authService, $flashMessengerHelper, $tableFactory, + $formHelperService, ); } } diff --git a/module/Olcs/src/Form/Model/Fieldset/Message/Reply.php b/module/Olcs/src/Form/Model/Fieldset/Message/Reply.php new file mode 100644 index 000000000..debb24e15 --- /dev/null +++ b/module/Olcs/src/Form/Model/Fieldset/Message/Reply.php @@ -0,0 +1,43 @@ +partial( echo $menu->setMinDepth(0) ->setMaxDepth(0) ->setPartial('partials/tabs-nav'); - + ?> +
+ + + Send a reply + + +
+ formErrors($this->form); + echo $this->form($this->form); + ?> +
+
+ table; ?> diff --git a/test/Olcs/src/Controller/ConversationsControllerTest.php b/test/Olcs/src/Controller/ConversationsControllerTest.php index 19da55ecd..d37c63e44 100644 --- a/test/Olcs/src/Controller/ConversationsControllerTest.php +++ b/test/Olcs/src/Controller/ConversationsControllerTest.php @@ -2,16 +2,26 @@ namespace OlcsTest\Controller; +use Common\Controller\Plugin\HandleCommand; use Common\Controller\Plugin\HandleQuery; +use Common\Controller\Plugin\Redirect; +use Common\Form\Form; use Common\Service\Cqrs\Response; use Common\Service\Helper\FlashMessengerHelperService; +use Common\Service\Helper\FormHelperService; use Common\Service\Table\TableFactory; use Dvsa\Olcs\Utils\Translation\NiTextTranslation; +use Laminas\Form\Element\Text; +use Laminas\Form\Fieldset; +use Laminas\Http\Request; +use Laminas\Http\Response as HttpResponse; use Laminas\Mvc\Controller\Plugin\Params; +use Dvsa\Olcs\Transfer\Command\Messaging\Message\Create as CreateMessageCommand; use Laminas\View\Model\ViewModel; use Mockery as m; use Mockery\Adapter\Phpunit\MockeryTestCase as TestCase; use Olcs\Controller\ConversationsController as Sut; +use Olcs\Form\Model\Form\Message\Reply; use ReflectionClass; use LmcRbacMvc\Service\AuthorizationService; @@ -25,6 +35,9 @@ public function setUp(): void $this->mockAuthService = m::mock(AuthorizationService::class)->makePartial(); $this->mockFlashMessengerHelper = m::mock(FlashMessengerHelperService::class)->makePartial(); $this->mockTableFactory = m::mock(TableFactory::class)->makePartial(); + $this->mockFormHelperService = m::mock(FormHelperService::class)->makePartial(); + $this->mockForm = m::mock(Form::class); + $this->mockParams = m::mock(Params::class); $this->sut = m::mock(Sut::class) ->makePartial() @@ -35,6 +48,21 @@ public function setUp(): void $this->setMockedProperties($reflectionClass, 'authService', $this->mockAuthService); $this->setMockedProperties($reflectionClass, 'flashMessengerHelper', $this->mockFlashMessengerHelper); $this->setMockedProperties($reflectionClass, 'tableFactory', $this->mockTableFactory); + $this->setMockedProperties($reflectionClass, 'formHelperService', $this->mockFormHelperService); + + $this->mockFormHelperService->shouldReceive('createForm') + ->once() + ->with(Reply::class, true, false) + ->andReturn($this->mockForm); + + $this->mockFormHelperService->shouldReceive('setFormActionFromRequest') + ->once() + ->withArgs( + function ($form, $request) { + $this->assertInstanceOf(Form::class, $form); + return true; + }, + ); } public function setMockedProperties(ReflectionClass $reflectionClass, string $property, $value): void @@ -57,22 +85,21 @@ public function testViewAction(): void $mockHandleQuery->shouldReceive('__invoke') ->andReturn($mockResponse); - $mockParams = m::mock(Params::class); - $mockParams->shouldReceive('fromQuery') - ->with('page', 1) - ->andReturn(1); - $mockParams->shouldReceive('fromQuery') - ->with('limit', 10) - ->andReturn(10); - $mockParams->shouldReceive('fromQuery') - ->withNoArgs() - ->andReturn([]); - $mockParams->shouldReceive('fromRoute') - ->with('conversationId') - ->andReturn(1); + $this->mockParams->shouldReceive('fromQuery') + ->with('page', 1) + ->andReturn(1); + $this->mockParams->shouldReceive('fromQuery') + ->with('limit', 10) + ->andReturn(10); + $this->mockParams->shouldReceive('fromQuery') + ->withNoArgs() + ->andReturn([]); + $this->mockParams->shouldReceive('fromRoute') + ->with('conversationId') + ->andReturn(1); $this->sut->shouldReceive('params') - ->andReturn($mockParams); + ->andReturn($this->mockParams); $this->sut->shouldReceive('plugin') ->with('handleQuery') ->andReturn($mockHandleQuery); @@ -91,4 +118,109 @@ public function testViewAction(): void $this->assertInstanceOf(ViewModel::class, $view); $this->assertEquals($table, $view->getVariable('table')); } + + public function testReply(): void + { + $mockRequest = m::mock(Request::class); + $mockRequest->shouldReceive('isPost') + ->once() + ->andReturn(true); + + $this->mockParams->shouldReceive('fromPost') + ->once() + ->with('action') + ->andReturn('reply'); + $this->mockParams->shouldReceive('fromPost') + ->once() + ->withNoArgs() + ->andReturn(['a' => 'b']); + $this->mockParams->shouldReceive('fromRoute') + ->once() + ->with('conversation') + ->andReturn('1'); + $this->mockParams->shouldReceive('fromRoute') + ->once() + ->withNoArgs() + ->andReturn(['a' => 'b']); + + $this->sut->shouldReceive('getRequest') + ->twice() + ->andReturn($mockRequest); + + $mockCommandReturn = m::mock(Response::class); + $mockCommandReturn->shouldReceive('isOk') + ->once() + ->andReturn(true); + + $mockCommandHandler = m::mock(HandleCommand::class); + $mockCommandHandler->shouldReceive('__invoke') + ->once() + ->withArgs( + function ($command) { + $this->assertInstanceOf(CreateMessageCommand::class, $command); + + return true; + }, + ) + ->andReturn($mockCommandReturn); + + $this->sut->shouldReceive('plugin') + ->with('handleCommand') + ->andReturn($mockCommandHandler); + + $this->mockForm->shouldReceive('setData') + ->once() + ->with(['a' => 'b']); + + $mockFormElement = m::mock(Text::class); + $mockFormElement->shouldReceive('setValue') + ->once() + ->with('1'); + $mockFormElement->shouldReceive('getValue') + ->once() + ->andReturn('abc'); + + $this->mockForm->shouldReceive('get') + ->once() + ->with('id') + ->andReturn($mockFormElement); + + $mockFormActionsElement = m::mock(Fieldset::class); + $mockFormActionsElement->shouldReceive('get') + ->once() + ->with('reply') + ->andReturn($mockFormElement); + $this->mockForm->shouldReceive('get') + ->once() + ->with('form-actions') + ->andReturn($mockFormActionsElement); + + $this->mockForm->shouldReceive('isValid') + ->once() + ->with() + ->andReturn(true); + + $this->mockFlashMessengerHelper->shouldReceive('addSuccessMessage') + ->once() + ->with('Reply submitted successfully'); + + $mockViewModel = m::mock(ViewModel::class); + $mockViewModel->shouldReceive('getVariable') + ->once() + ->with('table') + ->andReturn(''); + + $mockRedirect = m::mock(Redirect::class); + $mockRedirect->shouldReceive('toRoute') + ->once() + ->with('conversations/view', ['a' => 'b']) + ->andReturn($mockViewModel); + + $this->sut->shouldReceive('plugin') + ->once() + ->with('redirect') + ->andReturn($mockRedirect); + + $this->testViewAction(); + } }