Passed
Branch master (05c266)
by Andreas
09:55
created

midcom_services_cache_module_memcache   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Test Coverage

Coverage 75.86%

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 85
ccs 22
cts 29
cp 0.7586
rs 10
c 0
b 0
f 0
wmc 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A lookup_parent_data() 0 3 1
A __construct() 0 4 1
A invalidate() 0 8 3
A update_parent_data() 0 3 1
A put() 0 14 2
A get() 0 8 2
1
<?php
2
/**
3
 * @package midcom.services
4
 * @author The Midgard Project, http://www.midgard-project.org
5
 * @copyright The Midgard Project, http://www.midgard-project.org
6
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
7
 */
8
9
use Symfony\Component\Cache\Adapter\AdapterInterface;
10
11
/**
12
 * The Memory caching system is geared to hold needed information available quickly.
13
 * There are a number of limitations you have to deal with, when working with the
14
 * Memory Cache.
15
 *
16
 * Number One, you cannot put arbitrary keys into the cache. Since the memcached
17
 * php extension does not support key listings, you are bound to use MidCOM object
18
 * GUIDs as cache keys, whatever you do. To allow for different subsystems of the
19
 * Framework to share the cache, I have introduce "Data groups", which are suffixes
20
 * for the actual cache information. Thus, all keys in the cache follow a
21
 * "{$datagroup}-{$guid}" naming scheme. These groups need to be registered in the
22
 * MidCOM configuration key <i>cache_module_memcache_data_groups</i>.
23
 *
24
 * Number Two, it is entirely possible (as it is the default), that the memcache
25
 * is actually not available, as no memcache daemon has been found.  This is
26
 * controlled by the <i>cache_module_memcache_backend</i> configuration option,
27
 * which tries to auto-detect a sensible default. If it is set to the name of a caching module
28
 * it will actually start caching. Otherwise it will silently ignore
29
 * put requests, and reports all keys as not existent.
30
 *
31
 * Number Three, as at least memcache's contains() check isn't working on some machines, key
32
 * values of false are forbidden, as they are used to check a keys existence
33
 * during the get cycle. You should also avoid null and 0 members, if possible,
34
 * they could naturally be error prone if you start forgetting about the typed
35
 * comparisons.
36
 *
37
 * <b>Special functionality</b>
38
 *
39
 * - Interface to the PARENT caching group, has a few simple shortcuts to the
40
 *   access the available information.
41
 *
42
 * @package midcom.services
43
 */
44
class midcom_services_cache_module_memcache extends midcom_services_cache_module
45
{
46
    /**
47
     * List of known data groups. See the class introduction for details.
48
     *
49
     * @var array
50
     */
51
    private $_data_groups = [];
52
53
    public function __construct(midcom_config $config, AdapterInterface $backend)
54
    {
55
        parent::__construct($backend);
56
        $this->_data_groups = $config->get_array('cache_module_memcache_data_groups');
57
    }
58
59
    /**
60
     * {@inheritDoc}
61
     */
62 315
    public function invalidate(string $guid, $object = null)
63
    {
64 315
        foreach ($this->_data_groups as $group) {
65 315
            if ($group == 'ACL') {
66 315
                $this->backend->deleteItem("{$group}-SELF-{$guid}");
67 315
                $this->backend->deleteItem("{$group}-CONTENT-{$guid}");
68
            } else {
69 315
                $this->backend->deleteItem("{$group}-{$guid}");
70
            }
71
        }
72
    }
73
74
    /**
75
     * Looks up a value in the cache and returns it. Not existent
76
     * keys are caught in this call as well
77
     *
78
     * @return mixed The cached value on success, false on failure.
79
     */
80 327
    public function get(string $data_group, string $key)
81
    {
82 327
        $item = $this->backend->getItem("{$data_group}-{$key}");
83 327
        if ($item->isHit()) {
84 3
            return $item->get();
85
        }
86
87 327
        return false;
88
    }
89
90
    /**
91
     * Sets a given key in the cache. If the data group is unknown, a Warning-Level error
92
     * is logged and putting is denied.
93
     */
94 325
    public function put(string $data_group, string $key, $data, int $timeout = null)
95
    {
96 325
        if (!in_array($data_group, $this->_data_groups)) {
97
            debug_add("Tried to add data to the unknown data group {$data_group}, cannot do that.", MIDCOM_LOG_WARN);
98
            debug_print_r('Known data groups:', $this->_data_groups);
99
            debug_print_function_stack('We were called from here:');
100
            return;
101
        }
102 325
        $item = $this->backend
103 325
            ->getItem("{$data_group}-{$key}")
104 325
            ->set($data)
105 325
            ->expiresAfter($timeout);
106
107 325
        $this->backend->save($item);
108
    }
109
110
    /**
111
     * This is a little helper that tries to look up a GUID in the memory
112
     * cache's PARENT data group. If it is not found, false is returned.
113
     * If the object has no parent, the array value is null
114
     *
115
     * @return array|false The classname => GUID pair or false when nothing is in cache
116
     */
117 309
    public function lookup_parent_data(string $guid)
118
    {
119 309
        return $this->get('PARENT', $guid);
120
    }
121
122
    /**
123
     * This is a little helper that saves a parent GUID and class in the memory
124
     * cache's PARENT data group.
125
     */
126 309
    public function update_parent_data(string $object_guid, array $parent_data)
127
    {
128 309
        $this->put('PARENT', $object_guid, $parent_data);
129
    }
130
}
131