Skip to content

Commit d54ba64

Browse files
barw4alongosz
authored andcommitted
Merge branch '1.3' of ezsystems/ezplatform-rest into 4.4
2 parents 7968db7 + b9ca4c2 commit d54ba64

File tree

2 files changed

+185
-15
lines changed

2 files changed

+185
-15
lines changed

src/lib/Server/Output/ValueObjectVisitor/Location.php

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
namespace Ibexa\Rest\Server\Output\ValueObjectVisitor;
88

99
use Ibexa\Contracts\Core\Repository\ContentService;
10+
use Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException;
1011
use Ibexa\Contracts\Core\Repository\LocationService;
11-
use Ibexa\Contracts\Core\Repository\Values\Content\Location as LocationValue;
12+
use Ibexa\Contracts\Core\Repository\Values\Content;
1213
use Ibexa\Contracts\Rest\Output\Generator;
1314
use Ibexa\Contracts\Rest\Output\ValueObjectVisitor;
1415
use Ibexa\Contracts\Rest\Output\Visitor;
15-
use Ibexa\Core\Base\Exceptions\UnauthorizedException;
1616
use Ibexa\Rest\Server\Values\RestContent as RestContentValue;
1717

1818
/**
@@ -26,8 +26,10 @@ class Location extends ValueObjectVisitor
2626
/** @var \Ibexa\Contracts\Core\Repository\ContentService */
2727
private $contentService;
2828

29-
public function __construct(LocationService $locationService, ContentService $contentService)
30-
{
29+
public function __construct(
30+
LocationService $locationService,
31+
ContentService $contentService
32+
) {
3133
$this->locationService = $locationService;
3234
$this->contentService = $contentService;
3335
}
@@ -48,8 +50,15 @@ public function visit(Visitor $visitor, Generator $generator, $location)
4850
$generator->endObjectElement('Location');
4951
}
5052

