Completed
Push — 1.0 ( 7a80f0...fb098d )
by Valentin
10:10 queued 03:21
created

LocationManager::find()   C

Complexity

Conditions 8
Paths 22

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 8

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 27
ccs 18
cts 18
cp 1
rs 5.3846
cc 8
eloc 17
nc 22
nop 1
crap 8
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)
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...
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)
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...
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