Completed
Push — master ( d5499f...cf5cfd )
by André
17:03
created

AbstractHandler::getMultipleCacheItems()   C

Complexity

Conditions 8
Paths 25

Size

Total Lines 52
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 34
nc 25
nop 4
dl 0
loc 52
rs 6.8493
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\SPI\Persistence\Handler as PersistenceHandler;
12
use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
13
14
/**
15
 * Class AbstractHandler.
16
 *
17
 * Abstract handler for use in other Persistence Cache Handlers.
18
 */
19
abstract class AbstractHandler
20
{
21
    /**
22
     * @var \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface
23
     */
24
    protected $cache;
25
26
    /**
27
     * @var \eZ\Publish\SPI\Persistence\Handler
28
     */
29
    protected $persistenceHandler;
30
31
    /**
32
     * @var \eZ\Publish\Core\Persistence\Cache\PersistenceLogger
33
     */
34
    protected $logger;
35
36
    /**
37
     * Setups current handler with everything needed.
38
     *
39
     * @param \Symfony\Component\Cache\Adapter\TagAwareAdapterInterface $cache
40
     * @param \eZ\Publish\SPI\Persistence\Handler $persistenceHandler
41
     * @param \eZ\Publish\Core\Persistence\Cache\PersistenceLogger $logger
42
     */
43
    public function __construct(
44
        TagAwareAdapterInterface $cache,
45
        PersistenceHandler $persistenceHandler,
46
        PersistenceLogger $logger
47
    ) {
48
        $this->cache = $cache;
49
        $this->persistenceHandler = $persistenceHandler;
50
        $this->logger = $logger;
51
    }
52
53
    /**
54
     * Helper for getting multiple cache items in one call and do the id extraction for you.
55
     *
56
     * Cache items must be stored with a key in the following format "${keyPrefix}${id}", like "ez-content-info-${id}",
57
     * in order for this method to be able to prefix key on id's and also extract key prefix afterwards.
58
     *
59
     * @param array $ids
60
     * @param string $keyPrefix
61
     * @param callable $missingLoader Function for loading missing objects, gets array with missing id's as argument,
62
     *                                expects return value to be array with id as key. Missing items should be missing.
63
     * @param callable $loadedTagger Function for tagging loaded object, gets object as argument, return array of tags.
64
     *
65
     * @return array
66
     */
67
    final protected function getMultipleCacheItems(
68
        array $ids,
69
        string $keyPrefix,
70
        callable $missingLoader,
71
        callable $loadedTagger
72
    ): array {
73
        if (empty($ids)) {
74
            return [];
75
        }
76
77
        // Generate unique cache keys
78
        $cacheKeys = [];
79
        foreach (array_unique($ids) as $id) {
80
            $cacheKeys[] = $keyPrefix . $id;
81
        }
82
83
        // Load cache items by cache keys (will contain hits and misses)
84
        $list = [];
85
        $cacheMisses = [];
86
        $keyPrefixLength = strlen($keyPrefix);
87
        foreach ($this->cache->getItems($cacheKeys) as $key => $cacheItem) {
88
            $id = substr($key, $keyPrefixLength);
89
            if ($cacheItem->isHit()) {
90
                $list[$id] = $cacheItem->get();
91
            } else {
92
                $cacheMisses[] = $id;
93
                $list[$id] = $cacheItem;
94
            }
95
        }
96
97
        // No misses, return completely cached list
98
        if (empty($cacheMisses)) {
99
            return $list;
100
        }
101
102
        // Load missing items, save to cache & apply to list if found
103
        $loadedList = $missingLoader($cacheMisses);
104
        foreach ($cacheMisses as $id) {
105
            if (isset($loadedList[$id])) {
106
                $this->cache->save(
107
                    $list[$id]
108
                        ->set($loadedList[$id])
109
                        ->tag($loadedTagger($loadedList[$id]))
110
                );
111
                $list[$id] = $loadedList[$id];
112
            } else {
113
                unset($list[$id]);
114
            }
115
        }
116
117
        return $list;
118
    }
119
}
120