Completed
Push — 8.x-2.x ( 0cda8a...8af97d )
by Frédéric G.
02:15
created

DrupalMongoDBCache::prepareItem()   D

Complexity

Conditions 10
Paths 11

Size

Total Lines 31
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 14
c 2
b 0
f 0
nc 11
nop 1
dl 0
loc 31
rs 4.8196

How to fix   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
 * @file
4
 * MongoDB cache backend.
5
 * Replace your cache-backend file with this file. See README.txt for details.
6
 */
7
8
include_once dirname(__FILE__) . '/../mongodb_module.php';
9
10
/**
11
 * MonogoDB cache implementation.
12
 *
13
 * This is Drupal's default cache implementation. It uses the MongoDB to store
14
 * cached data. Each cache bin corresponds to a collection by the same name.
15
 */
16
class DrupalMongoDBCache implements DrupalCacheInterface {
17
  protected $bin;
18
19
  function __construct($bin) {
20
    $this->bin = $bin;
21
  }
22
23
  function get($cid) {
24
    $collection = mongodb_collection($this->bin);
25
    // Garbage collection necessary when enforcing a minimum cache lifetime.
26
    $this->garbageCollection($this->bin);
27
    $cache = $collection->findOne(array('_id' => (string)$cid));
28
    return $this->prepareItem($cache);
29
  }
30
31
  function getMultiple(&$cids) {
32
    $collection = mongodb_collection($this->bin);
33
    // Garbage collection necessary when enforcing a minimum cache lifetime.
34
    $this->garbageCollection($this->bin);
35
    $find = array();
36
    $find['_id']['$in'] = array_map('strval', $cids);
37
    $result = $collection->find($find);
38
    $cache = array();
39
    foreach ($result as $item) {
40
      $item = $this->prepareItem($item);
41
      if ($item) {
42
        $cache[$item->cid] = $item;
43
      }
44
    }
45
    $cids = array_diff($cids, array_keys($cache));
46
    return $cache;
47
  }
48
49
  /**
50
   * Garbage collection for get() and getMultiple().
51
   *
52
   * @param $bin
53
   *   The bin being requested.
54
   */
55
  protected function garbageCollection() {
56
    global $user;
57
    $collection = mongodb_collection($this->bin);
58
59
    // Garbage collection necessary when enforcing a minimum cache lifetime.
60
    $cache_flush = variable_get('cache_flush_' . $this->bin, 0);
61
    if ($cache_flush && ($cache_flush + variable_get('cache_lifetime', 0) <= REQUEST_TIME)) {
62
      // Reset the variable immediately to prevent a meltdown in heavy load situations.
63
      variable_set('cache_flush_' . $this->bin, 0);
64
      // Time to flush old cache data
65
66
67
      $find = array('expire' => array('$lte' => $cache_flush, '$ne' => CACHE_PERMANENT));
68
      $collection->remove($find, mongodb_default_write_options(FALSE));
69
    }
70
  }
71
72
  /**
73
   * Prepare a cached item.
74
   *
75
   * Checks that items are either permanent or did not expire, and unserializes
76
   * data as appropriate.
77
   *
78
   * @param $cache
79
   *   An item loaded from cache_get() or cache_get_multiple().
80
   * @return
81
   *   The item with data unserialized as appropriate or FALSE if there is no
82
   *   valid item to load.
83
   */
84
  protected function prepareItem($cache) {
85
    global $user;
86
87
    if (!$cache || !isset($cache['data'])) {
88
      return FALSE;
89
    }
90
    unset($cache['_id']);
91
    $cache = (object)$cache;
92
    // If the data is permanent or we are not enforcing a minimum cache lifetime
93
    // always return the cached data.
94
    if ($cache->expire == CACHE_PERMANENT || !variable_get('cache_lifetime', 0)) {
95
    }
96
    // If enforcing a minimum cache lifetime, validate that the data is
97
    // currently valid for this user before we return it by making sure the cache
98
    // entry was created before the timestamp in the current session's cache
99
    // timer. The cache variable is loaded into the $user object by _drupal_session_read()
100
    // in session.inc. If the data is permanent or we're not enforcing a minimum
101
    // cache lifetime always return the cached data.
102
    if ($cache->expire != CACHE_PERMANENT && variable_get('cache_lifetime', 0) && $user->cache > $cache->created) {
103
      // This cache data is too old and thus not valid for us, ignore it.
104
      return FALSE;
105
    }
106
    if ($cache->data instanceof MongoBinData) {
107
      $cache->data = $cache->data->bin;
108
    }
109
    if ($cache->serialized) {
110
      $cache->data = unserialize($cache->data);
111
    }
112
113
    return $cache;
114
  }
115
116
  function set($cid, $data, $expire = CACHE_PERMANENT) {
117
    $scalar = is_scalar($data);
118
    $entry = array(
119
      '_id' => (string)$cid,
120
      'cid' => (string)$cid,
121
      'created' => REQUEST_TIME,
122
      'expire' => $expire,
123
      'serialized' => !$scalar,
124
      'data' => $scalar ? $data : serialize($data),
125
    );
126
127
    // Use MongoBinData for non-UTF8 strings.
128
    if (is_string($entry['data']) && !drupal_validate_utf8($entry['data'])) {
129
      $entry['data'] = new MongoBinData($entry['data']);
130
    }
131
132
    try {
133
      $collection = mongodb_collection($this->bin);
134
      $collection->save($entry, mongodb_default_write_options(FALSE));
135
    }
136
    catch (Exception $e) {
137
      // The database may not be available, so we'll ignore cache_set requests.
138
    }
139
  }
140
141
  function clear($cid = NULL, $wildcard = FALSE) {
142
    global $user;
143
144
    $collection = mongodb_collection($this->bin);
145
146
    if (empty($cid)) {
147
      if (variable_get('cache_lifetime', 0)) {
148
        // We store the time in the current user's $user->cache variable which
149
        // will be saved into the sessions bin by _drupal_session_write(). We then
150
        // simulate that the cache was flushed for this user by not returning
151
        // cached data that was cached before the timestamp.
152
        $user->cache = REQUEST_TIME;
153
154
        $cache_flush = variable_get('cache_flush_' . $this->bin, 0);
155
        if ($cache_flush == 0) {
156
          // This is the first request to clear the cache, start a timer.
157
          variable_set('cache_flush_' . $this->bin, REQUEST_TIME);
158
        }
159
        elseif (REQUEST_TIME > ($cache_flush + variable_get('cache_lifetime', 0))) {
160
          // Clear the cache for everyone, cache_lifetime seconds have
161
          // passed since the first request to clear the cache.
162
163
          $collection->remove(array('expire' => array('$ne' => CACHE_PERMANENT, '$lte' => REQUEST_TIME)), mongodb_default_write_options(FALSE));
164
          variable_set('cache_flush_' . $this->bin, 0);
165
        }
166
      }
167
      else {
168
        // No minimum cache lifetime, flush all temporary cache entries now.
169
        $collection->remove(array('expire' => array('$ne' => CACHE_PERMANENT, '$lte' => REQUEST_TIME)), mongodb_default_write_options(FALSE));
170
      }
171
    }
172
    else {
173
      if ($wildcard) {
174
        if ($cid == '*') {
175
          $collection->remove();
176
        }
177
        else {
178
          $collection->remove(array('cid' => new MongoRegex('/'. preg_quote($cid) .'.*/')), mongodb_default_write_options(FALSE));
179
        }
180
      }
181
      elseif (is_array($cid)) {
182
        // Delete in chunks when a large array is passed.
183
        do {
184
          $find = array('cid' => array('$in' => array_map('strval', array_splice($cid, 0, 1000))));
185
          $collection->remove($find, mongodb_default_write_options(FALSE));
186
        }
187
        while (count($cid));
188
      }
189
      else {
190
        $collection->remove(array('_id' => (string)$cid), mongodb_default_write_options(FALSE));
191
      }
192
    }
193
  }
194
195
  function isEmpty() {
196
    return !mongodb_collection($this->bin)->findOne();
197
  }
198
}
199