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