create('cache_class', [ 'comment' => 'Pfad der Datei, die die StudipCache-Klasse enthält', 'value' => $class] ); $cfg->create('cache_class_file', [ 'comment' => 'Klassenname des zu verwendenden StudipCaches', 'value' => $file] ); $cfg->create('cache_init_args', [ 'comment' => 'JSON-kodiertes Array von Argumenten für die Instanziierung der StudipCache-Klasse', 'value' => $arguments] ); $cfg->store('cache_class', $class); $cfg->store('cache_class_file', $file); $cfg->store('cache_init_args', $arguments); } /** * Resets the configuration and voids the cache instance. * * @return void */ public static function unconfigure() { self::$cache = NULL; } /** * Returns a cache instance. * * @param bool $apply_proxied_operations Whether or not to apply any * proxied (disable this in tests!) * @return StudipCache the cache instance */ public static function getCache($apply_proxied_operations = true) { if (is_null(self::$cache)) { $proxied = false; if (!$GLOBALS['CACHING_ENABLE']) { self::$cache = new StudipMemoryCache(); // Proxy cache operations if CACHING_ENABLE is different from the globally set // caching value. This should only be the case in cli mode. if (isset($GLOBALS['GLOBAL_CACHING_ENABLE']) && $GLOBALS['GLOBAL_CACHING_ENABLE']) { $proxied = true; } } else { try { $class = self::loadCacheClass(); $args = self::retrieveConstructorArguments(); self::$cache = self::instantiateCache($class, $args); } catch (Exception $e) { error_log(__METHOD__ . ': ' . $e->getMessage()); PageLayout::addBodyElements(MessageBox::error(__METHOD__ . ': ' . $e->getMessage())); $class = self::DEFAULT_CACHE_CLASS; self::$cache = new $class(); } } // If proxy should be used, inject it. Otherwise apply pending // operations, if any. if ($proxied) { self::$cache = new StudipCacheProxy(self::$cache); } elseif ($GLOBALS['CACHING_ENABLE'] && $apply_proxied_operations) { // Even if the above condition will try to eliminate most // failures, the following operation still needs to be wrapped // in a try/catch block. Otherwise there are no means to // execute migration 166 which creates the neccessary tables // for said operation. try { StudipCacheOperation::apply(self::$cache); } catch (Exception $e) { } } } return self::$cache; } /** * Load configured cache class and return its name. * * @return string the name of the configured cache class */ public static function loadCacheClass() { $cacheConfig = self::getConfig()->SYSTEMCACHE; $cache_class = $cacheConfig['type'] ?: null; # default class if (is_null($cache_class)) { $version = new DBSchemaVersion(); if ($version->get(1) < 224) { // db cache is not yet available, use StudipMemoryCache return 'StudipMemoryCache'; } return self::DEFAULT_CACHE_CLASS; } # already loaded if (class_exists($cache_class)) { return $cache_class; } $loaded = false; if (file_exists($cache_class_file) || file_exists($GLOBALS['STUDIP_BASE_PATH'] . '/' . $cache_class_file)) { $loaded = include $cache_class_file; } if ($loaded === FALSE || !class_exists($cache_class)) { # TODO (mlunzena) a more specific exception would be welcome here throw new Exception("Could not find class: '$cache_class'"); } return $cache_class; } /** * Return an array of arguments required for instantiation of the cache * class. * * @return array the array of arguments */ public static function retrieveConstructorArguments() { $cacheConfig = self::getConfig()->SYSTEMCACHE; return $cacheConfig ?: []; } /** * Return an instance of a given class using some arguments * * @param string the name of the class * @param array an array of arguments to be used by the constructor * * @return StudipCache an instance of the specified class */ public static function instantiateCache($class, $arguments) { $reflection_class = new ReflectionClass($class); return (is_array($arguments['config']) && count($arguments['config']) > 0) ? $reflection_class->newInstanceArgs($arguments['config']) : $reflection_class->newInstance(); } }