Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
8bd2a39
IBX-9060: Added $query parameter for filtering notifications count an…
tbialcz Apr 3, 2025
b1370e9
Merge branch '4.6' into ibx_9060-notification-filtering
tbialcz Apr 10, 2025
49c4ec0
IBX-9060: Fixed code style
tbialcz Apr 10, 2025
b5a96d8
IBX-9060: Implemented notification query logic: added NotificationQue…
tbialcz May 8, 2025
dc978aa
Merge branch '4.6' into ibx_9060-notification-filtering
tbialcz May 8, 2025
8f0c65b
Merge branch '4.6' into ibx_9060-notification-filtering
tbialcz May 20, 2025
852c013
IBX-9060: Refactored notification loading logic by splitting `loadNot…
tbialcz Jun 10, 2025
626debe
IBX-9060: Refactored notification filtering with criterion handlers, …
tbialcz Jun 10, 2025
70061b3
IBX-9060: Replaced `Criterion` abstract class with `CriterionInterfac…
tbialcz Jun 10, 2025
f722a69
IBX-9060: Replaced `Criterion` abstract class with `CriterionInterfac…
tbialcz Jun 10, 2025
9a12a9d
Merge remote-tracking branch 'origin/ibx_9060-notification-filtering'…
tbialcz Jun 11, 2025
dac3c1d
IBX-9060: Optimized notification count caching logic by avoiding unne…
tbialcz Jun 20, 2025
2b79cf5
IBX-9060: Refactored `NotificationQuery` namespace, improved encapsul…
tbialcz Jun 20, 2025
00c0c64
IBX-9060: Fixed issues after code review
tbialcz Jun 23, 2025
8b26279
IBX-9060: Added `ibexa/polyfill-php82` dependency and utilized `itera…
tbialcz Jun 23, 2025
3b687a0
IBX-9060: Simplified resource path in legacy notification service con…
tbialcz Jun 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 1 addition & 151 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -22734,18 +22734,6 @@ parameters:
count: 1
path: src/lib/Persistence/Legacy/Notification/Gateway.php

-
message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Notification\\Gateway\:\:loadUserNotifications\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: src/lib/Persistence/Legacy/Notification/Gateway.php

-
message: '#^Cannot call method fetchAll\(\) on Doctrine\\DBAL\\ForwardCompatibility\\Result\|int\|string\.$#'
identifier: method.nonObject
count: 2
path: src/lib/Persistence/Legacy/Notification/Gateway/DoctrineDatabase.php

-
message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Notification\\Gateway\\DoctrineDatabase\:\:getColumns\(\) return type has no value type specified in iterable type array\.$#'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tbialcz I'm coming a bit late to the party, but the issues in new code need to be resolved instead of being added to the baseline.

identifier: missingType.iterableValue
Expand All @@ -22758,12 +22746,6 @@ parameters:
count: 1
path: src/lib/Persistence/Legacy/Notification/Gateway/DoctrineDatabase.php

-
message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Notification\\Gateway\\DoctrineDatabase\:\:loadUserNotifications\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: src/lib/Persistence/Legacy/Notification/Gateway/DoctrineDatabase.php

-
message: '#^Property Ibexa\\Contracts\\Core\\Persistence\\Notification\\Notification\:\:\$id \(int\) in isset\(\) is not nullable\.$#'
identifier: isset.property
Expand All @@ -22788,12 +22770,6 @@ parameters:
count: 1
path: src/lib/Persistence/Legacy/Notification/Gateway/ExceptionConversion.php

-
message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Notification\\Gateway\\ExceptionConversion\:\:loadUserNotifications\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: src/lib/Persistence/Legacy/Notification/Gateway/ExceptionConversion.php

-
message: '#^Method Ibexa\\Core\\Persistence\\Legacy\\Notification\\Mapper\:\:extractNotificationFromRow\(\) has parameter \$row with no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
Expand Down Expand Up @@ -42486,72 +42462,6 @@ parameters:
count: 2
path: tests/integration/Core/Repository/NonRedundantFieldSetTest.php

