1: <?php
2:
3: /**
4: * Least Recently Used Cache
5: *
6: * A fixed sized cache that removes the element used last when it reaches its
7: * size limit.
8: *
9: * Based on https://github.com/cash/LRUCache
10: *
11: * @access private
12: *
13: * @package Elgg.Core
14: * @subpackage Cache
15: */
16: class ElggLRUCache implements ArrayAccess {
17: /** @var int */
18: protected $maximumSize;
19:
20: /**
21: * The front of the array contains the LRU element
22: *
23: * @var array
24: */
25: protected $data = array();
26:
27: /**
28: * Create a LRU Cache
29: *
30: * @param int $size The size of the cache
31: * @throws InvalidArgumentException
32: */
33: public function __construct($size) {
34: if (!is_int($size) || $size <= 0) {
35: throw new InvalidArgumentException();
36: }
37: $this->maximumSize = $size;
38: }
39:
40: /**
41: * Get the value cached with this key
42: *
43: * @param int|string $key The key. Strings that are ints are cast to ints.
44: * @param mixed $default The value to be returned if key not found. (Optional)
45: * @return mixed
46: */
47: public function get($key, $default = null) {
48: if (isset($this->data[$key])) {
49: $this->recordAccess($key);
50: return $this->data[$key];
51: } else {
52: return $default;
53: }
54: }
55:
56: /**
57: * Add something to the cache
58: *
59: * @param int|string $key The key. Strings that are ints are cast to ints.
60: * @param mixed $value The value to cache
61: * @return void
62: */
63: public function set($key, $value) {
64: if (isset($this->data[$key])) {
65: $this->data[$key] = $value;
66: $this->recordAccess($key);
67: } else {
68: $this->data[$key] = $value;
69: if ($this->size() > $this->maximumSize) {
70: // remove least recently used element (front of array)
71: reset($this->data);
72: unset($this->data[key($this->data)]);
73: }
74: }
75: }
76:
77: /**
78: * Get the number of elements in the cache
79: *
80: * @return int
81: */
82: public function size() {
83: return count($this->data);
84: }
85:
86: /**
87: * Does the cache contain an element with this key
88: *
89: * @param int|string $key The key
90: * @return boolean
91: */
92: public function containsKey($key) {
93: return isset($this->data[$key]);
94: }
95:
96: /**
97: * Remove the element with this key.
98: *
99: * @param int|string $key The key
100: * @return mixed Value or null if not set
101: */
102: public function remove($key) {
103: if (isset($this->data[$key])) {
104: $value = $this->data[$key];
105: unset($this->data[$key]);
106: return $value;
107: } else {
108: return null;
109: }
110: }
111:
112: /**
113: * Clear the cache
114: *
115: * @return void
116: */
117: public function clear() {
118: $this->data = array();
119: }
120:
121: /**
122: * Moves the element from current position to end of array
123: *
124: * @param int|string $key The key
125: * @return void
126: */
127: protected function recordAccess($key) {
128: $value = $this->data[$key];
129: unset($this->data[$key]);
130: $this->data[$key] = $value;
131: }
132:
133: /**
134: * Assigns a value for the specified key
135: *
136: * @see ArrayAccess::offsetSet()
137: *
138: * @param int|string $key The key to assign the value to.
139: * @param mixed $value The value to set.
140: * @return void
141: */
142: public function offsetSet($key, $value) {
143: $this->set($key, $value);
144: }
145:
146: /**
147: * Get the value for specified key
148: *
149: * @see ArrayAccess::offsetGet()
150: *
151: * @param int|string $key The key to retrieve.
152: * @return mixed
153: */
154: public function offsetGet($key) {
155: return $this->get($key);
156: }
157:
158: /**
159: * Unsets a key.
160: *
161: * @see ArrayAccess::offsetUnset()
162: *
163: * @param int|string $key The key to unset.
164: * @return void
165: */
166: public function offsetUnset($key) {
167: $this->remove($key);
168: }
169:
170: /**
171: * Does key exist?
172: *
173: * @see ArrayAccess::offsetExists()
174: *
175: * @param int|string $key A key to check for.
176: * @return boolean
177: */
178: public function offsetExists($key) {
179: return $this->containsKey($key);
180: }
181: }
182: