Completed
Push — ezp_30300 ( ef176f...d1dcf2 )
by
unknown
26:24
created

LocationHandler::update()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the LocationHandler implementation.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 */
9
namespace eZ\Publish\Core\Persistence\Cache;
10
11
use eZ\Publish\SPI\Persistence\Content\Location\Handler as LocationHandlerInterface;
12
use eZ\Publish\SPI\Persistence\Content\Location\CreateStruct;
13
use eZ\Publish\SPI\Persistence\Content\Location\UpdateStruct;
14
use eZ\Publish\SPI\Persistence\Content\Location;
15
16
/**
17
 * @see \eZ\Publish\SPI\Persistence\Content\Location\Handler
18
 */
19
class LocationHandler extends AbstractHandler implements LocationHandlerInterface
20
{
21
    /**
22
     * {@inheritdoc}
23
     */
24 View Code Duplication
    public function load($locationId, array $translations = null, bool $useAlwaysAvailable = true)
25
    {
26
        $translationsKey = $this->getCacheTranslationKey($translations, $useAlwaysAvailable);
27
        $cacheItem = $this->cache->getItem("ez-location-${locationId}-${translationsKey}");
28
        if ($cacheItem->isHit()) {
29
            return $cacheItem->get();
30
        }
31
32
        $this->logger->logCall(
33
            __METHOD__,
34
            ['location' => $locationId, 'translations' => $translations, 'always-available' => $useAlwaysAvailable]
35
        );
36
        $location = $this->persistenceHandler->locationHandler()->load($locationId, $translations, $useAlwaysAvailable);
0 ignored issues
show
Bug introduced by
It seems like $translations defined by parameter $translations on line 24 can also be of type array; however, eZ\Publish\SPI\Persisten...ocation\Handler::load() does only seem to accept null|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
37
38
        $cacheItem->set($location);
39
        $cacheItem->tag($this->getCacheTags($location));
40
        $this->cache->save($cacheItem);
41
42
        return $location;
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public function loadSubtreeIds($locationId)
49
    {
50
        $cacheItem = $this->cache->getItem("ez-location-subtree-${locationId}");
51
        if ($cacheItem->isHit()) {
52
            return $cacheItem->get();
53
        }
54
55
        $this->logger->logCall(__METHOD__, array('location' => $locationId));
56
        $locationIds = $this->persistenceHandler->locationHandler()->loadSubtreeIds($locationId);
57
58
        $cacheItem->set($locationIds);
59
        $cacheTags = ['location-' . $locationId, 'location-path-' . $locationId];
60
        foreach ($locationIds as $id) {
61
            $cacheTags[] = 'location-' . $id;
62
            $cacheTags[] = 'location-path-' . $id;
63
        }
64
        $cacheItem->tag($cacheTags);
65
        $this->cache->save($cacheItem);
66
67
        return $locationIds;
68
    }
69
70
    /**
71
     * {@inheritdoc}
72
     */
73
    public function loadLocationsByContent($contentId, $rootLocationId = null)
74
    {
75
        if ($rootLocationId) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $rootLocationId of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
76
            $cacheItem = $this->cache->getItem("ez-content-locations-${contentId}-root-${rootLocationId}");
77
            $cacheTags = ['content-' . $contentId, 'location-' . $rootLocationId, 'location-path-' . $rootLocationId];
78
        } else {
79
            $cacheItem = $this->cache->getItem("ez-content-locations-${contentId}");
80
            $cacheTags = ['content-' . $contentId];
81
        }
82
83
        if ($cacheItem->isHit()) {
84
            return $cacheItem->get();
85
        }
86
87
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'root' => $rootLocationId));
88
        $locations = $this->persistenceHandler->locationHandler()->loadLocationsByContent($contentId, $rootLocationId);
89
90
        $cacheItem->set($locations);
91
        foreach ($locations as $location) {
92
            $cacheTags = $this->getCacheTags($location, $cacheTags);
93
        }
94
        $cacheItem->tag($cacheTags);
95
        $this->cache->save($cacheItem);
96
97
        return $locations;
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 View Code Duplication
    public function loadParentLocationsForDraftContent($contentId)