51-
protected function visitLocationAttributes(Visitor $visitor, Generator $generator, LocationValue $location)
52-
{
53+
/**
54+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
55+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException
56+
*/
57+
protected function visitLocationAttributes(
58+
Visitor $visitor,
59+
Generator $generator,
60+
Content\Location $location
61+
) {
5362
$generator->startAttribute(
5463
'href',
5564
$this->router->generate(
@@ -153,15 +162,8 @@ protected function visitLocationAttributes(Visitor $visitor, Generator $generato
153162
$generator->endAttribute('href');
154163

155164
$content = $location->getContent();
156-
$contentInfo = $location->contentInfo;
157-
158-
try {
159-
$mainLocation = $contentInfo->mainLocationId === $location->id
160-
? $location
161-
: $this->locationService->loadLocation($contentInfo->mainLocationId);
162-
} catch (UnauthorizedException $e) {
163-
$mainLocation = null;
164-
}
165+
$contentInfo = $location->getContentInfo();
166+
$mainLocation = $this->resolveMainLocation($contentInfo, $location);
165167

166168
$visitor->visitValueObject(
167169
new RestContentValue(
@@ -175,6 +177,29 @@ protected function visitLocationAttributes(Visitor $visitor, Generator $generato
175177

176178
$generator->endObjectElement('ContentInfo');
177179
}
180+
181+
/**
182+
* @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException
183+
*/
184+
private function resolveMainLocation(
185+
Content\ContentInfo $contentInfo,
186+
Content\Location $location
187+
): ?Content\Location {
188+
$mainLocationId = $contentInfo->getMainLocationId();
189+
if ($mainLocationId === null) {
190+
return null;
191+
}
192+
193+
if ($mainLocationId === $location->id) {
194+
return $location;
195+
}
196+
197+
try {
198+
return $this->locationService->loadLocation($mainLocationId);
199+
} catch (UnauthorizedException $e) {
200+
return null;
201+
}
202+
}
178203
}
179204

180205
class_alias(Location::class, 'EzSystems\EzPlatformRest\Server\Output\ValueObjectVisitor\Location');
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
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+
namespace Ibexa\Tests\Rest\Server\Output\ValueObjectVisitor;
8+
9+
use eZ\Publish\Core\Repository\Values\Content\Location;
10+
use Ibexa\Contracts\Core\Repository\ContentService;
11+
use Ibexa\Contracts\Core\Repository\LocationService;
12+
use Ibexa\Contracts\Core\Repository\PermissionResolver;
13+
use Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo;
14+
use Ibexa\Contracts\Core\Repository\Values\Content\Location as ApiLocation;
15+
use Ibexa\Core\Base\Exceptions\UnauthorizedException;
16+
use Ibexa\Core\Repository\Values\Content\Content;
17+
use Ibexa\Core\Repository\Values\Content\VersionInfo;
18+
use Ibexa\Core\Repository\Values\ContentType\ContentType;
19+
use Ibexa\Rest\Server\Output\ValueObjectVisitor;
20+
use Ibexa\Tests\Rest\Output\ValueObjectVisitorBaseTest;
21+
22+
final class LocationTest extends ValueObjectVisitorBaseTest
23+
{
24+
private const MAIN_LOCATION_ID = 78;
25+
26+
private const UNAUTHORIZED_MAIN_LOCATION_ID = 111;
27+
28+
private const LOCATION_ID = 55;
29+
30+
/** @var \Ibexa\Contracts\Core\Repository\LocationService&\PHPUnit\Framework\MockObject\MockObject */
31+
private LocationService $locationServiceMock;
32+
33+
/** @var \Ibexa\Contracts\Core\Repository\ContentService&\PHPUnit\Framework\MockObject\MockObject */
34+
private ContentService $contentServiceMock;
35+
36+
protected function setUp(): void
37+
{
38+
$this->permissionResolverMock = $this->createMock(PermissionResolver::class);
39+
$this->locationServiceMock = $this->createMock(LocationService::class);
40+
$this->contentServiceMock = $this->createMock(ContentService::class);
41+
42+
parent::setUp();
43+
}
44+
45+
/**
46+
* @dataProvider getDataForTestVisitLocationAttributesResolvesMainLocation
47+
*/
48+
public function testVisitLocationAttributesResolvesMainLocation(
49+
?int $mainLocationId,
50+
int $locationId
51+
): void {
52+
$visitor = $this->getVisitor();
53+
$generator = $this->getGenerator();
54+
55+
$generator->startDocument(null);
56+
57+
$contentId = 7;
58+
$versionInfo = new VersionInfo();
59+
60+
$location = new Location([
61+
'id' => $locationId,
62+
'path' => ['1', '25', '42'],
63+
'priority' => 1,
64+
'sortField' => ApiLocation::SORT_FIELD_DEPTH,
65+
'sortOrder' => ApiLocation::SORT_ORDER_ASC,
66+
'parentLocationId' => 42,
67+
'contentInfo' => new ContentInfo([
68+
'id' => $contentId,
69+
'mainLocationId' => $mainLocationId,
70+
]),
71+
'content' => new Content([
72+
'id' => $contentId,
73+
'contentType' => new ContentType(),
74+
'versionInfo' => $versionInfo,
75+
]),
76+
]);
77+
78+
$this->mockLoadLocation($location);
79+
80+
$this->contentServiceMock->expects(self::once())
81+
->method('loadRelations')
82+
->with($versionInfo)
83+
->willReturn([]);
84+
85+
$visitor->visit(
86+
$this->getVisitorMock(),
87+
$generator,
88+
$location
89+
);
90+
91+
$result = $generator->endDocument(null);
92+
93+
self::assertNotNull($result);
94+
95+
$this->assertXMLTag(
96+
[
97+
'tag' => 'Location',
98+
'content' => $location->id . 1 . 'false' . 'false',
99+
],
100+
$result,
101+
'Invalid <Location> element.',
102+
);
103+
}
104+
105+
private function mockLoadLocation(Location $location): void
106+
{
107+
$mainLocationId = $location->getContentInfo()->getMainLocationId();
108+
109+
switch ($mainLocationId) {
110+
case $location->id:
111+
case null:
112+
$this->locationServiceMock->expects(self::never())
113+
->method('loadLocation');
114+
break;
115+
case self::UNAUTHORIZED_MAIN_LOCATION_ID:
116+
$this->locationServiceMock->expects(self::once())
117+
->method('loadLocation')
118+
->with($mainLocationId)
119+
->willThrowException(new UnauthorizedException('', ''));
120+
break;
121+
default:
122+
$this->locationServiceMock->expects(self::once())
123+
->method('loadLocation')
124+
->with($mainLocationId)
125+
->willReturn(new Location(['id' => $mainLocationId]));
126+
break;
127+
}
128+
}
129+
130+
public function getDataForTestVisitLocationAttributesResolvesMainLocation(): iterable
131+
{
132+
yield 'same' => [self::MAIN_LOCATION_ID, self::MAIN_LOCATION_ID];
133+
134+
yield 'empty-main-location' => [null, self::LOCATION_ID];
135+
136+
yield 'different' => [999, self::LOCATION_ID];
137+
138+
yield 'unauthorized' => [self::UNAUTHORIZED_MAIN_LOCATION_ID, self::LOCATION_ID];
139+
}
140+
141+
protected function internalGetVisitor(): ValueObjectVisitor\Location
142+
{
143+
return new ValueObjectVisitor\Location($this->locationServiceMock, $this->contentServiceMock);
144+
}
145+
}

0 commit comments

Comments
 (0)