Skip to content

Commit 0cbc4ee

Browse files
committed
Merge branch '4.6'
2 parents bb02ea1 + 793ee0e commit 0cbc4ee

File tree

11 files changed

+241
-20
lines changed

11 files changed

+241
-20
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21990,12 +21990,6 @@ parameters:
2199021990
count: 1
2199121991
path: src/lib/Repository/NameSchema/NameSchemaService.php
2199221992

21993-
-
21994-
message: '#^Parameter \#1 \$module of class Ibexa\\Core\\Base\\Exceptions\\UnauthorizedException constructor expects string, int\<min, \-1\>\|int\<1, max\> given\.$#'
21995-
identifier: argument.type
21996-
count: 1
21997-
path: src/lib/Repository/NotificationService.php
21998-
2199921993
-
2200021994
message: '#^Parameter \#2 \$whatIsWrong of class Ibexa\\Core\\Base\\Exceptions\\InvalidArgumentException constructor expects string, int given\.$#'
2200121995
identifier: argument.type

src/contracts/Repository/Decorator/NotificationServiceDecorator.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public function markNotificationAsRead(Notification $notification): void
4040
$this->innerService->markNotificationAsRead($notification);
4141
}
4242

43+
public function markNotificationAsUnread(Notification $notification): void
44+
{
45+
$this->innerService->markNotificationAsUnread($notification);
46+
}
47+
4348
public function getPendingNotificationCount(): int
4449
{
4550
return $this->innerService->getPendingNotificationCount();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Contracts\Core\Repository\Events\Notification;
10+
11+
use Ibexa\Contracts\Core\Repository\Event\BeforeEvent;
12+
use Ibexa\Contracts\Core\Repository\Values\Notification\Notification;
13+
14+
final class BeforeMarkNotificationAsUnreadEvent extends BeforeEvent
15+
{
16+
private Notification $notification;
17+
18+
public function __construct(Notification $notification)
19+
{
20+
$this->notification = $notification;
21+
}
22+
23+
public function getNotification(): Notification
24+
{
25+
return $this->notification;
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Contracts\Core\Repository\Events\Notification;
10+
11+
use Ibexa\Contracts\Core\Repository\Event\AfterEvent;
12+
use Ibexa\Contracts\Core\Repository\Values\Notification\Notification;
13+
14+
final class MarkNotificationAsUnreadEvent extends AfterEvent
15+
{
16+
private Notification $notification;
17+
18+
public function __construct(Notification $notification)
19+
{
20+
$this->notification = $notification;
21+
}
22+
23+
public function getNotification(): Notification
24+
{
25+
return $this->notification;
26+
}
27+
}

src/contracts/Repository/NotificationService.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,14 @@ public function getNotification(int $notificationId): Notification;
4949
*/
5050
public function markNotificationAsRead(Notification $notification): void;
5151

52+
/**
53+
* Marks the given notification as unread so it is shown again as new to the user.
54+
*
55+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
56+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
57+
*/
58+
public function markNotificationAsUnread(Notification $notification): void;
59+
5260
/**
5361
* Get count of unread users notifications.
5462
*

src/lib/Event/NotificationService.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeCreateNotificationEvent;
1313
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeDeleteNotificationEvent;
1414
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeMarkNotificationAsReadEvent;
15+
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeMarkNotificationAsUnreadEvent;
1516
use Ibexa\Contracts\Core\Repository\Events\Notification\CreateNotificationEvent;
1617
use Ibexa\Contracts\Core\Repository\Events\Notification\DeleteNotificationEvent;
1718
use Ibexa\Contracts\Core\Repository\Events\Notification\MarkNotificationAsReadEvent;
19+
use Ibexa\Contracts\Core\Repository\Events\Notification\MarkNotificationAsUnreadEvent;
1820
use Ibexa\Contracts\Core\Repository\NotificationService as NotificationServiceInterface;
1921
use Ibexa\Contracts\Core\Repository\Values\Notification\CreateStruct;
2022
use Ibexa\Contracts\Core\Repository\Values\Notification\Notification;
@@ -52,6 +54,24 @@ public function markNotificationAsRead(Notification $notification): void
5254
);
5355
}
5456

57+
public function markNotificationAsUnread(Notification $notification): void
58+
{
59+
$eventData = [$notification];
60+
61+
$beforeEvent = new BeforeMarkNotificationAsUnreadEvent(...$eventData);
62+
63+
$this->eventDispatcher->dispatch($beforeEvent);
64+
if ($beforeEvent->isPropagationStopped()) {
65+
return;
66+
}
67+
68+
$this->innerService->markNotificationAsUnread($notification);
69+
70+
$this->eventDispatcher->dispatch(
71+
new MarkNotificationAsUnreadEvent(...$eventData)
72+
);
73+
}
74+
5575
public function createNotification(CreateStruct $createStruct): Notification
5676
{
5777
$eventData = [$createStruct];

src/lib/Repository/NotificationService.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ public function markNotificationAsRead(APINotification $notification): void
112112
}
113113

114114
if ($notification->ownerId !== $currentUserId) {
115-
throw new UnauthorizedException($notification->id, 'Notification');
115+
throw new UnauthorizedException('notification', 'update', ['id' => $notification->id]);
116116
}
117117

118118
if (!$notification->isPending) {
@@ -125,6 +125,28 @@ public function markNotificationAsRead(APINotification $notification): void
125125
$this->persistenceHandler->updateNotification($notification, $updateStruct);
126126
}
127127

128+
public function markNotificationAsUnread(APINotification $notification): void
129+
{
130+
$currentUserId = $this->getCurrentUserId();
131+
132+
if (!$notification->id) {
133+
throw new NotFoundException('Notification', $notification->id);
134+
}
135+
136+
if ($notification->ownerId !== $currentUserId) {
137+
throw new UnauthorizedException('notification', 'update', ['id' => $notification->id]);
138+
}
139+
140+
if ($notification->isPending) {
141+
return;
142+
}
143+
144+
$updateStruct = new UpdateStruct();
145+
$updateStruct->isPending = true;
146+
147+
$this->persistenceHandler->updateNotification($notification, $updateStruct);
148+
}
149+
128150
/**
129151
* {@inheritdoc}
130152
*/

src/lib/Repository/SiteAccessAware/NotificationService.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ public function markNotificationAsRead(Notification $notification): void
6262
$this->service->markNotificationAsRead($notification);
6363
}
6464

65+
public function markNotificationAsUnread(Notification $notification): void
66+
{
67+
$this->service->markNotificationAsUnread($notification);
68+
}
69+
6570
/**
6671
* Get count of unread users notifications.
6772
*

tests/integration/Core/Repository/NotificationServiceTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,28 @@ public function testMarkNotificationAsRead()
7777
self::assertFalse($notification->isPending);
7878
}
7979

80+
/**
81+
* @covers \Ibexa\Contracts\Core\Repository\NotificationService::markNotificationAsUnread()
82+
*/
83+
public function testMarkNotificationAsUnread(): void
84+
{
85+
$repository = $this->getRepository();
86+
87+
$notificationId = $this->generateId('notification', 5);
88+
$notificationService = $repository->getNotificationService();
89+
90+
$notification = $notificationService->getNotification($notificationId);
91+
$notificationService->markNotificationAsRead($notification);
92+
93+
$notification = $notificationService->getNotification($notificationId);
94+
self::assertFalse($notification->isPending);
95+
96+
$notificationService->markNotificationAsUnread($notification);
97+
$notification = $notificationService->getNotification($notificationId);
98+
99+
self::assertTrue($notification->isPending);
100+
}
101+
80102
/**
81103
* @covers \Ibexa\Contracts\Core\Repository\NotificationService::getPendingNotificationCount()
82104
*/

tests/lib/Event/NotificationServiceTest.php

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeCreateNotificationEvent;
1111
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeDeleteNotificationEvent;
1212
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeMarkNotificationAsReadEvent;
13+
use Ibexa\Contracts\Core\Repository\Events\Notification\BeforeMarkNotificationAsUnreadEvent;
1314
use Ibexa\Contracts\Core\Repository\Events\Notification\CreateNotificationEvent;
1415
use Ibexa\Contracts\Core\Repository\Events\Notification\DeleteNotificationEvent;
1516
use Ibexa\Contracts\Core\Repository\Events\Notification\MarkNotificationAsReadEvent;
17+
use Ibexa\Contracts\Core\Repository\Events\Notification\MarkNotificationAsUnreadEvent;
1618
use Ibexa\Contracts\Core\Repository\NotificationService as NotificationServiceInterface;
1719
use Ibexa\Contracts\Core\Repository\Values\Notification\CreateStruct;
1820
use Ibexa\Contracts\Core\Repository\Values\Notification\Notification;
@@ -64,9 +66,13 @@ public function testReturnCreateNotificationResultInBeforeEvents()
6466
$innerServiceMock = $this->createMock(NotificationServiceInterface::class);
6567
$innerServiceMock->method('createNotification')->willReturn($notification);
6668

67-
$traceableEventDispatcher->addListener(BeforeCreateNotificationEvent::class, static function (BeforeCreateNotificationEvent $event) use ($eventNotification) {
68-
$event->setNotification($eventNotification);
69-
}, 10);
69+
$traceableEventDispatcher->addListener(
70+
BeforeCreateNotificationEvent::class,
71+
static function (BeforeCreateNotificationEvent $event) use ($eventNotification): void {
72+
$event->setNotification($eventNotification);
73+
},
74+
10
75+
);
7076

7177
$service = new NotificationService($innerServiceMock, $traceableEventDispatcher);
7278
$result = $service->createNotification(...$parameters);
@@ -98,10 +104,14 @@ public function testCreateNotificationStopPropagationInBeforeEvents()
98104
$innerServiceMock = $this->createMock(NotificationServiceInterface::class);
99105
$innerServiceMock->method('createNotification')->willReturn($notification);
100106

101-
$traceableEventDispatcher->addListener(BeforeCreateNotificationEvent::class, static function (BeforeCreateNotificationEvent $event) use ($eventNotification) {
102-
$event->setNotification($eventNotification);
103-
$event->stopPropagation();
104-
}, 10);
107+
$traceableEventDispatcher->addListener(
108+
BeforeCreateNotificationEvent::class,
109+
static function (BeforeCreateNotificationEvent $event) use ($eventNotification): void {
110+
$event->setNotification($eventNotification);
111+
$event->stopPropagation();
112+
},
113+
10
114+
);
105115

106116
$service = new NotificationService($innerServiceMock, $traceableEventDispatcher);
107117
$result = $service->createNotification(...$parameters);
@@ -157,9 +167,13 @@ public function testDeleteNotificationStopPropagationInBeforeEvents()
157167

158168
$innerServiceMock = $this->createMock(NotificationServiceInterface::class);
159169

160-
$traceableEventDispatcher->addListener(BeforeDeleteNotificationEvent::class, static function (BeforeDeleteNotificationEvent $event) {
161-
$event->stopPropagation();
162-
}, 10);
170+
$traceableEventDispatcher->addListener(
171+
BeforeDeleteNotificationEvent::class,
172+
static function (BeforeDeleteNotificationEvent $event): void {
173+
$event->stopPropagation();
174+
},
175+
10
176+
);
163177

164178
$service = new NotificationService($innerServiceMock, $traceableEventDispatcher);
165179
$service->deleteNotification(...$parameters);
@@ -201,6 +215,31 @@ public function testMarkNotificationAsReadEvents()
201215
self::assertSame([], $traceableEventDispatcher->getNotCalledListeners());
202216
}
203217

218+
public function testMarkNotificationAsUnreadEvents(): void
219+
{
220+
$traceableEventDispatcher = $this->getEventDispatcher(
221+
BeforeMarkNotificationAsUnreadEvent::class,
222+
MarkNotificationAsUnreadEvent::class
223+
);
224+
225+
$parameters = [
226+
$this->createMock(Notification::class),
227+
];
228+
229+
$innerServiceMock = $this->createMock(NotificationServiceInterface::class);
230+
231+
$service = new NotificationService($innerServiceMock, $traceableEventDispatcher);
232+
$service->markNotificationAsUnread(...$parameters);
233+
234+
$calledListeners = $this->getListenersStack($traceableEventDispatcher->getCalledListeners());
235+
236+
self::assertSame($calledListeners, [
237+
[BeforeMarkNotificationAsUnreadEvent::class, 0],
238+
[MarkNotificationAsUnreadEvent::class, 0],
239+
]);
240+
self::assertSame([], $traceableEventDispatcher->getNotCalledListeners());
241+
}
242+
204243
public function testMarkNotificationAsReadStopPropagationInBeforeEvents()
205244
{
206245
$traceableEventDispatcher = $this->getEventDispatcher(
@@ -214,9 +253,13 @@ public function testMarkNotificationAsReadStopPropagationInBeforeEvents()
214253

215254
$innerServiceMock = $this->createMock(NotificationServiceInterface::class);
216255

217-
$traceableEventDispatcher->addListener(BeforeMarkNotificationAsReadEvent::class, static function (BeforeMarkNotificationAsReadEvent $event) {
218-
$event->stopPropagation();
219-
}, 10);
256+
$traceableEventDispatcher->addListener(
257+
BeforeMarkNotificationAsReadEvent::class,
258+
static function (BeforeMarkNotificationAsReadEvent $event): void {
259+
$event->stopPropagation();
260+
},
261+
10
262+
);
220263

221264
$service = new NotificationService($innerServiceMock, $traceableEventDispatcher);
222265
$service->markNotificationAsRead(...$parameters);
@@ -232,4 +275,40 @@ public function testMarkNotificationAsReadStopPropagationInBeforeEvents()
232275
[MarkNotificationAsReadEvent::class, 0],
233276
]);
234277
}
278+
279+
public function testMarkNotificationAsUnreadStopPropagationInBeforeEvents(): void
280+
{
281+
$traceableEventDispatcher = $this->getEventDispatcher(
282+
BeforeMarkNotificationAsUnreadEvent::class,
283+
MarkNotificationAsUnreadEvent::class
284+
);
285+
286+
$parameters = [
287+
$this->createMock(Notification::class),
288+
];
289+
290+
$innerServiceMock = $this->createMock(NotificationServiceInterface::class);
291+
292+
$traceableEventDispatcher->addListener(
293+
BeforeMarkNotificationAsUnreadEvent::class,
294+
static function (BeforeMarkNotificationAsUnreadEvent $event): void {
295+
$event->stopPropagation();
296+
},
297+
10
298+
);
299+
300+
$service = new NotificationService($innerServiceMock, $traceableEventDispatcher);
301+
$service->markNotificationAsUnread(...$parameters);
302+
303+
$calledListeners = $this->getListenersStack($traceableEventDispatcher->getCalledListeners());
304+
$notCalledListeners = $this->getListenersStack($traceableEventDispatcher->getNotCalledListeners());
305+
306+
self::assertSame($calledListeners, [
307+
[BeforeMarkNotificationAsUnreadEvent::class, 10],
308+
]);
309+
self::assertSame($notCalledListeners, [
310+
[BeforeMarkNotificationAsUnreadEvent::class, 0],
311+
[MarkNotificationAsUnreadEvent::class, 0],
312+
]);
313+
}
235314
}

0 commit comments

Comments
 (0)