-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Notification\\\\Notification'' and Ibexa\\Contracts\\Core\\Repository\\Values\\Notification\\Notification will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 2
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Notification\\\\NotificationList'' and Ibexa\\Contracts\\Core\\Repository\\Values\\Notification\\NotificationList will always evaluate to true\.$#'
identifier: method.alreadyNarrowedType
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testCreateNotification\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testCreateNotificationThrowsInvalidArgumentExceptionOnMissingOwner\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testCreateNotificationThrowsInvalidArgumentExceptionOnMissingType\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testDeleteNotification\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testGetNotification\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testGetNotificationCount\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testGetPendingNotificationCount\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testLoadNotifications\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\NotificationServiceTest\:\:testMarkNotificationAsRead\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/integration/Core/Repository/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Integration\\Core\\Repository\\ObjectStateServiceAuthorizationTest\:\:testCreateObjectStateGroupThrowsUnauthorizedException\(\) has no return type specified\.$#'
identifier: missingType.return
Expand Down Expand Up @@ -50364,48 +50274,6 @@ parameters:
count: 1
path: tests/lib/Event/LocationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\NotificationServiceTest\:\:testCreateNotificationEvents\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Event/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\NotificationServiceTest\:\:testCreateNotificationStopPropagationInBeforeEvents\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Event/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\NotificationServiceTest\:\:testDeleteNotificationEvents\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Event/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\NotificationServiceTest\:\:testDeleteNotificationStopPropagationInBeforeEvents\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Event/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\NotificationServiceTest\:\:testMarkNotificationAsReadEvents\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Event/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\NotificationServiceTest\:\:testMarkNotificationAsReadStopPropagationInBeforeEvents\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Event/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\NotificationServiceTest\:\:testReturnCreateNotificationResultInBeforeEvents\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Event/NotificationServiceTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Event\\ObjectStateServiceTest\:\:testCreateObjectStateEvents\(\) has no return type specified\.$#'
identifier: missingType.return
Expand Down Expand Up @@ -67236,12 +67104,6 @@ parameters:
count: 1
path: tests/lib/Persistence/Legacy/Notification/Gateway/DoctrineDatabaseTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Persistence\\Legacy\\Notification\\Gateway\\DoctrineDatabaseTest\:\:testLoadUserNotifications\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Persistence/Legacy/Notification/Gateway/DoctrineDatabaseTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Persistence\\Legacy\\Notification\\Gateway\\DoctrineDatabaseTest\:\:testUpdateNotification\(\) has no return type specified\.$#'
identifier: missingType.return
Expand Down Expand Up @@ -67278,12 +67140,6 @@ parameters:
count: 1
path: tests/lib/Persistence/Legacy/Notification/HandlerTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Persistence\\Legacy\\Notification\\HandlerTest\:\:testLoadUserNotifications\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Persistence/Legacy/Notification/HandlerTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Persistence\\Legacy\\Notification\\HandlerTest\:\:testUpdateNotification\(\) has no return type specified\.$#'
identifier: missingType.return
Expand Down Expand Up @@ -69144,20 +69000,14 @@ parameters:
count: 1
path: tests/lib/Repository/Decorator/NotificationServiceDecoratorTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Repository\\Decorator\\NotificationServiceDecoratorTest\:\:testLoadNotificationsDecorator\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Repository/Decorator/NotificationServiceDecoratorTest.php

-
message: '#^Method Ibexa\\Tests\\Core\\Repository\\Decorator\\NotificationServiceDecoratorTest\:\:testMarkNotificationAsReadDecorator\(\) has no return type specified\.$#'
identifier: missingType.return
count: 1
path: tests/lib/Repository/Decorator/NotificationServiceDecoratorTest.php

-
message: '#^Parameter \#1 \$innerService of class Ibexa\\Contracts\\Core\\Repository\\Decorator\\NotificationServiceDecorator@anonymous/tests/lib/Repository/Decorator/NotificationServiceDecoratorTest\.php\:22 constructor expects Ibexa\\Contracts\\Core\\Repository\\NotificationService, PHPUnit\\Framework\\MockObject\\MockObject given\.$#'
message: '#^Parameter \#1 \$innerService of class Ibexa\\Contracts\\Core\\Repository\\Decorator\\NotificationServiceDecorator@anonymous/tests/lib/Repository/Decorator/NotificationServiceDecoratorTest\.php\:.* constructor expects Ibexa\\Contracts\\Core\\Repository\\NotificationService, PHPUnit\\Framework\\MockObject\\MockObject given\.$#'
identifier: argument.type
count: 1
path: tests/lib/Repository/Decorator/NotificationServiceDecoratorTest.php
Expand Down
13 changes: 5 additions & 8 deletions src/contracts/Persistence/Notification/Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace Ibexa\Contracts\Core\Persistence\Notification;

