@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.)
hq.recaptime.dev/wiki/Phorge
phorge
phabricator
1<?php
2
3/**
4 * Key-value cache implemented in the current request. All storage is local
5 * to this request (i.e., the current page) and destroyed after the request
6 * exits. This means the first request to this cache for a given key on a page
7 * will ALWAYS miss.
8 *
9 * This cache exists mostly to support unit tests. In a well-designed
10 * applications, you generally should not be fetching the same data over and
11 * over again in one request, so this cache should be of limited utility.
12 * If using this cache improves application performance, especially if it
13 * improves it significantly, it may indicate an architectural problem in your
14 * application.
15 */
16final class PhutilInRequestKeyValueCache extends PhutilKeyValueCache {
17
18 private $cache = array();
19 private $ttl = array();
20 private $limit = 0;
21
22
23 /**
24 * Set a limit on the number of keys this cache may contain.
25 *
26 * When too many keys are inserted, the oldest keys are removed from the
27 * cache. Setting a limit of `0` disables the cache.
28 *
29 * @param int $limit Maximum number of items to store in the cache.
30 * @return $this
31 */
32 public function setLimit($limit) {
33 $this->limit = $limit;
34 return $this;
35 }
36
37
38/* -( Key-Value Cache Implementation )------------------------------------- */
39
40
41 public function isAvailable() {
42 return true;
43 }
44
45 public function getKeys(array $keys) {
46 $results = array();
47 $now = time();
48 foreach ($keys as $key) {
49 if (!isset($this->cache[$key]) && !array_key_exists($key, $this->cache)) {
50 continue;
51 }
52 if (isset($this->ttl[$key]) && ($this->ttl[$key] < $now)) {
53 continue;
54 }
55 $results[$key] = $this->cache[$key];
56 }
57
58 return $results;
59 }
60
61 public function setKeys(array $keys, $ttl = null) {
62
63 foreach ($keys as $key => $value) {
64 $this->cache[$key] = $value;
65 }
66
67 if ($ttl) {
68 $end = time() + $ttl;
69 foreach ($keys as $key => $value) {
70 $this->ttl[$key] = $end;
71 }
72 } else {
73 foreach ($keys as $key => $value) {
74 unset($this->ttl[$key]);
75 }
76 }
77
78 if ($this->limit) {
79 $count = count($this->cache);
80 if ($count > $this->limit) {
81 $remove = array();
82 foreach ($this->cache as $key => $value) {
83 $remove[] = $key;
84
85 $count--;
86 if ($count <= $this->limit) {
87 break;
88 }
89 }
90
91 $this->deleteKeys($remove);
92 }
93 }
94
95 return $this;
96 }
97
98 public function deleteKeys(array $keys) {
99 foreach ($keys as $key) {
100 unset($this->cache[$key]);
101 unset($this->ttl[$key]);
102 }
103
104 return $this;
105 }
106
107 public function getAllKeys() {
108 return $this->cache;
109 }
110
111 public function destroyCache() {
112 $this->cache = array();
113 $this->ttl = array();
114
115 return $this;
116 }
117
118}