Skip to content

Commit

Permalink
EZP-30029: As a Developer I'd like API for bulk loading Content Info …
Browse files Browse the repository at this point in the history
…Items (ezsystems#2529)
  • Loading branch information
andrerom committed Feb 19, 2019
1 parent 6c3e1a9 commit f2dfe9c
Show file tree
Hide file tree
Showing 11 changed files with 151 additions and 26 deletions.
11 changes: 11 additions & 0 deletions eZ/Publish/API/Repository/ContentService.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ interface ContentService
*/ */
public function loadContentInfo($contentId); public function loadContentInfo($contentId);


/**
* Bulk-load ContentInfo items by id's.
*
* Note: It does not throw exceptions on load, just skips erroneous (NotFound or Unauthorized) ContentInfo items.
*
* @param int[] $contentIds
*
* @return \eZ\Publish\API\Repository\Values\Content\ContentInfo[] list of ContentInfo with Content Ids as keys
*/
public function loadContentInfoList(array $contentIds): iterable;

/** /**
* Loads a content info object for the given remoteId. * Loads a content info object for the given remoteId.
* *
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -139,6 +139,24 @@ public function testSudo()
); );
} }


/**
* Test for the loadContentInfoList() method.
*
* @see \eZ\Publish\API\Repository\ContentService::loadContentInfoList()
* @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testLoadContentInfoList
*/
public function testLoadContentInfoListSkipsUnauthorizedItems()
{
$repository = $this->getRepository();
$contentId = $this->generateId('object', 10);
$contentService = $repository->getContentService();
$repository->setCurrentUser($this->createAnonymousWithEditorRole());

$list = $contentService->loadContentInfoList([$contentId]);

$this->assertCount(0, $list);
}

/** /**
* Test for the loadContentInfoByRemoteId() method. * Test for the loadContentInfoByRemoteId() method.
* *
Expand Down
38 changes: 38 additions & 0 deletions eZ/Publish/API/Repository/Tests/ContentServiceTest.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -571,6 +571,44 @@ public function testLoadContentInfoThrowsNotFoundException()
/* END: Use Case */ /* END: Use Case */
} }


/**
* Test for the loadContentInfoList() method.
*
* @see \eZ\Publish\API\Repository\ContentService::loadContentInfoList()
*/
public function testLoadContentInfoList()
{
$repository = $this->getRepository();

$mediaFolderId = $this->generateId('object', 41);
$contentService = $repository->getContentService();
$list = $contentService->loadContentInfoList([$mediaFolderId]);

$this->assertCount(1, $list);
$this->assertEquals([$mediaFolderId], array_keys($list), 'Array key was not content id');
$this->assertInstanceOf(
ContentInfo::class,
$list[$mediaFolderId]
);
}

/**
* Test for the loadContentInfoList() method.
*
* @see \eZ\Publish\API\Repository\ContentService::loadContentInfoList()
* @depends testLoadContentInfoList
*/
public function testLoadContentInfoListSkipsNotFoundItems()
{
$repository = $this->getRepository();

$nonExistentContentId = $this->generateId('object', self::DB_INT_MAX);
$contentService = $repository->getContentService();
$list = $contentService->loadContentInfoList([$nonExistentContentId]);

$this->assertCount(0, $list);
}

