Skip to content

Commit

Permalink
Added BeforeLoadContentEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
mateuszdebinski committed Jul 25, 2024
1 parent 04c4bac commit a94c6b8
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 3 deletions.
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -62664,3 +62664,8 @@ parameters:
message: "#^Method Ibexa\\\\Tests\\\\Core\\\\Specification\\\\Content\\\\ContentTypeSpecificationTest\\:\\:providerForIsSatisfiedBy\\(\\) return type has no value type specified in iterable type array\\.$#"
count: 1
path: tests/lib/Specification/Content/ContentTypeSpecificationTest.php

-
message: "#^Method Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Events\\\\Content\\\\BeforeLoadContentEvent\\:\\:getContent\\(\\) should return Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Content but returns Ibexa\\\\Contracts\\\\Core\\\\Repository\\\\Values\\\\Content\\\\Content\\|null\\.$#"
count: 1
path: src/contracts/Repository/Events/Content/BeforeLoadContentEvent.php
84 changes: 84 additions & 0 deletions src/contracts/Repository/Events/Content/BeforeLoadContentEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?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\Events\Content;

use Ibexa\Contracts\Core\Repository\Event\BeforeEvent;
use Ibexa\Contracts\Core\Repository\Values\Content\Content;
use UnexpectedValueException;

final class BeforeLoadContentEvent extends BeforeEvent
{
private int $contentId;

/** @var string[]|null */
private ?array $languages;

private ?int $versionNo;

private bool $useAlwaysAvailable;

private ?Content $content = null;

/**
* @param string[] $languages
*/
public function __construct(
int $contentId,
array $languages = null,
?int $versionNo = null,
bool $useAlwaysAvailable = true
) {
$this->contentId = $contentId;
$this->languages = $languages;
$this->versionNo = $versionNo;
$this->useAlwaysAvailable = $useAlwaysAvailable;
}

public function getContentId(): int
{
return $this->contentId;
}

/**
* @return string[]|null
*/
public function getLanguages(): ?array
{
return $this->languages;
}

public function getVersionNo(): ?int
{
return $this->versionNo;
}

public function getUseAlwaysAvailable(): bool
{
return $this->useAlwaysAvailable;
}

public function getContent(): Content
{
if (!$this->hasContent()) {
throw new UnexpectedValueException(sprintf('Return value is not set or not of type %s. Check hasContent() or set it using setContent() before you call the getter.', Content::class));
}

return $this->content;
}

public function setContent(?Content $content): void
{
$this->content = $content;
}

public function hasContent(): bool
{
return $this->content instanceof Content;
}
}
26 changes: 26 additions & 0 deletions src/lib/Event/ContentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeDeleteTranslationEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeDeleteVersionEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeHideContentEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeLoadContentEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforePublishVersionEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeRevealContentEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeUpdateContentEvent;
Expand Down Expand Up @@ -380,6 +381,31 @@ public function revealContent(ContentInfo $contentInfo): void
new RevealContentEvent(...$eventData)
);
}

public function loadContent(
int $contentId,
array $languages = null,
?int $versionNo = null,
bool $useAlwaysAvailable = true
): Content {
$eventData = [
$contentId,
$languages,
$versionNo,
$useAlwaysAvailable,
];

$beforeEvent = new BeforeLoadContentEvent(...$eventData);

$this->eventDispatcher->dispatch($beforeEvent);
if ($beforeEvent->isPropagationStopped()) {
return $beforeEvent->getContent();
}

return $beforeEvent->hasContent()
? $beforeEvent->getContent()
: $this->innerService->loadContent($contentId, $languages, $versionNo, $useAlwaysAvailable);
}
}

