|
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\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
|
14 |
|
public function __construct(Repository $repository) |
|
59
|
|
|
{ |
|
60
|
14 |
|
$this->repository = $repository; |
|
61
|
14 |
|
$this->locationService = $repository->getLocationService(); |
|
62
|
14 |
|
$this->contentService = $repository->getContentService(); |
|
63
|
14 |
|
} |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* {@inheritdoc} |
|
67
|
|
|
*/ |
|
68
|
33 |
|
public function setLogger(LoggerInterface $logger) |
|
69
|
12 |
|
{ |
|
70
|
33 |
|
$this->logger = $logger; |
|
71
|
33 |
|
} |
|
72
|
|
|
|
|
73
|
|
|
/** |
|
74
|
|
|
* Attempts to load Location based on id or remoteId. |
|
75
|
|
|
* Returns false if not found. |
|
76
|
|
|
* |
|
77
|
|
|
* @param ValueObject $object |
|
78
|
|
|
* @param bool $throwException |
|
79
|
|
|
* |
|
80
|
|
|
* @return Location|false |
|
81
|
|
|
* |
|
82
|
|
|
* @throws NotFoundException |
|
83
|
|
|
*/ |
|
84
|
12 |
|
public function find(ValueObject $object, $throwException = false) |
|
85
|
|
|
{ |
|
86
|
|
|
try { |
|
87
|
12 |
|
if (isset($object->data['remote_id'])) { |
|
88
|
11 |
|
$location = $this->locationService->loadLocationByRemoteId($object->data['remote_id']); |
|
89
|
12 |
|
} elseif ($object->getProperty('id')) { |
|
90
|
3 |
|
$location = $this->locationService->loadLocation($object->getProperty('id')); |
|
91
|
3 |
|
} |
|
92
|
12 |
|
} catch (NotFoundException $notFound) { |
|
93
|
2 |
|
$exception = $notFound; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
12 |
|
if (!isset($location)) { |
|
97
|
4 |
|
if (isset($exception) && $throwException) { |
|
98
|
1 |
|
throw $exception; |
|
99
|
|
|
} |
|
100
|
|
|
|
|
101
|
4 |
|
return false; |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
11 |
|
return isset($location) ? $location : false; |
|
105
|
|
|
} |
|
106
|
|
|
|
|
107
|
|
|
/** |
|
108
|
|
|
* Shortcut to find, mainly for locating parents. |
|
109
|
|
|
* |
|
110
|
|
|
* @param int $id |
|
111
|
|
|
* @param bool $throwException |
|
112
|
|
|
* |
|
113
|
|
|
* @return Location|false |
|
114
|
|
|
*/ |
|
115
|
2 |
|
public function findById($id, $throwException = false) |
|
116
|
|
|
{ |
|
117
|
2 |
|
return $this->find(new ValueObject([], ['id' => $id]), $throwException); |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
|
/** |
|
121
|
|
|
* {@inheritdoc} |
|
122
|
|
|
*/ |
|
123
|
5 |
|
public function create(ObjectInterface $object) |
|
124
|
|
|
{ |
|
125
|
5 |
|
if (!$object instanceof LocationObject) { |
|
126
|
1 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
|
127
|
|
|
} |
|
128
|
|
|
|
|
129
|
4 |
|
$contentInfo = $this->repository->getContentService()->loadContentInfo($object->data['content_id']); |
|
130
|
|
|
|
|
131
|
4 |
|
$locationCreateStruct = $this->locationService->newLocationCreateStruct($object->data['parent_location_id']); |
|
132
|
|
|
|
|
133
|
4 |
|
$object->getMapper()->getNewLocationCreateStruct($locationCreateStruct); |
|
134
|
|
|
|
|
135
|
4 |
|
$location = $this->locationService->createLocation($contentInfo, $locationCreateStruct); |
|
136
|
|
|
|
|
137
|
4 |
|
if ($this->logger) { |
|
138
|
4 |
|
$this->logger->info(sprintf('Created location %s on content id %s, with parent location id %s.', $location->id, $contentInfo->id, $location->parentLocationId)); |
|
139
|
4 |
|
} |
|
140
|
|
|
|
|
141
|
4 |
|
$object->getMapper()->locationToObject($location); |
|
142
|
|
|
|
|
143
|
4 |
|
return $object; |
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
|
/** |
|
147
|
|
|
* {@inheritdoc} |
|
148
|
|
|
*/ |
|
149
|
11 |
|
public function update(ObjectInterface $object) |
|
150
|
|
|
{ |
|
151
|
11 |
|
if (!$object instanceof LocationObject) { |
|
152
|
1 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
|
153
|
|
|
} |
|
154
|
|
|
|
|
155
|
11 |
|
$location = $this->find($object, true); |
|
156
|
|
|
|
|
157
|
|
|
// Move if parent_location_id differs. |
|
158
|
11 |
|
if (isset($object->data['parent_location_id'])) { |
|
159
|
11 |
|
if ($object->data['parent_location_id'] !== $location->parentLocationId) { |
|
160
|
2 |
|
$parentLocation = $this->findById($object->data['parent_location_id'], true); |
|
161
|
2 |
|
$this->locationService->moveSubtree($location, $parentLocation); |
|
|
|
|
|
|
162
|
2 |
|
} |
|
163
|
11 |
|
} |
|
164
|
|
|
|
|
165
|
11 |
|
$locationUpdateStruct = $this->locationService->newLocationUpdateStruct(); |
|
166
|
|
|
|
|
167
|
11 |
|
$object->getMapper()->getNewLocationUpdateStruct($locationUpdateStruct); |
|
168
|
|
|
|
|
169
|
11 |
|
$location = $this->locationService->updateLocation($location, $locationUpdateStruct); |
|
|
|
|
|
|
170
|
|
|
|
|
171
|
11 |
|
if ($this->logger) { |
|
172
|
11 |
|
$this->logger->info(sprintf('Updated location %s with parent location id %s.', $location->id, $location->parentLocationId)); |
|
173
|
11 |
|
} |
|
174
|
|
|
|
|
175
|
11 |
|
$object->getMapper()->locationToObject($location); |
|
176
|
|
|
|
|
177
|
11 |
|
return $object; |
|
178
|
|
|
} |
|
179
|
|
|
|
|
180
|
|
|
/** |
|
181
|
|
|
* {@inheritdoc} |
|
182
|
|
|
*/ |
|
183
|
12 |
View Code Duplication |
public function createOrUpdate(ObjectInterface $object) |
|
|
|
|
|
|
184
|
|
|
{ |
|
185
|
12 |
|
if (!$object instanceof LocationObject) { |
|
186
|
1 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
|
187
|
|
|
} |
|
188
|
|
|
|
|
189
|
12 |
|
if ($this->find($object)) { |
|
190
|
11 |
|
return $this->update($object); |
|
191
|
|
|
} else { |
|
192
|
4 |
|
return $this->create($object); |
|
193
|
|
|
} |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
/** |
|
197
|
|
|
* Creates/updates/deletes locations in ContentObject->parent_locations. |
|
198
|
|
|
* |
|
199
|
|
|
* @param ContentObject $object |
|
200
|
|
|
*/ |
|
201
|
15 |
|
public function syncronizeLocationsFromContentObject(ContentObject $object) |
|
202
|
|
|
{ |
|
203
|
|
|
/** @var LocationObject[] $parentLocations */ |
|
204
|
15 |
|
$parentLocations = $object->getProperty('parent_locations'); |
|
205
|
15 |
|
if (is_array($parentLocations) && count($parentLocations) > 0) { |
|
206
|
2 |
|
$addOrUpdate = []; |
|
207
|
2 |
|
foreach ($parentLocations as $parentLocation) { |
|
208
|
2 |
|
$addOrUpdate[$parentLocation->data['parent_location_id']] = $parentLocation; |
|
209
|
2 |
|
} |
|
210
|
|
|
|
|
211
|
|
|
// Filter which Locations should be created/updated and deleted. |
|
212
|
2 |
|
$delible = $this->filterLocationsToBeDeleted($object, $addOrUpdate); |
|
213
|
|
|
|
|
214
|
|
|
// Create or update locations, and attach to Content |
|
215
|
2 |
|
foreach ($addOrUpdate as $parentLocation) { |
|
216
|
2 |
|
$parentLocation->data['content_id'] = $object->getProperty('content_info')->id; |
|
217
|
2 |
|
$object->addParentLocation( |
|
218
|
2 |
|
$this->createOrUpdate($parentLocation) |
|
219
|
2 |
|
); |
|
220
|
2 |
|
} |
|
221
|
|
|
|
|
222
|
|
|
// Lastly delete, cannot delete first because Content cannot have zero locations. |
|
223
|
2 |
|
foreach ($delible as $delete) { |
|
224
|
1 |
|
$this->locationService->deleteLocation($delete); |
|
225
|
2 |
|
} |
|
226
|
2 |
|
} |
|
227
|
15 |
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* @param ContentObject $object |
|
231
|
|
|
* @param LocationObject[] $locationsToKeep |
|
232
|
|
|
* |
|
233
|
|
|
* @return Location[] |
|
234
|
|
|
*/ |
|
235
|
2 |
|
private function filterLocationsToBeDeleted(ContentObject $object, $locationsToKeep) |
|
236
|
|
|
{ |
|
237
|
2 |
|
$toBeDeleted = []; |
|
238
|
|
|
|
|
239
|
2 |
|
foreach ($this->locationService->loadLocations($object->getProperty('content_info')) as $existingLocation) { |
|
240
|
2 |
|
if (!array_key_exists($existingLocation->parentLocationId, $locationsToKeep)) { |
|
241
|
1 |
|
$toBeDeleted[] = $existingLocation; |
|
242
|
1 |
|
} |
|
243
|
2 |
|
} |
|
244
|
|
|
|
|
245
|
2 |
|
return $toBeDeleted; |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
/** |
|
249
|
|
|
* {@inheritdoc} |
|
250
|
|
|
*/ |
|
251
|
4 |
View Code Duplication |
public function remove(ObjectInterface $object) |
|
|
|
|
|
|
252
|
|
|
{ |
|
253
|
4 |
|
if (!$object instanceof LocationObject) { |
|
254
|
1 |
|
throw new UnsupportedObjectOperationException(LocationObject::class, get_class($object)); |
|
255
|
|
|
} |
|
256
|
|
|
|
|
257
|
1 |
|
if ($location = $this->find($object)) { |
|
258
|
3 |
|
$this->locationService->deleteLocation($location); |
|
259
|
1 |
|
} |
|
260
|
|
|
|
|
261
|
1 |
|
return true; |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
/** |
|
265
|
|
|
* Hides a location. |
|
266
|
|
|
* |
|
267
|
|
|
* @param Location $location |
|
268
|
|
|
* |
|
269
|
|
|
* @return Location |
|
270
|
|
|
*/ |
|
271
|
2 |
|
public function hide(Location $location) |
|
272
|
|
|
{ |
|
273
|
2 |
|
return $this->locationService->hideLocation($location); |
|
274
|
|
|
} |
|
275
|
|
|
|
|
276
|
|
|
/** |
|
277
|
|
|
* Un-hides a location. |
|
278
|
|
|
* |
|
279
|
|
|
* @param Location $location |
|
280
|
|
|
* |
|
281
|
|
|
* @return Location |
|
282
|
|
|
*/ |
|
283
|
1 |
|
public function unHide(Location $location) |
|
284
|
|
|
{ |
|
285
|
1 |
|
return $this->locationService->unhideLocation($location); |
|
286
|
|
|
} |
|
287
|
|
|
|
|
288
|
|
|
/** |
|
289
|
|
|
* Toggles location visibility. |
|
290
|
|
|
* |
|
291
|
|
|
* @param Location $location |
|
292
|
|
|
* |
|
293
|
|
|
* @return Location |
|
294
|
|
|
*/ |
|
295
|
2 |
|
public function toggleVisibility(Location $location) |
|
296
|
|
|
{ |
|
297
|
2 |
|
if ($location->hidden) { |
|
298
|
1 |
|
return $this->unHide($location); |
|
299
|
|
|
} |
|
300
|
|
|
|
|
301
|
2 |
|
return $this->hide($location); |
|
302
|
|
|
} |
|
303
|
|
|
} |
|
304
|
|
|
|
This check looks for type mismatches where the missing type is
false. This is usually indicative of an error condtion.Consider the follow example
This function either returns a new
DateTimeobject or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returnedfalsebefore passing on the value to another function or method that may not be able to handle afalse.