1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of Transfer. |
5
|
|
|
* |
6
|
|
|
* For the full copyright and license information, please view the LICENSE file located |
7
|
|
|
* in the root directory. |
8
|
|
|
*/ |
9
|
|
|
namespace Transfer\EzPlatform\Repository\Manager; |
10
|
|
|
|
11
|
|
|
use eZ\Publish\API\Repository\ContentService; |
12
|
|
|
use eZ\Publish\API\Repository\Exceptions\NotFoundException; |
13
|
|
|
use eZ\Publish\API\Repository\LocationService; |
14
|
|
|
use eZ\Publish\API\Repository\Repository; |
15
|
|
|
use eZ\Publish\API\Repository\Values\Content\Location; |
16
|
|
|
use Psr\Log\LoggerAwareInterface; |
17
|
|
|
use Psr\Log\LoggerInterface; |
18
|
|
|
use Transfer\Data\ObjectInterface; |
19
|
|
|
use Transfer\Data\ValueObject; |
20
|
|
|
use Transfer\EzPlatform\Exception\ObjectNotFoundException; |
21
|
|
|
use Transfer\EzPlatform\Exception\UnsupportedObjectOperationException; |
22
|
|
|
use Transfer\EzPlatform\Repository\Values\ContentObject; |
23
|
|
|
use Transfer\EzPlatform\Repository\Values\LocationObject; |
24
|
|
|
use Transfer\EzPlatform\Repository\Manager\Type\CreatorInterface; |
25
|
|
|
use Transfer\EzPlatform\Repository\Manager\Type\RemoverInterface; |
26
|
|
|
use Transfer\EzPlatform\Repository\Manager\Type\UpdaterInterface; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Location manager. |
30
|
|
|
* |
31
|
|
|
* @internal |
32
|
|
|
*/ |
33
|
|
|
class LocationManager implements LoggerAwareInterface, CreatorInterface, UpdaterInterface, RemoverInterface |
34
|
|
|
{ |
35
|
|
|
/** |
36
|
|
|
* @var LoggerInterface Logger |
37
|
|
|
*/ |
38
|
|
|
protected $logger; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var Repository |
42
|
|
|
*/ |
43
|
|
|
private $repository; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var LocationService Location service |
47
|
|
|
*/ |
48
|
|
|
private $locationService; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var ContentService Content service |
52
|
|
|
*/ |
53
|
|
|
private $contentService; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @param Repository $repository |
57
|
|
|
*/ |
58
|
16 |
|
public function __construct(Repository $repository) |
59
|
|
|
{ |
60
|
16 |
|
$this->repository = $repository; |
61
|
16 |
|
$this->locationService = $repository->getLocationService(); |
62
|
16 |
|
$this->contentService = $repository->getContentService(); |
63
|
16 |
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* {@inheritdoc} |
67
|
|
|
*/ |
68
|
35 |
|
public function setLogger(LoggerInterface $logger) |
69
|
14 |
|
{ |
70
|
35 |
|
$this->logger = $logger; |
71
|
35 |
|
} |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* {@inheritdoc} |
75
|
|
|
*/ |
76
|
14 |
|
public function find(ValueObject $object) |
77
|
|
|
{ |
78
|
|
|
try { |
79
|
14 |
|
if (isset($object->data['remote_id'])) { |
80
|
12 |
|
$location = $this->locationService->loadLocationByRemoteId($object->data['remote_id']); |
81
|
14 |
|
} elseif ($object->getProperty('id')) { |
82
|
5 |
|
$location = $this->locationService->loadLocation($object->getProperty('id')); |
83
|
8 |
|
} elseif (isset($object->data['content_id'])) { |
84
|
4 |
|
$contentInfo = $this->contentService->loadContentInfo($object->data['content_id']); |
85
|
4 |
|
$locations = $this->locationService->loadLocations($contentInfo); |
86
|
4 |
|
foreach ($locations as $loc) { |
87
|
3 |
|
if ($loc->parentLocationId === $object->data['parent_location_id']) { |
88
|
1 |
|
$location = $loc; |
89
|
1 |
|
break; |
90
|
|
|
} |
91
|
4 |
|
} |
92
|
4 |
|
} |
93
|
14 |
|
} catch (NotFoundException $notFoundException) { |
94
|
|
|
// We'll throw our own exception later instead. |
95
|
|
|
} |
96
|
|
|
|
97
|
14 |
|
if (!isset($location)) { |
98
|
5 |
|
throw new ObjectNotFoundException(Location::class, array('remote_id', 'id')); |
99
|
|
|
} |
100
|
|
|
|
101
|
13 |
|
return $location; |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* Shortcut to find, mainly for locating parents. |
106
|
|
|
* |
107
|
|
|
* @param int $id |
108
|
|
|
* |
109
|
|
|
* @return Location |
110
|
|
|
* |
111
|
|
|
* @throws ObjectNotFoundException |
112
|
|
|
*/ |
113
|
4 |
|
public function findById($id) |
114
|
|
|
{ |
115
|
4 |
|
return $this->find(new ValueObject([], ['id' => $id])); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* {@inheritdoc} |
120
|
|
|
*/ |
121
|
6 |
|
public function create(ObjectInterface $object) |
122
|
|
|
{ |
123
|
6 |
|
if (!$object instanceof LocationObject) { |
124
|
1 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
125
|
|
|
} |
126
|
|
|
|
127
|
5 |
|
$contentInfo = $this->repository->getContentService()->loadContentInfo($object->data['content_id']); |
128
|
|
|
|
129
|
5 |
|
$locationCreateStruct = $this->locationService->newLocationCreateStruct($object->data['parent_location_id']); |
130
|
|
|
|
131
|
5 |
|
$object->getMapper()->getNewLocationCreateStruct($locationCreateStruct); |
132
|
|
|
|
133
|
5 |
|
$location = $this->locationService->createLocation($contentInfo, $locationCreateStruct); |
134
|
|
|
|
135
|
5 |
|
if ($this->logger) { |
136
|
5 |
|
$this->logger->info(sprintf('Created location %s on content id %s, with parent location id %s.', $location->id, $contentInfo->id, $location->parentLocationId)); |
137
|
5 |
|
} |
138
|
|
|
|
139
|
5 |
|
$object->getMapper()->locationToObject($location); |
140
|
|
|
|
141
|
5 |
|
return $object; |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* {@inheritdoc} |
146
|
|
|
*/ |
147
|
13 |
|
public function update(ObjectInterface $object) |
148
|
|
|
{ |
149
|
13 |
|
if (!$object instanceof LocationObject) { |
150
|
1 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
151
|
|
|
} |
152
|
|
|
|
153
|
13 |
|
$location = $this->find($object); |
154
|
|
|
|
155
|
|
|
// Move if parent_location_id differs. |
156
|
13 |
|
if (isset($object->data['parent_location_id'])) { |
157
|
13 |
|
if ($object->data['parent_location_id'] !== $location->parentLocationId) { |
158
|
4 |
|
$parentLocation = $this->findById($object->data['parent_location_id']); |
159
|
4 |
|
$this->locationService->moveSubtree($location, $parentLocation); |
160
|
4 |
|
} |
161
|
13 |
|
} |
162
|
|
|
|
163
|
13 |
|
$locationUpdateStruct = $this->locationService->newLocationUpdateStruct(); |
164
|
|
|
|
165
|
13 |
|
$object->getMapper()->getNewLocationUpdateStruct($locationUpdateStruct); |
166
|
|
|
|
167
|
13 |
|
$location = $this->locationService->updateLocation($location, $locationUpdateStruct); |
168
|
|
|
|
169
|
13 |
|
if ($this->logger) { |
170
|
13 |
|
$this->logger->info(sprintf('Updated location %s with parent location id %s.', $location->id, $location->parentLocationId)); |
171
|
13 |
|
} |
172
|
|
|
|
173
|
13 |
|
$object->getMapper()->locationToObject($location); |
174
|
|
|
|
175
|
13 |
|
return $object; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* {@inheritdoc} |
180
|
|
|
*/ |
181
|
14 |
View Code Duplication |
public function createOrUpdate(ObjectInterface $object) |
|
|
|
|
182
|
|
|
{ |
183
|
14 |
|
if (!$object instanceof LocationObject) { |
184
|
1 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
try { |
188
|
14 |
|
$this->find($object); |
189
|
|
|
|
190
|
13 |
|
return $this->update($object); |
191
|
5 |
|
} catch (NotFoundException $notFound) { |
192
|
5 |
|
return $this->create($object); |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* Creates/updates/deletes locations in ContentObject->parent_locations. |
198
|
|
|
* |
199
|
|
|
* @param ContentObject $object |
200
|
|
|
*/ |
201
|
17 |
|
public function syncronizeLocationsFromContentObject(ContentObject $object) |
202
|
|
|
{ |
203
|
|
|
/** @var LocationObject[] $parentLocations */ |
204
|
17 |
|
$parentLocations = $object->getProperty('parent_locations'); |
205
|
17 |
|
if (is_array($parentLocations) && count($parentLocations) > 0) { |
206
|
4 |
|
$addOrUpdate = []; |
207
|
4 |
|
foreach ($parentLocations as $parentLocation) { |
208
|
4 |
|
$addOrUpdate[$parentLocation->data['parent_location_id']] = $parentLocation; |
209
|
4 |
|
} |
210
|
|
|
|
211
|
|
|
// Filter which Locations should be created/updated and deleted. |
212
|
4 |
|
$delible = $this->filterLocationsToBeDeleted($object, $addOrUpdate); |
213
|
|
|
|
214
|
|
|
// Create or update locations, and attach to Content |
215
|
4 |
|
foreach ($addOrUpdate as $parentLocation) { |
216
|
4 |
|
$parentLocation->data['content_id'] = $object->getProperty('content_info')->id; |
217
|
4 |
|
$locationObject = $this->createOrUpdate($parentLocation); |
218
|
4 |
|
$object->addParentLocation($locationObject); |
219
|
4 |
|
} |
220
|
|
|
|
221
|
|
|
// Lastly delete. We cannot delete first because Content cannot remove it's last Location. |
222
|
4 |
|
foreach ($delible as $delete) { |
223
|
1 |
|
$this->locationService->deleteLocation($delete); |
224
|
4 |
|
} |
225
|
4 |
|
} |
226
|
17 |
|
} |
227
|
|
|
|
228
|
|
|
/** |
229
|
|
|
* @param ContentObject $object |
230
|
|
|
* @param LocationObject[] $locationsToKeep |
231
|
|
|
* |
232
|
|
|
* @return Location[] |
233
|
|
|
*/ |
234
|
4 |
|
private function filterLocationsToBeDeleted(ContentObject $object, $locationsToKeep) |
235
|
|
|
{ |
236
|
4 |
|
$toBeDeleted = []; |
237
|
|
|
|
238
|
4 |
|
foreach ($this->locationService->loadLocations($object->getProperty('content_info')) as $existingLocation) { |
239
|
3 |
|
if (!array_key_exists($existingLocation->parentLocationId, $locationsToKeep)) { |
240
|
1 |
|
$toBeDeleted[] = $existingLocation; |
241
|
1 |
|
} |
242
|
4 |
|
} |
243
|
|
|
|
244
|
4 |
|
return $toBeDeleted; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* {@inheritdoc} |
249
|
|
|
*/ |
250
|
5 |
View Code Duplication |
public function remove(ObjectInterface $object) |
|
|
|
|
251
|
|
|
{ |
252
|
2 |
|
if (!$object instanceof LocationObject) { |
253
|
5 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
254
|
|
|
} |
255
|
|
|
|
256
|
1 |
|
if ($location = $this->find($object)) { |
257
|
1 |
|
$this->locationService->deleteLocation($location); |
258
|
5 |
|
} |
259
|
|
|
|
260
|
1 |
|
return true; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
/** |
264
|
|
|
* Hides a location. |
265
|
|
|
* |
266
|
|
|
* @param Location $location |
267
|
|
|
* |
268
|
|
|
* @return Location |
269
|
|
|
*/ |
270
|
2 |
|
public function hide(Location $location) |
271
|
|
|
{ |
272
|
2 |
|
return $this->locationService->hideLocation($location); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* Un-hides a location. |
277
|
|
|
* |
278
|
|
|
* @param Location $location |
279
|
|
|
* |
280
|
|
|
* @return Location |
281
|
|
|
*/ |
282
|
1 |
|
public function unHide(Location $location) |
283
|
|
|
{ |
284
|
1 |
|
return $this->locationService->unhideLocation($location); |
285
|
|
|
} |
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Toggles location visibility. |
289
|
|
|
* |
290
|
|
|
* @param Location $location |
291
|
|
|
* |
292
|
|
|
* @return Location |
293
|
|
|
*/ |
294
|
2 |
|
public function toggleVisibility(Location $location) |
295
|
|
|
{ |
296
|
2 |
|
if ($location->hidden) { |
297
|
1 |
|
return $this->unHide($location); |
298
|
|
|
} |
299
|
|
|
|
300
|
2 |
|
return $this->hide($location); |
301
|
|
|
} |
302
|
|
|
} |
303
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.