Completed
Push — master ( 89223c...9f8254 )
by Andreas
51:18 queued 05:30
created

midcom_services_cache_module_nap::invalidate()   C

Complexity

Conditions 14
Paths 25

Size

Total Lines 59
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 30
CRAP Score 14.1472

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 14
eloc 33
c 3
b 0
f 0
nc 25
nop 2
dl 0
loc 59
ccs 30
cts 33
cp 0.9091
crap 14.1472
rs 6.2666

How to fix   Long Method    Complexity   

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
 * @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
/**
10
 * This is the NAP caching module. It provides the basic management functionality
11
 * for the various backend databases which will be created based on the root topic of the
12
 * NAP trees.
13
 *
14
 * The actual handling of the various dbs is done with Doctrine Cache, this
15
 * class is responsible for the creation of backend instances and invalidation for NAP
16
 * cache objects. (Which implies that it is fully aware of the data structures
17
 * stored in the cache.)
18
 *
19
 * All entries are indexed by their Midgard Object GUID. The entries in the NAP cache
20
 * basically resemble the arrays within the NAP backend node/leaf cache
21
 *
22
 * NAP caches can be shared over multiple sites, as all site specific data (like
23
 * site prefixes) are evaluated during runtime.
24
 *
25
 * Most of the cache update work is done in midcom_helper_nav_backend,
26
 * so you should look there for details about the caching strategy.
27
 *
28
 * @see midcom_helper_nav_backend
29
 *
30
 * @package midcom.services
31
 */
