Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Example] Dispatch domain events for albums #95

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 17 additions & 0 deletions src/Admin/AlbumAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Admin;

use App\Entity\Album;
use Sulu\Bundle\ActivityBundle\Infrastructure\Sulu\Admin\View\ActivityViewBuilderFactoryInterface;
use Sulu\Bundle\AdminBundle\Admin\Admin;
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItem;
use Sulu\Bundle\AdminBundle\Admin\Navigation\NavigationItemCollection;
Expand All @@ -23,13 +24,16 @@ class AlbumAdmin extends Admin
const EDIT_FORM_DETAILS_VIEW = 'app.album.edit_form.details';

private ViewBuilderFactoryInterface $viewBuilderFactory;
private ActivityViewBuilderFactoryInterface $activityViewBuilderFactory;
private SecurityCheckerInterface $securityChecker;

public function __construct(
ViewBuilderFactoryInterface $viewBuilderFactory,
ActivityViewBuilderFactoryInterface $activityViewBuilderFactory,
SecurityCheckerInterface $securityChecker
) {
$this->viewBuilderFactory = $viewBuilderFactory;
$this->activityViewBuilderFactory = $activityViewBuilderFactory;
$this->securityChecker = $securityChecker;
}

Expand Down Expand Up @@ -102,6 +106,7 @@ public function configureViews(ViewCollection $viewCollection): void
$this->viewBuilderFactory->createResourceTabViewBuilder(static::EDIT_FORM_VIEW, '/albums/:id')
->setResourceKey(Album::RESOURCE_KEY)
->setBackView(static::LIST_VIEW)
->setTitleProperty('title')
);

$viewCollection->add(
Expand All @@ -112,6 +117,18 @@ public function configureViews(ViewCollection $viewCollection): void
->addToolbarActions($formToolbarActions)
->setParent(static::EDIT_FORM_VIEW)
);

if ($this->activityViewBuilderFactory->hasActivityListPermission()) {
$viewCollection->add(
$this->activityViewBuilderFactory
->createActivityListViewBuilder(
static::EDIT_FORM_VIEW . '.activity',
'/activity',
Album::RESOURCE_KEY
)
->setParent(static::EDIT_FORM_VIEW)
);
}
}
}

Expand Down
31 changes: 29 additions & 2 deletions src/Controller/Admin/AlbumController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
namespace App\Controller\Admin;

use App\Common\DoctrineListRepresentationFactory;
use App\Domain\Event\AlbumCreatedEvent;
use App\Domain\Event\AlbumModifiedEvent;
use App\Domain\Event\AlbumRemovedEvent;
use App\Entity\Album;
use Doctrine\ORM\EntityManagerInterface;
use FOS\RestBundle\View\ViewHandlerInterface;
use HandcraftedInTheAlps\RestRoutingBundle\Controller\Annotations\RouteResource;
use HandcraftedInTheAlps\RestRoutingBundle\Routing\ClassResourceInterface;
use Sulu\Bundle\ActivityBundle\Application\Collector\DomainEventCollectorInterface;
use Sulu\Bundle\MediaBundle\Media\Manager\MediaManagerInterface;
use Sulu\Component\Rest\AbstractRestController;
use Sulu\Component\Security\SecuredControllerInterface;
Expand All @@ -26,17 +30,20 @@ class AlbumController extends AbstractRestController implements ClassResourceInt
private DoctrineListRepresentationFactory $doctrineListRepresentationFactory;
private EntityManagerInterface $entityManager;
private MediaManagerInterface $mediaManager;
private DomainEventCollectorInterface $domainEventCollector;

public function __construct(
DoctrineListRepresentationFactory $doctrineListRepresentationFactory,
EntityManagerInterface $entityManager,
MediaManagerInterface $mediaManager,
DomainEventCollectorInterface $domainEventCollector,
ViewHandlerInterface $viewHandler,
?TokenStorageInterface $tokenStorage = null
) {
$this->doctrineListRepresentationFactory = $doctrineListRepresentationFactory;
$this->entityManager = $entityManager;
$this->mediaManager = $mediaManager;
$this->domainEventCollector = $domainEventCollector;

parent::__construct($viewHandler, $tokenStorage);
}
Expand All @@ -62,12 +69,19 @@ public function getAction(int $id): Response