/** /**
* Test for the loadContentInfoByRemoteId() method. * Test for the loadContentInfoByRemoteId() method.
* *
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
namespace eZ\Publish\Core\MVC\Symfony\FieldType\RelationList; namespace eZ\Publish\Core\MVC\Symfony\FieldType\RelationList;


use eZ\Publish\API\Repository\ContentService; use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use eZ\Publish\API\Repository\Values\Content\Field; use eZ\Publish\API\Repository\Values\Content\Field;
use eZ\Publish\Core\MVC\Symfony\FieldType\View\ParameterProviderInterface; use eZ\Publish\Core\MVC\Symfony\FieldType\View\ParameterProviderInterface;


Expand Down Expand Up @@ -34,18 +32,18 @@ public function __construct(ContentService $contentService)
*/ */
public function getViewParameters(Field $field) public function getViewParameters(Field $field)
{ {
$available = []; $ids = $field->value->destinationContentIds;

$list = $this->contentService->loadContentInfoList($ids);
foreach ($field->value->destinationContentIds as $contentId) {
try { // Start by setting missing ids as false on $available
$contentInfo = $this->contentService->loadContentInfo($contentId); $available = array_fill_keys(

array_diff($ids, array_keys($list)),
$available[$contentId] = !$contentInfo->isTrashed(); false
} catch (NotFoundException $exception) { );
$available[$contentId] = false;
} catch (UnauthorizedException $exception) { // Check if loaded items are in trash or not, for availability
$available[$contentId] = false; foreach ($list as $contentId => $contentInfo) {
} $available[$contentId] = !$contentInfo->isTrashed();
} }


return [ return [
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
use eZ\Publish\API\Repository\ContentService; use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\API\Repository\Values\Content\ContentInfo; use eZ\Publish\API\Repository\Values\Content\ContentInfo;
use eZ\Publish\API\Repository\Values\Content\Field; use eZ\Publish\API\Repository\Values\Content\Field;
use eZ\Publish\Core\Base\Exceptions\NotFoundException;
use eZ\Publish\Core\Base\Exceptions\UnauthorizedException;
use eZ\Publish\Core\FieldType\RelationList\Value; use eZ\Publish\Core\FieldType\RelationList\Value;
use eZ\Publish\Core\MVC\Symfony\FieldType\RelationList\ParameterProvider; use eZ\Publish\Core\MVC\Symfony\FieldType\RelationList\ParameterProvider;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
Expand All @@ -30,12 +28,24 @@ public function testGetViewParameters(array $desinationContentIds, array $expect
{ {
$contentServiceMock = $this->createMock(ContentService::class); $contentServiceMock = $this->createMock(ContentService::class);
$contentServiceMock $contentServiceMock
->method('loadContentInfo') ->method('loadContentInfoList')
->will(TestCase::returnValueMap([ ->with($desinationContentIds)
[123, new ContentInfo(['status' => ContentInfo::STATUS_DRAFT])], ->will($this->returnCallback(function ($arg) {
[456, new ContentInfo(['status' => ContentInfo::STATUS_PUBLISHED])], $return = [];
[789, new ContentInfo(['status' => ContentInfo::STATUS_TRASHED])], if (in_array(123, $arg)) {
])); $return[123] = new ContentInfo(['status' => ContentInfo::STATUS_DRAFT]);
}

if (in_array(456, $arg)) {
$return[456] = new ContentInfo(['status' => ContentInfo::STATUS_PUBLISHED]);
}

if (in_array(789, $arg)) {
$return[789] = new ContentInfo(['status' => ContentInfo::STATUS_TRASHED]);
}

return $return;
}));


$parameterProvider = new ParameterProvider($contentServiceMock); $parameterProvider = new ParameterProvider($contentServiceMock);
$parameters = $parameterProvider->getViewParameters(new Field([ $parameters = $parameterProvider->getViewParameters(new Field([
Expand All @@ -51,8 +61,9 @@ public function testNotFoundGetViewParameters()


$contentServiceMock = $this->createMock(ContentService::class); $contentServiceMock = $this->createMock(ContentService::class);
$contentServiceMock $contentServiceMock
->method('loadContentInfo') ->method('loadContentInfoList')
->will(TestCase::throwException(new NotFoundException('ContentInfo', $contentId))); ->with([$contentId])
->willReturn([]);


$parameterProvider = new ParameterProvider($contentServiceMock); $parameterProvider = new ParameterProvider($contentServiceMock);
$parameters = $parameterProvider->getViewParameters(new Field([ $parameters = $parameterProvider->getViewParameters(new Field([
Expand All @@ -68,8 +79,9 @@ public function testUnauthorizedGetViewParameters()


$contentServiceMock = $this->createMock(ContentService::class); $contentServiceMock = $this->createMock(ContentService::class);
$contentServiceMock $contentServiceMock
->method('loadContentInfo') ->method('loadContentInfoList')
->will(TestCase::throwException(new UnauthorizedException('content', 'read'))); ->with([$contentId])
->willReturn([]);


$parameterProvider = new ParameterProvider($contentServiceMock); $parameterProvider = new ParameterProvider($contentServiceMock);
$parameters = $parameterProvider->getViewParameters(new Field([ $parameters = $parameterProvider->getViewParameters(new Field([
Expand Down
8 changes: 8 additions & 0 deletions eZ/Publish/Core/REST/Client/ContentService.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ public function loadContentInfo($contentId)
return $this->completeContentInfo($restContentInfo); return $this->completeContentInfo($restContentInfo);
} }


/**
* {@inheritdoc}
*/
public function loadContentInfoList(array $contentIds): iterable
{
throw new \Exception('@todo: Implement.');
}

/** /**
* Loads a content info object for the given remoteId. * Loads a content info object for the given remoteId.
* *
Expand Down
17 changes: 17 additions & 0 deletions eZ/Publish/Core/Repository/ContentService.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -139,6 +139,23 @@ public function loadContentInfo($contentId)
return $contentInfo; return $contentInfo;
} }


/**
* {@inheritdoc}
*/
public function loadContentInfoList(array $contentIds): iterable
{
$contentInfoList = [];
$spiInfoList = $this->persistenceHandler->contentHandler()->loadContentInfoList($contentIds);
foreach ($spiInfoList as $id => $spiInfo) {
$contentInfo = $this->domainMapper->buildContentInfoDomainObject($spiInfo);
if ($this->repository->canUser('content', 'read', $contentInfo)) {
$contentInfoList[$id] = $contentInfo;
}
}

return $contentInfoList;
}

/** /**
* Loads a content info object. * Loads a content info object.
* *
Expand Down
8 changes: 8 additions & 0 deletions eZ/Publish/Core/Repository/SiteAccessAware/ContentService.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ public function loadContentInfo($contentId)
return $this->service->loadContentInfo($contentId); return $this->service->loadContentInfo($contentId);
} }


/**
* {@inheritdoc}
*/
public function loadContentInfoList(array $contentIds): iterable
{
return $this->service->loadContentInfoList($contentIds);
}

public function loadContentInfoByRemoteId($remoteId) public function loadContentInfoByRemoteId($remoteId)
{ {
return $this->service->loadContentInfoByRemoteId($remoteId); return $this->service->loadContentInfoByRemoteId($remoteId);
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public function providerForPassTroughMethods()
// string $method, array $arguments, bool $return = true // string $method, array $arguments, bool $return = true
return [ return [
['loadContentInfo', [42]], ['loadContentInfo', [42]],
['loadContentInfoList', [[42]], [$contentInfo]],


['loadContentInfoByRemoteId', ['f348tj4gorgji4']], ['loadContentInfoByRemoteId', ['f348tj4gorgji4']],


Expand Down
8 changes: 8 additions & 0 deletions eZ/Publish/Core/SignalSlot/ContentService.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ public function loadContentInfo($contentId)
return $this->service->loadContentInfo($contentId); return $this->service->loadContentInfo($contentId);
} }


/**
* {@inheritdoc}
*/
public function loadContentInfoList(array $contentIds): iterable
{
return $this->service->loadContentInfoList($contentIds);
}

/** /**
* Loads a content info object for the given remoteId. * Loads a content info object for the given remoteId.
* *
Expand Down
6 changes: 6 additions & 0 deletions eZ/Publish/Core/SignalSlot/Tests/ContentServiceTest.php
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ public function serviceProvider()
$contentInfo, $contentInfo,
0, 0,
), ),
array(
'loadContentInfoList',
array(array($contentId)),
[$contentInfo],
0,
),
array( array(
'loadContentInfoByRemoteId', 'loadContentInfoByRemoteId',
array($remoteId), array($remoteId),
Expand Down

0 comments on commit f2dfe9c

Please sign in to comment.