32
class midcom_services_cache_module_nap extends midcom_services_cache_module
33
{
34
    /**
35
     * {@inheritDoc}
36
     */
37 288
    public function invalidate($guid, $object = null)
38
    {
39 288
        $napobject = $this->get_guid($guid);
40
41 288
        if (!$napobject) {
42
            // The object itself is not in cache, but it still might have a parent that
43
            // needs invalidating (f.x. if it is newly-created or was moved from outside the tree)
44 287
            $napobject = $this->_load_from_guid($guid, $object);
45 287
            if (!$napobject) {
46
                // We couldn't load the object (because it's deleted f.x.) or it is not in NAP.
47
                // Either way, there is nothing more we can do here.
48 262
                return;
49
            }
50
        }
51
52 98
        if ($napobject[MIDCOM_NAV_TYPE] == 'leaf') {
53 2
            $cached_node_id = $napobject[MIDCOM_NAV_NODEID];
54
            // Get parent from DB and compare to catch moves
55 2
            if ($parent = $napobject[MIDCOM_NAV_OBJECT]->get_parent()) {
56 2
                $parent_entry = $this->get_guid($parent->guid);
57 2
                if (   $parent_entry
58 2
                    && $parent_entry[MIDCOM_NAV_ID] != $cached_node_id) {
59
                    $this->backend->delete($parent_entry[MIDCOM_NAV_ID] . '-leaves');
60
                }
61
            }
62 2
            if (!empty($napobject[MIDCOM_NAV_GUID])) {
63 2
                $this->backend->delete($napobject[MIDCOM_NAV_GUID]);
64
            }
65
        } else {
66 98
            $cached_node_id = $napobject[MIDCOM_NAV_ID];
67
68
            //Invalidate subnode cache for the (cached) parent
69 98
            $parent_id = $napobject[MIDCOM_NAV_NODEID];
70 98
            $parent_entry = $this->get_node($parent_id);
71
72 98
            if (   $parent_entry
73 98
                && array_key_exists(MIDCOM_NAV_SUBNODES, $parent_entry)) {
74 2
                unset($parent_entry[MIDCOM_NAV_SUBNODES]);
75 2
                $this->put_node($parent_id, $parent_entry);
76
            }
77
78
            //Cross-check parent value from object to detect topic moves
79 98
            if ($parent = $napobject[MIDCOM_NAV_OBJECT]->get_parent()) {
80 24
                $parent_entry_from_object = $this->get_guid($parent->guid);
81
82 24
                if (    !empty($parent_entry_from_object[MIDCOM_NAV_ID])
83 24
                     && !empty($parent_entry[MIDCOM_NAV_ID])
84 24
                     && $parent_entry_from_object[MIDCOM_NAV_ID] != $parent_entry[MIDCOM_NAV_ID]) {
85
                    unset($parent_entry_from_object[MIDCOM_NAV_SUBNODES]);
86
                    $this->put_node($parent_entry_from_object[MIDCOM_NAV_ID], $parent_entry_from_object);
87
                }
88
            }
89
        }
90
91 98
        $leaves_key = "{$cached_node_id}-leaves";
92
93 98
        $this->backend->delete($cached_node_id);
94 98
        $this->backend->delete($napobject[MIDCOM_NAV_GUID]);
95 98
        $this->backend->delete($leaves_key);
96 98
    }
97
98 287
    private function _load_from_guid(string $guid, $object)
99
    {
100 287
        $napobject = false;
101
        try {
102 287
            if (!is_object($object)) {
103 119
                $object = midcom::get()->dbfactory->get_object_by_guid($guid);
104
            }
105 287
            $nav = new midcom_helper_nav;
106 287
            if ($object instanceof midcom_db_topic) {
107 93
                $napobject = $nav->get_node($object->id);
108 245
            } elseif (   ($node = $nav->find_closest_topic($object))
109 245
                      && $nodeobject = $nav->get_node($node->id)) {
110 287
                $napobject = $nav->get_leaf($nodeobject[MIDCOM_NAV_ID] . '-' . $object->id);
111
            }
112
        } catch (midcom_error $e) {
113
            $e->log();
114
        }
115 287
        return $napobject;
116
    }
117
118
    /**
119
     * Looks up a node in the cache and returns it. Not existent
120
     * keys are caught in this call as well, so you do not need
121
     * to call exists first.
122
     *
123
     * @param string $key The key to look up.
124
     * @return mixed The cached value on success, false on failure.
125
     */
126 143
    public function get_node($key)
127
    {
128 143
        $lang_id = midcom::get()->i18n->get_current_language();
129 143
        $result = $this->backend->fetch($key);
130 143
        if (!isset($result[$lang_id])) {
131 127
            return false;
132
        }
133
134 70
        return $result[$lang_id];
135
    }
136
137
    /**
138
     * Looks up a node in the cache and returns it. Not existent
139
     * keys are caught in this call as well, so you do not need
140
     * to call exists first.
141
     *
142
     * @param string $key The key to look up.
143
     * @return mixed The cached value on success, false on failure.
144
     */
145 40
    public function get_leaves($key)
146
    {
147 40
        $lang_id = midcom::get()->i18n->get_current_language();
148 40
        $result = $this->backend->fetch($key);
149 40
        if (!isset($result[$lang_id])) {
150 37
            return false;
151
        }
152
153 4
        return $result[$lang_id];
154
    }
155
156
    /**
157
     * Sets a given node key in the cache.
158
     *
159
     * @param string $key The key to look up.
160
     * @param mixed $data The data to store.
161
     */
162 111
    public function put_node($key, $data)
163
    {
164 111
        $lang_id = midcom::get()->i18n->get_current_language();
165 111
        $result = $this->backend->fetch($key);
166 111
        if (!is_array($result)) {
167 109
            $result = [];
168
        }
169 111
        $result[$lang_id] = $data;
170 111
        $this->backend->save($key, $result);
171 111
        $this->backend->save($data[MIDCOM_NAV_GUID], $result);
172 111
    }
173
174
    /**
175
     * Save a given array by GUID in the cache.
176
     *
177
     * @param string $guid The key to store.
178
     * @param mixed $data The data to store.
179
     */
180 1
    public function put_guid($guid, $data)
181
    {
182 1
        $lang_id = midcom::get()->i18n->get_current_language();
183 1
        $result = $this->backend->fetch($guid);
184 1
        if (!is_array($result)) {
185 1
            $result = [];
186
        }
187 1
        $result[$lang_id] = $data;
188 1
        $this->backend->save($guid, $result);
189 1
    }
190
191
    /**
192
     * Get a given array by GUID from the cache.
193
     *
194
     * @param string $guid The key to look up.
195
     */
196 295
    public function get_guid($guid)
197
    {
198 295
        $lang_id = midcom::get()->i18n->get_current_language();
199 295
        $result = $this->backend->fetch($guid);
200 295
        if (!isset($result[$lang_id])) {
201 294
            return false;
202
        }
203 56
        return $result[$lang_id];
204
    }
205
206
    /**
207
     * Sets a given leave key in the cache
208
     *
209
     * @param string $key The key to look up.
210
     * @param mixed $data The data to store.
211
     */
212 13
    public function put_leaves($key, $data)
213
    {
214 13
        $lang_id = midcom::get()->i18n->get_current_language();
215 13
        $result = $this->backend->fetch($key);
216 13
        if (!is_array($result)) {
217 13
            $result = [];
218
        }
219 13
        $result[$lang_id] = $data;
220 13
        $this->backend->save($key, $result);
221 13
    }
222
}
223