Completed
Push — master ( 97e40f...89ec5c )
by André
40:26 queued 12:35
created

ContentHandler::loadContentInfoByRemoteId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 1
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the ContentHandler 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\API\Repository\Values\Content\Relation as APIRelation;
12
use eZ\Publish\SPI\Persistence\Content\Handler as ContentHandlerInterface;
13
use eZ\Publish\SPI\Persistence\Content\VersionInfo;
14
use eZ\Publish\SPI\Persistence\Content\ContentInfo;
15
use eZ\Publish\SPI\Persistence\Content\CreateStruct;
16
use eZ\Publish\SPI\Persistence\Content\UpdateStruct;
17
use eZ\Publish\SPI\Persistence\Content\MetadataUpdateStruct;
18
use eZ\Publish\SPI\Persistence\Content\Relation\CreateStruct as RelationCreateStruct;
19
20
/**
21
 * @see \eZ\Publish\SPI\Persistence\Content\Handler
22
 */
23
class ContentHandler extends AbstractHandler implements ContentHandlerInterface
24
{
25
    const ALL_TRANSLATIONS_KEY = '0';
26
27
    /**
28
     * {@inheritdoc}
29
     */
30
    public function create(CreateStruct $struct)
31
    {
32
        // Cached on demand when published or loaded
33
        $this->logger->logCall(__METHOD__, array('struct' => $struct));
34
35
        return $this->persistenceHandler->contentHandler()->create($struct);
36
    }
37
38
    /**
39
     * {@inheritdoc}
40
     */
41
    public function createDraftFromVersion($contentId, $srcVersion, $userId)
42
    {
43
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $srcVersion, 'user' => $userId));
44
        $draft = $this->persistenceHandler->contentHandler()->createDraftFromVersion($contentId, $srcVersion, $userId);
45
        $this->cache->invalidateTags(["content-$contentId-version-list"]);
46
47
        return $draft;
48
    }
49
50
    /**
51
     * {@inheritdoc}
52
     */
53
    public function copy($contentId, $versionNo = null)
54
    {
55
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo));
56
57
        return $this->persistenceHandler->contentHandler()->copy($contentId, $versionNo);
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    public function load($contentId, $versionNo, array $translations = null)
64
    {
65
        $translationsKey = empty($translations) ? self::ALL_TRANSLATIONS_KEY : implode('|', $translations);
66
        $cacheItem = $this->cache->getItem("ez-content-${contentId}-${versionNo}-${translationsKey}");
67
        if ($cacheItem->isHit()) {
68
            return $cacheItem->get();
69
        }
70
71
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo, 'translations' => $translations));
72
        $content = $this->persistenceHandler->contentHandler()->load($contentId, $versionNo, $translations);
0 ignored issues
show
Bug introduced by
It seems like $translations defined by parameter $translations on line 63 can also be of type array; however, eZ\Publish\SPI\Persistence\Content\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...
73
        $cacheItem->set($content);
74
        $cacheItem->tag($this->getCacheTags($content->versionInfo->contentInfo, true));
75
        $this->cache->save($cacheItem);
76
77
        return $content;
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function loadContentInfo($contentId)
84
    {
85
        $cacheItem = $this->cache->getItem("ez-content-info-${contentId}");
86
        if ($cacheItem->isHit()) {
87
            return $cacheItem->get();
88
        }
89
90
        $this->logger->logCall(__METHOD__, array('content' => $contentId));
91
        $contentInfo = $this->persistenceHandler->contentHandler()->loadContentInfo($contentId);
92
        $cacheItem->set($contentInfo);
93
        $cacheItem->tag($this->getCacheTags($contentInfo));
94
        $this->cache->save($cacheItem);
95
96
        return $contentInfo;
97
    }
98
99 View Code Duplication
    public function loadContentInfoList(array $contentIds)
100
    {
101
        list($cacheMisses, $list) = $this->getMultipleCacheItems($contentIds, 'ez-content-info-');
102
        if (empty($cacheMisses)) {
103
            return $list;
104
        }
105
106
        // Load cache misses
107
        $this->logger->logCall(__METHOD__, array('content' => $cacheMisses));
108
        $cacheMissList = $this->persistenceHandler->contentHandler()->loadContentInfoList($cacheMisses);
109
110
        // Populate cache misses with data and set final info data instead on list
111
        foreach ($cacheMissList as $id => $contentInfo) {
112
            $this->cache->save(
113
                $list[$id]
114
                    ->set($contentInfo)
115
                    ->tag($this->getCacheTags($contentInfo))
116
            );
117
            $list[$id] = $contentInfo;
118
        }
119
120
        return $list;
121
    }
122
123
    /**
124
     * {@inheritdoc}
125
     */
126
    public function loadContentInfoByRemoteId($remoteId)