use Ibexa\Contracts\Core\Repository\Values\Notification\Notification as APINotification;
use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\NotificationQuery;

interface Handler
{
Expand Down Expand Up @@ -51,20 +52,16 @@ public function countPendingNotifications(int $ownerId): int;
public function getNotificationById(int $notificationId): Notification;

/**
* @param int $userId
* @param int $offset
* @param int $limit
*
* @return \Ibexa\Contracts\Core\Persistence\Notification\Notification[]
*/
public function loadUserNotifications(int $userId, int $offset, int $limit): array;

/**
* @param int $currentUserId
*
* @return int
* @return \Ibexa\Contracts\Core\Persistence\Notification\Notification[]
*/
public function countNotifications(int $currentUserId): int;
public function findUserNotifications(int $userId, ?NotificationQuery $query = null): array;

public function countNotifications(int $currentUserId, ?NotificationQuery $query = null): int;

/**
* @param \Ibexa\Contracts\Core\Repository\Values\Notification\Notification $notification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Ibexa\Contracts\Core\Repository\Values\Notification\CreateStruct;
use Ibexa\Contracts\Core\Repository\Values\Notification\Notification;
use Ibexa\Contracts\Core\Repository\Values\Notification\NotificationList;
use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\NotificationQuery;

abstract class NotificationServiceDecorator implements NotificationService
{
Expand All @@ -30,6 +31,11 @@ public function loadNotifications(
return $this->innerService->loadNotifications($offset, $limit);
}

public function findNotifications(?NotificationQuery $query = null): NotificationList
{
return $this->innerService->findNotifications($query);
}

public function getNotification(int $notificationId): Notification
{
return $this->innerService->getNotification($notificationId);
Expand All @@ -50,9 +56,9 @@ public function getPendingNotificationCount(): int
return $this->innerService->getPendingNotificationCount();
}

public function getNotificationCount(): int
public function getNotificationCount(?NotificationQuery $query = null): int
{
return $this->innerService->getNotificationCount();
return $this->innerService->getNotificationCount($query);
}

public function createNotification(CreateStruct $createStruct): Notification
Expand Down
18 changes: 4 additions & 14 deletions src/contracts/Repository/NotificationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,18 @@
use Ibexa\Contracts\Core\Repository\Values\Notification\CreateStruct;
use Ibexa\Contracts\Core\Repository\Values\Notification\Notification;
use Ibexa\Contracts\Core\Repository\Values\Notification\NotificationList;
use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\NotificationQuery;

/**
* Service to manager user notifications. It works in the context of a current User (obtained from
* the PermissionResolver).
*/
interface NotificationService
{
/**
* Get currently logged user notifications.
*
* @param int $offset the start offset for paging
* @param int $limit the number of notifications returned
*
* @return \Ibexa\Contracts\Core\Repository\Values\Notification\NotificationList
*/
public function loadNotifications(int $offset, int $limit): NotificationList;

public function findNotifications(?NotificationQuery $query = null): NotificationList;

/**
* Load single notification (by ID).
*
Expand Down Expand Up @@ -64,12 +59,7 @@ public function markNotificationAsUnread(Notification $notification): void;
*/
public function getPendingNotificationCount(): int;

/**
* Get count of total users notifications.
*
* @return int
*/
public function getNotificationCount(): int;
public function getNotificationCount(?NotificationQuery $query = null): int;

/**
* Creates a new notification.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Repository\Values\Notification;

use Doctrine\DBAL\Query\QueryBuilder;
use Ibexa\Contracts\Core\Repository\Values\Notification\Query\CriterionInterface;

interface CriterionHandlerInterface
{
public function supports(CriterionInterface $criterion): bool;

public function apply(QueryBuilder $qb, CriterionInterface $criterion): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion;

use DateTimeInterface;
use Ibexa\Contracts\Core\Repository\Values\Notification\Query\CriterionInterface;

final class DateCreated implements CriterionInterface
{
public ?DateTimeInterface $from;

public ?DateTimeInterface $to;

public function __construct(?DateTimeInterface $from = null, ?DateTimeInterface $to = null)
{
$this->from = $from;
$this->to = $to;
}
}
Loading
Loading