class_alias(ContentService::class, 'eZ\Publish\Core\Event\ContentService');
2 changes: 1 addition & 1 deletion src/lib/Persistence/Legacy/Content/Mapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ public function extractContentInfoFromRow(
$contentInfo->id = (int)$row["{$prefix}id"];
$contentInfo->name = (string)$row["{$prefix}name"];
$contentInfo->contentTypeId = (int)$row["{$prefix}contentclass_id"];
$contentInfo->contentTypeIdentifier = $row['content_type_identifier'];
$contentInfo->contentTypeIdentifier = (string)$row['content_type_identifier'];
$contentInfo->sectionId = (int)$row["{$prefix}section_id"];
$contentInfo->currentVersionNo = (int)$row["{$prefix}current_version"];
$contentInfo->ownerId = (int)$row["{$prefix}owner_id"];
Expand Down
7 changes: 5 additions & 2 deletions tests/lib/Event/AbstractServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@

abstract class AbstractServiceTest extends TestCase
{
public function getEventDispatcher(string $beforeEventName, string $eventName): TraceableEventDispatcher
public function getEventDispatcher(string $beforeEventName, ?string $eventName): TraceableEventDispatcher
{
$eventDispatcher = new EventDispatcher();
$eventDispatcher->addListener($beforeEventName, static function (BeforeEvent $event) {});
$eventDispatcher->addListener($eventName, static function (AfterEvent $event) {});
if ($eventName !== null) {
$eventDispatcher->addListener($eventName, static function (AfterEvent $event) {
});
}

return new TraceableEventDispatcher(
$eventDispatcher,
Expand Down
106 changes: 106 additions & 0 deletions tests/lib/Event/ContentServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeDeleteTranslationEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeDeleteVersionEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeHideContentEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeLoadContentEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforePublishVersionEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeRevealContentEvent;
use Ibexa\Contracts\Core\Repository\Events\Content\BeforeUpdateContentEvent;
Expand Down Expand Up @@ -1153,6 +1154,111 @@ public function testRevealContentStopPropagationInBeforeEvents()
[RevealContentEvent::class, 0],
]);
}

public function testLoadContentEvents(): void
{
$traceableEventDispatcher = $this->getEventDispatcher(
BeforeLoadContentEvent::class,
null
);

$parameters = [
2,
[],
null,
true,
];

$content = $this->createMock(Content::class);
$innerServiceMock = $this->createMock(ContentServiceInterface::class);
$innerServiceMock->method('loadContent')->willReturn($content);

$service = new ContentService($innerServiceMock, $traceableEventDispatcher);
$result = $service->loadContent(...$parameters);

$calledListeners = $this->getListenersStack($traceableEventDispatcher->getCalledListeners());

$this->assertSame($content, $result);
$this->assertSame($calledListeners, [
[BeforeLoadContentEvent::class, 0],
]);
$this->assertSame([], $traceableEventDispatcher->getNotCalledListeners());
}

public function testReturnLoadContentResultInBeforeEvents(): void
{
$traceableEventDispatcher = $this->getEventDispatcher(
BeforeLoadContentEvent::class,
null
);

$parameters = [
2,
[],
null,
true,
];

$content = $this->createMock(Content::class);
$eventContent = $this->createMock(Content::class);
$innerServiceMock = $this->createMock(ContentServiceInterface::class);
$innerServiceMock->method('loadContent')->willReturn($content);

$traceableEventDispatcher->addListener(BeforeLoadContentEvent::class, static function (BeforeLoadContentEvent $event) use ($eventContent) {
$event->setContent($eventContent);
}, 10);

$service = new ContentService($innerServiceMock, $traceableEventDispatcher);
$result = $service->loadContent(...$parameters);

$calledListeners = $this->getListenersStack($traceableEventDispatcher->getCalledListeners());

$this->assertSame($eventContent, $result);
$this->assertSame($calledListeners, [
[BeforeLoadContentEvent::class, 10],
[BeforeLoadContentEvent::class, 0],
]);
$this->assertSame([], $traceableEventDispatcher->getNotCalledListeners());
}

public function testLoadContentStopPropagationInBeforeEvents(): void
{
$traceableEventDispatcher = $this->getEventDispatcher(
BeforeLoadContentEvent::class,
null
);

$parameters = [
2,
[],
null,
true,
];

$content = $this->createMock(Content::class);
$eventContent = $this->createMock(Content::class);
$innerServiceMock = $this->createMock(ContentServiceInterface::class);
$innerServiceMock->method('loadContent')->willReturn($content);

$traceableEventDispatcher->addListener(BeforeLoadContentEvent::class, static function (BeforeLoadContentEvent $event) use ($eventContent) {
$event->setContent($eventContent);
$event->stopPropagation();
}, 10);

$service = new ContentService($innerServiceMock, $traceableEventDispatcher);
$result = $service->loadContent(...$parameters);

$calledListeners = $this->getListenersStack($traceableEventDispatcher->getCalledListeners());
$notCalledListeners = $this->getListenersStack($traceableEventDispatcher->getNotCalledListeners());

$this->assertSame($eventContent, $result);
$this->assertSame($calledListeners, [
[BeforeLoadContentEvent::class, 10],
]);
$this->assertSame($notCalledListeners, [
[BeforeLoadContentEvent::class, 0],
]);
}
}

class_alias(ContentServiceTest::class, 'eZ\Publish\Core\Event\Tests\ContentServiceTest');

0 comments on commit a94c6b8

Please sign in to comment.