Skip to content

Commit

Permalink
feat: Message footer showing operator first read (dvsa/olcs-backend#110)
Browse files Browse the repository at this point in the history
* feat: Message footer showing operator first read

* fix: Ensure backwards compatibility

* fix: Removed an empty line

* chore: Update olcs/transfer

* fix: CS whitespace
  • Loading branch information
wadedvsa authored Mar 18, 2024
1 parent bd0f3c0 commit e105ff8
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 30 deletions.
19 changes: 11 additions & 8 deletions app/api/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace Dvsa\Olcs\Api\Domain\QueryHandler\Messaging\Message;

use ArrayIterator;
use DateTime;
use Doctrine\ORM\NoResultException;
use Doctrine\ORM\Query;
use Dvsa\Olcs\Api\Domain\AuthAwareInterface;
use Dvsa\Olcs\Api\Domain\AuthAwareTrait;
use Dvsa\Olcs\Api\Domain\QueryHandler\AbstractQueryHandler;
Expand All @@ -14,6 +17,7 @@
use Dvsa\Olcs\Api\Entity\Messaging\MessagingConversation;
use Dvsa\Olcs\Api\Entity\Messaging\MessagingUserMessageRead;
use Dvsa\Olcs\Api\Entity\System\FeatureToggle;
use Dvsa\Olcs\Transfer\Query\Messaging\Messages\ByConversation as ByConversationQuery;
use Dvsa\Olcs\Transfer\Query\QueryInterface;

class ByConversation extends AbstractQueryHandler implements ToggleRequiredInterface, AuthAwareInterface
Expand All @@ -29,15 +33,25 @@ class ByConversation extends AbstractQueryHandler implements ToggleRequiredInter
Repository\MessagingUserMessageRead::class,
];

/** @param QueryInterface|ByConversationQuery $query */
public function handleQuery(QueryInterface $query)
{
$messageRepository = $this->getRepo(Repository\Message::class);

$messageQueryBuilder = $messageRepository->getBaseMessageListWithContentQuery($query);
$messagesQuery =
$messageRepository->filterByConversationId($messageQueryBuilder, (int)$query->getConversation());

$messagesQuery = $messageRepository->filterByConversationId($messageQueryBuilder, (int)$query->getConversation());
if ($query->getIncludeReadRoles()) {
$messagesQuery = $messageRepository->addReadersToMessages($messagesQuery);
}

$messages = $messageRepository->fetchPaginatedList($messagesQuery, Query::HYDRATE_ARRAY, $query);
$messages = $messages->getArrayCopy();

$messages = $messageRepository->fetchPaginatedList($messagesQuery);
if ($query->getIncludeReadRoles() && count($query->getIncludeReadRoles()) > 0) {
$messages = $this->filterReadHistory($messages, $query->getReadRoles());
}

/** @var MessagingConversation $conversation */
$conversation = $this->getRepo(Repository\Conversation::class)->fetchById($query->getConversation());
Expand All @@ -54,9 +68,9 @@ public function handleQuery(QueryInterface $query)
];
}

private function markMessagesAsReadByCurrentUser(\ArrayIterator $messages): void
private function markMessagesAsReadByCurrentUser(array $messages): void
{
$currentDatetime = new \DateTime();
$currentDatetime = new DateTime();

$messageRepo = $this->getRepo(Repository\Message::class);
$userMessageReadRepo = $this->getRepo(Repository\MessagingUserMessageRead::class);
Expand All @@ -76,4 +90,21 @@ private function markMessagesAsReadByCurrentUser(\ArrayIterator $messages): void
}
}
}

