Completed
Pull Request — 1.0 (#67)
by Harald
08:31 queued 01:50
created

LocationManager::find()   C

Complexity

Conditions 8
Paths 22

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 8

Importance

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