Completed
Push — 1.0 ( 2156a0...733517 )
by Valentin
07:09
created

LocationManager::syncronizeLocationsFromContentObject()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 26
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 26
ccs 18
cts 18
cp 1
rs 8.439
cc 6
eloc 13
nc 9
nop 1
crap 6
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);
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']);
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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