public function putAction(Request $request, int $id): Response
{
/** @var Album|null $album */
$album = $this->entityManager->getRepository(Album::class)->find($id);
if (!$album) {
throw new NotFoundHttpException();
}

$this->mapDataToEntity($request->request->all(), $album);
$data = $request->request->all();
$this->mapDataToEntity($data, $album);

$this->domainEventCollector->collect(
new AlbumModifiedEvent($album, $data)
);

$this->entityManager->flush();

return $this->handleView($this->view($album));
Expand All @@ -77,8 +91,14 @@ public function postAction(Request $request): Response
{
$album = new Album();

$this->mapDataToEntity($request->request->all(), $album);
$data = $request->request->all();
$this->mapDataToEntity($data, $album);
$this->entityManager->persist($album);

$this->domainEventCollector->collect(
new AlbumCreatedEvent($album, $data)
);

$this->entityManager->flush();

return $this->handleView($this->view($album, 201));
Expand All @@ -88,7 +108,14 @@ public function deleteAction(int $id): Response
{
/** @var Album $album */
$album = $this->entityManager->getReference(Album::class, $id);
$albumTitle = $album->getTitle();

$this->entityManager->remove($album);

$this->domainEventCollector->collect(
new AlbumRemovedEvent($id, $albumTitle)
);

$this->entityManager->flush();

return $this->handleView($this->view(null, 204));
Expand Down
64 changes: 64 additions & 0 deletions src/Domain/Event/AlbumCreatedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace App\Domain\Event;

use App\Entity\Album;
use Sulu\Bundle\ActivityBundle\Domain\Event\DomainEvent;

class AlbumCreatedEvent extends DomainEvent
{
private Album $album;

/**
* @var mixed[]
*/
private array $payload;

/**
* @param mixed[] $payload
*/
public function __construct(Album $album, array $payload)
{
parent::__construct();

$this->album = $album;
$this->payload = $payload;
}

public function getAlbum(): Album
{
return $this->album;
}

public function getEventPayload(): ?array
{
return $this->payload;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

By configuring sulu_activity.storage.persist_payload to true in config/packages/sulu_activity.yaml, the event payload will be persisted in the database too.

}

public function getEventType(): string
{
return 'created';
}

public function getResourceKey(): string
{
return Album::RESOURCE_KEY;
}

public function getResourceId(): string
{
return (string) $this->album->getId();
}

public function getResourceTitle(): ?string
{
return $this->album->getTitle();
}

public function getResourceSecurityContext(): ?string
{
return Album::SECURITY_CONTEXT;
}
}
64 changes: 64 additions & 0 deletions src/Domain/Event/AlbumModifiedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php

declare(strict_types=1);

namespace App\Domain\Event;

use App\Entity\Album;
use Sulu\Bundle\ActivityBundle\Domain\Event\DomainEvent;

class AlbumModifiedEvent extends DomainEvent
{
private Album $album;

/**
* @var mixed[]
*/
private array $payload;

/**
* @param mixed[] $payload
*/
public function __construct(Album $album, array $payload)
{
parent::__construct();

$this->album = $album;
$this->payload = $payload;
}

public function getAlbum(): Album
{
return $this->album;
}

public function getEventPayload(): ?array
{
return $this->payload;
}

public function getEventType(): string
{
return 'modified';
}

public function getResourceKey(): string
{
return Album::RESOURCE_KEY;
}

public function getResourceId(): string
{
return (string) $this->album->getId();
}

public function getResourceTitle(): ?string
{
return $this->album->getTitle();
}

public function getResourceSecurityContext(): ?string
{
return Album::SECURITY_CONTEXT;
}
}
47 changes: 47 additions & 0 deletions src/Domain/Event/AlbumRemovedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

declare(strict_types=1);

namespace App\Domain\Event;

use App\Entity\Album;
use Sulu\Bundle\ActivityBundle\Domain\Event\DomainEvent;

class AlbumRemovedEvent extends DomainEvent
{
private int $id;
private string $title;

public function __construct(int $id, string $title)
{
parent::__construct();

$this->id = $id;
$this->title = $title;
}

public function getEventType(): string
{
return 'removed';
}

public function getResourceKey(): string
{
return Album::RESOURCE_KEY;
}

public function getResourceId(): string
{
return (string) $this->id;
}

public function getResourceTitle(): ?string
{
return $this->title;
}

public function getResourceSecurityContext(): ?string
{
return Album::SECURITY_CONTEXT;
}
}
5 changes: 4 additions & 1 deletion translations/admin.de.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@
"app.album_selection_label": "{count} {count, plural, =1 {Album} other {Alben}} ausgewählt",
"app.select_albums": "Alben auswählen",
"app.no_album_selected": "Kein Album ausgewählt",
"app.select_album": "Album auswählen"
"app.select_album": "Album auswählen",
"sulu_activity.description.albums.created": "{userFullName} hat das Album \"{resourceTitle}\" erstellt",
"sulu_activity.description.albums.modified": "{userFullName} hat das Album \"{resourceTitle}\" geändert",
"sulu_activity.description.albums.removed": "{userFullName} hat das Album \"{resourceTitle}\" gelöscht"
}
5 changes: 4 additions & 1 deletion translations/admin.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@
"app.album_selection_label": "{count} {count, plural, =1 {album} other {albums}} selected",
"app.select_albums": "Select albums",
"app.no_album_selected": "No album selected",
"app.select_album": "Select album"
"app.select_album": "Select album",
"sulu_activity.description.albums.created": "{userFullName} has created the album \"{resourceTitle}\"",
"sulu_activity.description.albums.modified": "{userFullName} has changed the album \"{resourceTitle}\"",
"sulu_activity.description.albums.removed": "{userFullName} has removed the album \"{resourceTitle}\""
Copy link
Contributor Author

@luca-rath luca-rath Jun 1, 2021

Choose a reason for hiding this comment

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

These translation keys consist of sulu_activity.description as fixed part, the resourceKey (albums) and the eventType (removed).

The available translation parameters can be found here.

To use variables of the context, you have to use context_myVar.

}