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