127
    {
128
        $cacheItem = $this->cache->getItem("ez-content-info-byRemoteId-${remoteId}");
129
        if ($cacheItem->isHit()) {
130
            return $cacheItem->get();
131
        }
132
133
        $this->logger->logCall(__METHOD__, array('content' => $remoteId));
134
        $contentInfo = $this->persistenceHandler->contentHandler()->loadContentInfoByRemoteId($remoteId);
135
        $cacheItem->set($contentInfo);
136
        $cacheItem->tag($this->getCacheTags($contentInfo));
137
        $this->cache->save($cacheItem);
138
139
        return $contentInfo;
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145
    public function loadVersionInfo($contentId, $versionNo)
146
    {
147
        $cacheItem = $this->cache->getItem("ez-content-version-info-${contentId}-${versionNo}");
148
        if ($cacheItem->isHit()) {
149
            return $cacheItem->get();
150
        }
151
152
        $this->logger->logCall(__METHOD__, ['content' => $contentId, 'version' => $versionNo]);
153
        $versionInfo = $this->persistenceHandler->contentHandler()->loadVersionInfo($contentId, $versionNo);
154
        $cacheItem->set($versionInfo);
155
        $cacheItem->tag($this->getCacheTags($versionInfo->contentInfo));
156
        $this->cache->save($cacheItem);
157
158
        return $versionInfo;
159
    }
160
161
    /**
162
     * {@inheritdoc}
163
     */
164
    public function loadDraftsForUser($userId)
165
    {
166
        $this->logger->logCall(__METHOD__, array('user' => $userId));
167
168
        return $this->persistenceHandler->contentHandler()->loadDraftsForUser($userId);
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174
    public function setStatus($contentId, $status, $versionNo)
175
    {
176
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'status' => $status, 'version' => $versionNo));
177
        $return = $this->persistenceHandler->contentHandler()->setStatus($contentId, $status, $versionNo);
178
179
        $this->cache->deleteItem("ez-content-version-info-${contentId}-${versionNo}");
180
        if ($status === VersionInfo::STATUS_PUBLISHED) {
181
            $this->cache->invalidateTags(['content-' . $contentId]);
182
        } else {
183
            $this->cache->invalidateTags(["content-$contentId-version-list"]);
184
        }
185
186
        return $return;
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192
    public function updateMetadata($contentId, MetadataUpdateStruct $struct)
193
    {
194
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'struct' => $struct));
195
        $contentInfo = $this->persistenceHandler->contentHandler()->updateMetadata($contentId, $struct);
196
        $this->cache->invalidateTags(['content-' . $contentId]);
197
198
        return $contentInfo;
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204
    public function updateContent($contentId, $versionNo, UpdateStruct $struct)
205
    {
206
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo, 'struct' => $struct));
207
        $content = $this->persistenceHandler->contentHandler()->updateContent($contentId, $versionNo, $struct);
208
        $this->cache->invalidateTags(['content-' . $contentId]);
209
210
        return $content;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216
    public function deleteContent($contentId)
217
    {
218
        $this->logger->logCall(__METHOD__, array('content' => $contentId));
219
220
        // Load reverse field relations first
221
        $reverseRelations = $this->persistenceHandler->contentHandler()->loadReverseRelations(
222
            $contentId,
223
            APIRelation::FIELD
224
        );
225
226
        $return = $this->persistenceHandler->contentHandler()->deleteContent($contentId);
227
228
        $this->cache->invalidateTags(['content-' . $contentId]);
229
        if (!empty($reverseRelations)) {
230
            $this->cache->invalidateTags(
231
                array_map(
232
                    function ($relation) {
233
                        // only the full content object *with* fields is affected by this
234
                        return 'content-fields-' . $relation->sourceContentId;
235
                    },
236
                    $reverseRelations
237
                )
238
            );
239
        }
240
241
        return $return;
242
    }
243
244
    /**
245
     * {@inheritdoc}
246
     */
247
    public function deleteVersion($contentId, $versionNo)
248
    {
249
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo));
250
        $return = $this->persistenceHandler->contentHandler()->deleteVersion($contentId, $versionNo);
251
        $this->cache->invalidateTags(['content-' . $contentId]);
252
253
        return $return;
254
    }
255
256
    /**
257
     * {@inheritdoc}
258
     */
259
    public function listVersions($contentId, $status = null, $limit = -1)
260
    {
261
        $cacheItem = $this->cache->getItem("ez-content-${contentId}-version-list" . ($status ? "-byStatus-${status}" : ''));
262
        if ($cacheItem->isHit()) {
263
            return $cacheItem->get();
264
        }
265
266
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'status' => $status));
267
        $versions = $this->persistenceHandler->contentHandler()->listVersions($contentId, $status, $limit);
268
        $cacheItem->set($versions);
269
        $tags = ["content-$contentId", "content-$contentId-version-list"];
270
        $cacheItem->tag(empty($versions) ? $tags : $this->getCacheTags($versions[0]->contentInfo, false, $tags));
271
        $this->cache->save($cacheItem);