104
    {
105
        $cacheItem = $this->cache->getItem("ez-content-locations-${contentId}-parentForDraft");
106
        if ($cacheItem->isHit()) {
107
            return $cacheItem->get();
108
        }
109
110
        $this->logger->logCall(__METHOD__, array('content' => $contentId));
111
        $locations = $this->persistenceHandler->locationHandler()->loadParentLocationsForDraftContent($contentId);
112
113
        $cacheItem->set($locations);
114
        $cacheTags = ['content-' . $contentId];
115
        foreach ($locations as $location) {
116
            $cacheTags = $this->getCacheTags($location, $cacheTags);
117
        }
118
        $cacheItem->tag($cacheTags);
119
        $this->cache->save($cacheItem);
120
121
        return $locations;
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127 View Code Duplication
    public function loadByRemoteId($remoteId, array $translations = null, bool $useAlwaysAvailable = true)
128
    {
129
        $translationsKey = $this->getCacheTranslationKey($translations, $useAlwaysAvailable);
130
        $cacheItem = $this->cache->getItem("ez-location-remoteid-${remoteId}-${translationsKey}");
131
        if ($cacheItem->isHit()) {
132
            return $cacheItem->get();
133
        }
134
135
        $this->logger->logCall(
136
            __METHOD__,
137
            ['location' => $remoteId, 'translations' => $translations, 'always-available' => $useAlwaysAvailable]
138
        );
139
        $location = $this->persistenceHandler->locationHandler()->loadByRemoteId($remoteId, $translations, $useAlwaysAvailable);
0 ignored issues
show
Bug introduced by
It seems like $translations defined by parameter $translations on line 127 can also be of type array; however, eZ\Publish\SPI\Persisten...ndler::loadByRemoteId() does only seem to accept null|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
140
141
        $cacheItem->set($location);
142
        $cacheItem->tag($this->getCacheTags($location));
143
        $this->cache->save($cacheItem);
144
145
        return $location;
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151 View Code Duplication
    public function copySubtree($sourceId, $destinationParentId, $newOwnerId = null)
152
    {
153
        $this->logger->logCall(__METHOD__, array(
154
            'source' => $sourceId,
155
            'destination' => $destinationParentId,
156
            'newOwner' => $newOwnerId,
157
        ));
158
159
        return $this->persistenceHandler->locationHandler()->copySubtree($sourceId, $destinationParentId, $newOwnerId);
160
    }
161
162
    /**
163
     * {@inheritdoc}
164
     */
165
    public function move($sourceId, $destinationParentId)
166
    {
167
        $this->logger->logCall(__METHOD__, array('source' => $sourceId, 'destination' => $destinationParentId));
168
        $return = $this->persistenceHandler->locationHandler()->move($sourceId, $destinationParentId);
169
170
        $this->cache->invalidateTags(['location-path-' . $sourceId]);
171
172
        return $return;
173
    }
174
175
    /**
176
     * {@inheritdoc}
177
     */
178
    public function markSubtreeModified($locationId, $timestamp = null)
179
    {
180
        $this->logger->logCall(__METHOD__, array('location' => $locationId, 'time' => $timestamp));
181
        $this->persistenceHandler->locationHandler()->markSubtreeModified($locationId, $timestamp);
0 ignored issues
show
Deprecated Code introduced by
The method eZ\Publish\SPI\Persisten...::markSubtreeModified() has been deprecated with message: As of 6.8, not been used by repository since 5.x.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
182
    }
183
184
    /**
185
     * {@inheritdoc}
186
     */
187
    public function hide($locationId)
188
    {
189
        $this->logger->logCall(__METHOD__, array('location' => $locationId));
190
        $return = $this->persistenceHandler->locationHandler()->hide($locationId);
191
192
        $this->cache->invalidateTags(['location-path-data-' . $locationId]);
193
194
        return $return;
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200
    public function unHide($locationId)
201
    {
202
        $this->logger->logCall(__METHOD__, array('location' => $locationId));
203
        $return = $this->persistenceHandler->locationHandler()->unHide($locationId);
204
205
        $this->cache->invalidateTags(['location-path-data-' . $locationId]);
206
207
        return $return;
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213
    public function swap($locationId1, $locationId2)
214
    {
215
        $this->logger->logCall(__METHOD__, array('location1' => $locationId1, 'location2' => $locationId2));
216
        $locationHandler = $this->persistenceHandler->locationHandler();
217
218
        $return = $locationHandler->swap($locationId1, $locationId2);
219
220
        $this->cache->invalidateTags(
221
            [
222
                'location-' . $locationId1,
223
                'location-' . $locationId2,
224
            ]
225
        );
226
227
        return $return;
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233
    public function update(UpdateStruct $struct, $locationId)
234
    {
235
        $this->logger->logCall(__METHOD__, array('location' => $locationId, 'struct' => $struct));
236
        $this->persistenceHandler->locationHandler()->update($struct, $locationId);
237
238
        $this->cache->invalidateTags(['location-data-' . $locationId]);
239
    }
240
241
    /**
242
     * {@inheritdoc}
243
     */
244
    public function create(CreateStruct $locationStruct)
245
    {
246
        $this->logger->logCall(__METHOD__, array('struct' => $locationStruct));
247
        $location = $this->persistenceHandler->locationHandler()->create($locationStruct);
248
249
        // need to clear loadLocationsByContent and similar collections involving locations data
250
        // also need to clear content info on main location changes
251
        $this->cache->invalidateTags(['content-' . $locationStruct->contentId, 'role-assignment-group-list-' . $locationStruct->contentId]);
252
253
        return $location;
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259
    public function removeSubtree($locationId)
260
    {
261
        $this->logger->logCall(__METHOD__, array('location' => $locationId));
262
        $return = $this->persistenceHandler->locationHandler()->removeSubtree($locationId);
263
264
        $this->cache->invalidateTags(['location-path-' . $locationId]);
265
266
        return $return;
267
    }
268
269
    /**
270
     * {@inheritdoc}
271
     */
272
    public function setSectionForSubtree($locationId, $sectionId)
273
    {
274
        $this->logger->logCall(__METHOD__, array('location' => $locationId, 'section' => $sectionId));
275
        $this->persistenceHandler->locationHandler()->setSectionForSubtree($locationId, $sectionId);
276
277
        $this->cache->invalidateTags(['location-path-' . $locationId]);
278
    }
279
280
    /**
281
     * {@inheritdoc}
282
     */
283
    public function changeMainLocation($contentId, $locationId)
284
    {
285
        $this->logger->logCall(__METHOD__, array('location' => $locationId, 'content' => $contentId));
286
        $this->persistenceHandler->locationHandler()->changeMainLocation($contentId, $locationId);
287
288
        $this->cache->invalidateTags(['content-' . $contentId]);
289
    }
290
291
    /**
292
     * Get the total number of all existing Locations. Can be combined with loadAllLocations.
293
     *
294
     * @return int
295
     */
296
    public function countAllLocations()
297
    {
298
        $this->logger->logCall(__METHOD__);
299
300
        return $this->persistenceHandler->locationHandler()->countAllLocations();
301
    }
302
303
    /**
304
     * Bulk-load all existing Locations, constrained by $limit and $offset to paginate results.
305
     *
306
     * @param int $offset
307
     * @param int $limit
308
     *
309
     * @return \eZ\Publish\SPI\Persistence\Content\Location[]
310
     */
311
    public function loadAllLocations($offset, $limit)
312
    {
313
        $this->logger->logCall(__METHOD__, array('offset' => $offset, 'limit' => $limit));
314
315
        return $this->persistenceHandler->locationHandler()->loadAllLocations($offset, $limit);
316
    }
317
318
    /**
319
     * Return relevant content and location tags so cache can be purged reliably.
320
     *
321
     * @param \eZ\Publish\SPI\Persistence\Content\Location $location
322
     * @param array $tags Optional, can be used to specify additional tags.
323
     *
324
     * @return array
325
     */
326
    private function getCacheTags(Location $location, $tags = [])
327
    {
328
        $tags[] = 'content-' . $location->contentId;
329
        $tags[] = 'location-' . $location->id;
330
        $tags[] = 'location-data-' . $location->id;
331
        foreach (explode('/', trim($location->pathString, '/')) as $pathId) {
332
            $tags[] = 'location-path-' . $pathId;
333
            $tags[] = 'location-path-data-' . $pathId;
334
        }
335
336
        return $tags;
337
    }
338
339
    private function getCacheTranslationKey(array $translations = null, bool $useAlwaysAvailable = true): string
340
    {
341
        if (empty($translations)) {
342
            return (int)$useAlwaysAvailable;
343
        }
344
345
        // Sort array as we don't care about order in location handler usage & want to optimize for cache hits.
346
        sort($translations);
347
348
        return implode('|', $translations) . '|' . (int)$useAlwaysAvailable;
349
    }
350
}
351