private function filterReadHistory(array $messages, array $readRoles): array
{
array_walk(
$messages,
function (&$message) use ($readRoles) {
$message['userMessageReads'] = array_filter(
$message['userMessageReads'],
fn($umr) => count(array_filter($umr['user']['roles'], fn($r) => in_array($r['role'], $readRoles))) > 0,
);

usort($message['userMessageReads'], fn($a, $b) => $a['createdOn'] <=> $b['createdOn']);
},
);

return $messages;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -389,17 +389,18 @@ public function fetchList(QueryInterface $query, $hydrateMode = Query::HYDRATE_A
/**
* Abstracted paginator logic so it can be re-used with alternative queries
*
* @param QueryBuilder $qb Doctrine query builder
* @param int $hydrateMode Hydrate mode
* @param QueryBuilder $qb Doctrine query builder
* @param int $hydrateMode Hydrate mode
* @param QueryInterface $originalQuery Original query
*
* @return \ArrayIterator|\Traversable
*/
public function fetchPaginatedList(QueryBuilder $qb, $hydrateMode = Query::HYDRATE_ARRAY)
public function fetchPaginatedList(QueryBuilder $qb, $hydrateMode = Query::HYDRATE_ARRAY, QueryInterface $originalQuery = null)
{
$query = $qb->getQuery();
$query->setHydrationMode($hydrateMode);

if ($this->query instanceof PagedQueryInterface) {
if ($this->query instanceof PagedQueryInterface || ($originalQuery instanceof PagedQueryInterface)) {
$paginator = $this->getPaginator($query);

return $paginator->getIterator($hydrateMode);
Expand Down
13 changes: 13 additions & 0 deletions app/api/module/Api/src/Domain/Repository/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Doctrine\DBAL\ParameterType;
use Doctrine\ORM\Query;
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;
use Dvsa\Olcs\Api\Entity\Messaging\MessagingMessage as Entity;
use Dvsa\Olcs\Transfer\Query\QueryInterface;
Expand Down Expand Up @@ -53,6 +54,18 @@ public function filterByConversationId(QueryBuilder $qb, int $conversationId): Q
return $qb;
}

public function addReadersToMessages(QueryBuilder $qb): QueryBuilder
{
$qb->leftJoin($this->alias . '.userMessageReads', 'urm')
->leftJoin('urm.user', 'urmu')
->leftJoin('urmu.contactDetails', 'urmcd')
->leftJoin('urmcd.person', 'urmcdp')
->leftJoin('urmu.roles', 'urmur')
->addSelect('urm, urmcd, urmcdp, urmu, urmur');

return $qb;
}

public function getLastMessageByConversationId(int $conversationId): array
{
$qb = $this->createQueryBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Dvsa\OlcsTest\Api\Domain\QueryHandler\Messaging\Message;

use ArrayIterator;
use Doctrine\ORM\Query;
use Doctrine\ORM\QueryBuilder;
use Dvsa\Olcs\Api\Domain\QueryHandler\Messaging\Message\ByConversation;
use Dvsa\Olcs\Api\Domain\Repository;
Expand All @@ -12,6 +13,7 @@
use Dvsa\Olcs\Api\Entity\Messaging\MessagingUserMessageRead;
use Dvsa\Olcs\Api\Entity\Task\Task;
use Dvsa\Olcs\Api\Entity\User\Permission;
use Dvsa\Olcs\Api\Entity\User\Role;
use Dvsa\Olcs\Transfer\Query\Messaging\Messages\ByConversation as Qry;
use Dvsa\OlcsTest\Api\Domain\QueryHandler\QueryHandlerTestCase;
use LmcRbacMvc\Service\AuthorizationService;
Expand All @@ -37,27 +39,51 @@ public function testHandleQuery()
{
$query = Qry::create([
'conversation' => 1,
'includeReadRoles' => true,
'readRoles' => [Role::ROLE_OPERATOR_USER],
]);

$messages = new ArrayIterator(
[
['id' => 1,'messaging_conversation_id' => '1','messaging_content_id' => '1'],
['id' => 2,'messaging_conversation_id' => '1','messaging_content_id' => '2'],
['id' => 3,'messaging_conversation_id' => '1','messaging_content_id' => '3'],
['id' => 4,'messaging_conversation_id' => '1','messaging_content_id' => '4'],
['id' => 5,'messaging_conversation_id' => '1','messaging_content_id' => '5'],
['id' => 6,'messaging_conversation_id' => '1','messaging_content_id' => '6'],
['id' => 7,'messaging_conversation_id' => '1','messaging_content_id' => '7'],
['id' => 8,'messaging_conversation_id' => '1','messaging_content_id' => '8'],
]
['id' => 1, 'messaging_conversation_id' => '1', 'messaging_content_id' => '1', 'userMessageReads' => [['user' => ['roles' => [['role' => Role::ROLE_OPERATOR_USER]]]]]],
['id' => 2, 'messaging_conversation_id' => '1', 'messaging_content_id' => '2', 'userMessageReads' => [['user' => ['roles' => [['role' => Role::ROLE_OPERATOR_TM]]]]]],
['id' => 3, 'messaging_conversation_id' => '1', 'messaging_content_id' => '3', 'userMessageReads' => [['user' => ['roles' => []]]]],
['id' => 4, 'messaging_conversation_id' => '1', 'messaging_content_id' => '4', 'userMessageReads' => [['user' => ['roles' => []]]]],
['id' => 5, 'messaging_conversation_id' => '1', 'messaging_content_id' => '5', 'userMessageReads' => [['user' => ['roles' => []]]]],
['id' => 6, 'messaging_conversation_id' => '1', 'messaging_content_id' => '6', 'userMessageReads' => [['user' => ['roles' => []]]]],
['id' => 7, 'messaging_conversation_id' => '1', 'messaging_content_id' => '7', 'userMessageReads' => [['user' => ['roles' => []]]]],
['id' => 8, 'messaging_conversation_id' => '1', 'messaging_content_id' => '8', 'userMessageReads' => [['user' => ['roles' => []]]]],
],
);
$conversation = new MessagingConversation();
$mockQb = m::mock(QueryBuilder::class);
$this->repoMap[Repository\Message::class]->shouldReceive('getBaseMessageListWithContentQuery')->andReturn($mockQb);
$this->repoMap[Repository\Message::class]->shouldReceive('filterByConversationId')->andReturn($mockQb);
$this->repoMap[Repository\Message::class]->shouldReceive('fetchPaginatedList')->with($mockQb)->once()->andReturn($messages);
$this->repoMap[Repository\Message::class]->shouldReceive('fetchPaginatedCount')->with($mockQb)->once()->andReturn(10);
$this->repoMap[Repository\Conversation::class]->shouldReceive('fetchById')->with(1)->once()->andReturn($conversation);
$this->repoMap[Repository\Message::class]
->shouldReceive('getBaseMessageListWithContentQuery')
->once()
->andReturn($mockQb);
$this->repoMap[Repository\Message::class]
->shouldReceive('filterByConversationId')
->once()
->andReturn($mockQb);
$this->repoMap[Repository\Message::class]
->shouldReceive('addReadersToMessages')
->once()
->andReturn($mockQb);
$this->repoMap[Repository\Message::class]
->shouldReceive('fetchPaginatedList')
->with($mockQb, Query::HYDRATE_ARRAY, $query)
->once()
->andReturn($messages);
$this->repoMap[Repository\Message::class]
->shouldReceive('fetchPaginatedCount')
->with($mockQb)
->once()
->andReturn(10);
$this->repoMap[Repository\Conversation::class]
->shouldReceive('fetchById')
->with(1)
->once()
->andReturn($conversation);

foreach ($messages as $message) {
$this->repoMap[Repository\Message::class]
Expand Down Expand Up @@ -101,5 +127,7 @@ public function testHandleQuery()
$this->assertEquals(10, $result['count']);
$this->assertEquals(456, $result['application']['id']);
$this->assertEquals(123, $result['licence']['id']);
$this->assertNotEmpty($result['result'][0]['userMessageReads']);
$this->assertEmpty($result['result'][1]['userMessageReads']);
}
}

0 comments on commit e105ff8

Please sign in to comment.