]> git.mxchange.org Git - friendica.git/blob - include/cache.php
1f805836334ae46a8c25d6bb4bc0e0a41bc2bfc3
[friendica.git] / include / cache.php
1 <?php
2 /**
3  * @file include/cache.php
4  *
5  * @brief Class for storing data for a short time
6  */
7
8 use Friendica\Core\Config;
9 use Friendica\Core\PConfig;
10
11 class Cache {
12         /**
13          * @brief Check for memcache and open a connection if configured
14          *
15          * @return object|boolean The memcache object - or "false" if not successful
16          */
17         public static function memcache() {
18                 if (!function_exists('memcache_connect')) {
19                         return false;
20                 }
21
22                 if (!Config::get('system', 'memcache')) {
23                         return false;
24                 }
25
26                 $memcache_host = Config::get('system', 'memcache_host', '127.0.0.1');
27                 $memcache_port = Config::get('system', 'memcache_port', 11211);
28
29                 $memcache = new Memcache;
30
31                 if (!$memcache->connect($memcache_host, $memcache_port)) {
32                         return false;
33                 }
34
35                 return $memcache;
36         }
37
38         /**
39          * @brief Return the duration for a given cache level
40          *
41          * @param integer $level Cache level
42          *
43          * @return integer The cache duration in seconds
44          */
45         private static function duration($level) {
46                 switch($level) {
47                         case CACHE_MONTH;
48                                 $seconds = 2592000;
49                                 break;
50                         case CACHE_WEEK;
51                                 $seconds = 604800;
52                                 break;
53                         case CACHE_DAY;
54                                 $seconds = 86400;
55                                 break;
56                         case CACHE_HOUR;
57                                 $seconds = 3600;
58                                 break;
59                         case CACHE_HALF_HOUR;
60                                 $seconds = 1800;
61                                 break;
62                         case CACHE_QUARTER_HOUR;
63                                 $seconds = 900;
64                                 break;
65                         case CACHE_FIVE_MINUTES;
66                                 $seconds = 300;
67                                 break;
68                         case CACHE_MINUTE;
69                                 $seconds = 60;
70                                 break;
71                 }
72                 return $seconds;
73         }
74
75         /**
76          * @brief Fetch cached data according to the key
77          *
78          * @param string $key The key to the cached data
79          *
80          * @return mixed Cached $value or "null" if not found
81          */
82         public static function get($key) {
83
84                 $memcache = self::memcache();
85                 if (is_object($memcache)) {
86                         // We fetch with the hostname as key to avoid problems with other applications
87                         $cached = $memcache->get(get_app()->get_hostname().":".$key);
88                         $value = @unserialize($cached);
89
90                         // Only return a value if the serialized value is valid.
91                         // We also check if the db entry is a serialized
92                         // boolean 'false' value (which we want to return).
93                         if ($cached === serialize(false) || $value !== false) {
94                                 return $value;
95                         }
96
97                         return null;
98                 }
99
100                 // Frequently clear cache
101                 self::clear($duration);
102
103                 $r = q("SELECT `v` FROM `cache` WHERE `k`='%s' LIMIT 1",
104                         dbesc($key)
105                 );
106
107                 if (dbm::is_result($r)) {
108                         $cached = $r[0]['v'];
109                         $value = @unserialize($cached);
110
111                         // Only return a value if the serialized value is valid.
112                         // We also check if the db entry is a serialized
113                         // boolean 'false' value (which we want to return).
114                         if ($cached === serialize(false) || $value !== false) {
115                                 return $value;
116                         }
117                 }
118
119                 return null;
120         }
121
122         /**
123          * @brief Put data in the cache according to the key
124          *
125          * The input $value can have multiple formats.
126          *
127          * @param string $key The key to the cached data
128          * @param mixed $valie The value that is about to be stored
129          * @param integer $duration The cache lifespan
130          */
131         public static function set($key, $value, $duration = CACHE_MONTH) {
132
133                 // Do we have an installed memcache? Use it instead.
134                 $memcache = self::memcache();
135                 if (is_object($memcache)) {
136                         // We store with the hostname as key to avoid problems with other applications
137                         $memcache->set(get_app()->get_hostname().":".$key, serialize($value), MEMCACHE_COMPRESSED, self::duration($duration));
138                         return;
139                 }
140
141                 /// @todo store the cache data in the same way like the config data
142                 q("REPLACE INTO `cache` (`k`,`v`,`expire_mode`,`updated`) VALUES ('%s','%s',%d,'%s')",
143                                 dbesc($key),
144                                 dbesc(serialize($value)),
145                                 intval($duration),
146                                 dbesc(datetime_convert()));
147         }
148
149         /**
150          * @brief Remove outdated data from the cache
151          *
152          * @param integer $maxlevel The maximum cache level that is to be cleared
153          */
154         public static function clear($max_level = CACHE_MONTH) {
155
156                 // Clear long lasting cache entries only once a day
157                 if (get_config("system", "cache_cleared_day") < time() - self::duration(CACHE_DAY)) {
158                         if ($max_level == CACHE_MONTH) {
159                                 q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
160                                         dbesc(datetime_convert('UTC','UTC',"now - 30 days")), intval(CACHE_MONTH));
161                         }
162
163                         if ($max_level <= CACHE_WEEK) {
164                                 q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
165                                         dbesc(datetime_convert('UTC','UTC',"now - 7 days")), intval(CACHE_WEEK));
166                         }
167
168                         if ($max_level <= CACHE_DAY) {
169                                 q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
170                                 dbesc(datetime_convert('UTC','UTC',"now - 1 days")), intval(CACHE_DAY));
171                         }
172                         set_config("system", "cache_cleared_day", time());
173                 }
174
175                 if (($max_level <= CACHE_HOUR) && (get_config("system", "cache_cleared_hour")) < time() - self::duration(CACHE_HOUR)) {
176                         q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
177                                 dbesc(datetime_convert('UTC','UTC',"now - 1 hours")), intval(CACHE_HOUR));
178
179                         set_config("system", "cache_cleared_hour", time());
180                 }
181
182                 if (($max_level <= CACHE_HALF_HOUR) && (get_config("system", "cache_cleared_half_hour")) < time() - self::duration(CACHE_HALF_HOUR)) {
183                         q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
184                                 dbesc(datetime_convert('UTC','UTC',"now - 30 minutes")), intval(CACHE_HALF_HOUR));
185
186                         set_config("system", "cache_cleared_half_hour", time());
187                 }
188
189                 if (($max_level <= CACHE_QUARTER_HOUR) && (get_config("system", "cache_cleared_quarter_hour")) < time() - self::duration(CACHE_QUARTER_HOUR)) {
190                         q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
191                                 dbesc(datetime_convert('UTC','UTC',"now - 15 minutes")), intval(CACHE_QUARTER_HOUR));
192
193                         set_config("system", "cache_cleared_quarter_hour", time());
194                 }
195
196                 if (($max_level <= CACHE_FIVE_MINUTES) && (get_config("system", "cache_cleared_five_minute")) < time() - self::duration(CACHE_FIVE_MINUTES)) {
197                         q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
198                                 dbesc(datetime_convert('UTC','UTC',"now - 5 minutes")), intval(CACHE_FIVE_MINUTES));
199
200                         set_config("system", "cache_cleared_five_minute", time());
201                 }
202
203                 if (($max_level <= CACHE_MINUTE) && (get_config("system", "cache_cleared_minute")) < time() - self::duration(CACHE_MINUTE)) {
204                         q("DELETE FROM `cache` WHERE `updated` < '%s' AND `expire_mode` = %d",
205                                 dbesc(datetime_convert('UTC','UTC',"now - 1 minutes")), intval(CACHE_MINUTE));
206
207                         set_config("system", "cache_cleared_minute", time());
208                 }
209         }
210 }