272
273
        return $versions;
274
    }
275
276
    /**
277
     * {@inheritdoc}
278
     */
279
    public function addRelation(RelationCreateStruct $relation)
280
    {
281
        $this->logger->logCall(__METHOD__, array('struct' => $relation));
282
283
        return $this->persistenceHandler->contentHandler()->addRelation($relation);
284
    }
285
286
    /**
287
     * {@inheritdoc}
288
     */
289
    public function removeRelation($relationId, $type)
290
    {
291
        $this->logger->logCall(__METHOD__, array('relation' => $relationId, 'type' => $type));
292
        $this->persistenceHandler->contentHandler()->removeRelation($relationId, $type);
293
    }
294
295
    /**
296
     * {@inheritdoc}
297
     */
298
    public function loadRelations($sourceContentId, $sourceContentVersionNo = null, $type = null)
299
    {
300
        $this->logger->logCall(
301
            __METHOD__,
302
            array(
303
                'content' => $sourceContentId,
304
                'version' => $sourceContentVersionNo,
305
                'type' => $type,
306
            )
307
        );
308
309
        return $this->persistenceHandler->contentHandler()->loadRelations($sourceContentId, $sourceContentVersionNo, $type);
310
    }
311
312
    /**
313
     * {@inheritdoc}
314
     */
315
    public function loadReverseRelations($destinationContentId, $type = null)
316
    {
317
        $this->logger->logCall(__METHOD__, array('content' => $destinationContentId, 'type' => $type));
318
319
        return $this->persistenceHandler->contentHandler()->loadReverseRelations($destinationContentId, $type);
320
    }
321
322
    /**
323
     * {@inheritdoc}
324
     */
325
    public function publish($contentId, $versionNo, MetadataUpdateStruct $struct)
326
    {
327
        $this->logger->logCall(__METHOD__, array('content' => $contentId, 'version' => $versionNo, 'struct' => $struct));
328
        $content = $this->persistenceHandler->contentHandler()->publish($contentId, $versionNo, $struct);
329
        $this->cache->invalidateTags(['content-' . $contentId]);
330
331
        return $content;
332
    }
333
334
    /**
335
     * {@inheritdoc}
336
     */
337
    public function removeTranslationFromContent($contentId, $languageCode)
338
    {
339
        $this->deleteTranslationFromContent($contentId, $languageCode);
340
    }
341
342
    /**
343
     * {@inheritdoc}
344
     */
345
    public function deleteTranslationFromContent($contentId, $languageCode)
346
    {
347
        $this->logger->logCall(
348
            __METHOD__,
349
            [
350
                'contentId' => $contentId,
351
                'languageCode' => $languageCode,
352
            ]
353
        );
354
355
        $this->persistenceHandler->contentHandler()->deleteTranslationFromContent($contentId, $languageCode);
356
        $this->cache->invalidateTags(['content-' . $contentId]);
357
    }
358
359
    /**
360
     * {@inheritdoc}
361
     */
362
    public function deleteTranslationFromDraft($contentId, $versionNo, $languageCode)
363
    {
364
        $this->logger->logCall(
365
            __METHOD__,
366
            ['content' => $contentId, 'version' => $versionNo, 'languageCode' => $languageCode]
367
        );
368
        $content = $this->persistenceHandler->contentHandler()->deleteTranslationFromDraft(
369
            $contentId,
370
            $versionNo,
371
            $languageCode
372
        );
373
        $this->cache->invalidateTags(['content-' . $contentId]);
374
375
        return $content;
376
    }
377
378
    /**
379
     * Return relevant content and location tags so cache can be purged reliably.
380
     *
381
     * For use when generating cache, not on invalidation.
382
     *
383
     * @param \eZ\Publish\SPI\Persistence\Content\ContentInfo $contentInfo
384
     * @param bool $withFields Set to true if item contains fields which should be expired on relation or type updates.
385
     * @param array $tags Optional, can be used to specify other tags.
386
     *
387
     * @return array
388
     */
389
    private function getCacheTags(ContentInfo $contentInfo, $withFields = false, array $tags = [])
390
    {
391
        $tags[] = 'content-' . $contentInfo->id;
392
393
        if ($withFields) {
394
            $tags[] = 'content-fields-' . $contentInfo->id;
395
            $tags[] = 'content-fields-type-' . $contentInfo->contentTypeId;
396
        }
397
398 View Code Duplication
        if ($contentInfo->mainLocationId) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
399
            $locations = $this->persistenceHandler->locationHandler()->loadLocationsByContent($contentInfo->id);
400
            foreach ($locations as $location) {
401
                $tags[] = 'location-' . $location->id;
402
                foreach (explode('/', trim($location->pathString, '/')) as $pathId) {
403
                    $tags[] = 'location-path-' . $pathId;
404
                }
405
            }
406
        }
407
408
        return array_unique($tags);
409
    }
410
}
411