aboutsummaryrefslogtreecommitdiff
path: root/lib/classes/cache/MemcachedCache.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/classes/cache/MemcachedCache.php')
-rw-r--r--lib/classes/cache/MemcachedCache.php151
1 files changed, 151 insertions, 0 deletions
diff --git a/lib/classes/cache/MemcachedCache.php b/lib/classes/cache/MemcachedCache.php
new file mode 100644
index 0000000..1c4b685
--- /dev/null
+++ b/lib/classes/cache/MemcachedCache.php
@@ -0,0 +1,151 @@
+<?php
+
+namespace Studip\Cache;
+
+use Memcached;
+use Psr\Cache\CacheItemInterface;
+
+/**
+ * Cache implementation using memcached.
+ *
+ * @author Marcus Lunzenauer <mlunzena@uos.de>
+ * @copyright (c) Authors
+ * @license GPL2 or any later version
+ * @since 5.0
+ */
+class MemcachedCache extends Cache
+{
+ use KeyTrait;
+
+ private Memcached $memcache;
+
+ /**
+ * @return string A translateable display name for this cache class.
+ */
+ public static function getDisplayName(): string
+ {
+ return _('Memcached');
+ }
+
+ public function __construct($servers)
+ {
+ if (!extension_loaded('memcached')) {
+ throw new \Exception('Memcache extension missing.');
+ }
+
+ $prefix = \Config::get()->STUDIP_INSTALLATION_ID;
+ $this->memcache = new Memcached('studip' . ($prefix ? '-' . $prefix : ''));
+
+ if (count($this->memcache->getServerList()) === 0) {
+ foreach ($servers as $server) {
+ $status = $this->memcache->addServer($server['hostname'], (int) $server['port']);
+
+ if (!$status) {
+ throw new \Exception("Could not add server: {$server['hostname']} @ port {$server['port']}");
+ }
+ }
+ }
+ }
+
+ /**
+ * Expire item from the cache.
+ *
+ * Example:
+ *
+ * # expires foo
+ * $cache->expire('foo');
+ *
+ * @param string $arg a single key.
+ * @returns void
+ */
+ public function expire($arg)
+ {
+ $key = $this->getCacheKey($arg);
+ $this->memcache->delete($key);
+ }
+
+ /**
+ * Expire all items from the cache.
+ */
+ public function flush()
+ {
+ $this->memcache->flush();
+ }
+
+ /**
+ * Return statistics.
+ *
+ * @StudipCache::getStats()
+ *
+ * @return array|array[]
+ */
+ public function getStats(): array
+ {
+ return $this->memcache->getStats();
+ }
+
+ /**
+ * Return the Vue component name and props that handle configuration.
+ *
+ * @see Cache::getConfig()
+ *
+ * @return array
+ */
+ public static function getConfig(): array
+ {
+ $currentCache = \Config::get()->SYSTEMCACHE;
+
+ // Set default config for this cache
+ $currentConfig = [
+ 'servers' => []
+ ];
+
+ // If this cache is set as system cache, use config from global settings.
+ if ($currentCache['type'] == __CLASS__) {
+ $currentConfig = $currentCache['config'];
+ }
+
+ return [
+ 'component' => 'MemcachedCacheConfig',
+ 'props' => $currentConfig
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getItem(string $key): CacheItemInterface
+ {
+ $item = new Item($key);
+ $value = $this->memcache->get($this->getCacheKey($key));
+ if ($this->memcache->getResultCode() !== Memcached::RES_NOTFOUND) {
+ // Set the value, even if it is the boolean value false:
+ $item->setHit();
+ $item->set($value);
+ }
+ return $item;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function hasItem(string $key): bool
+ {
+ return $this->memcache->checkKey($this->getCacheKey($key));
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function save(CacheItemInterface $item): bool
+ {
+ $expiration = $this->getExpiration($item);
+ if ($expiration < 1) {
+ // The item would expire immediately.
+ return false;
+ }
+
+ $real_key = $this->getCacheKey($item->getKey());
+ return $this->memcache->set($real_key, $item->get(), $expiration);
+ }
+}