diff options
| author | Jan-Hendrik Willms <tleilax+github@gmail.com> | 2021-07-22 16:07:19 +0200 |
|---|---|---|
| committer | Jan-Hendrik Willms <tleilax+github@gmail.com> | 2021-07-22 16:19:12 +0200 |
| commit | a3da1483a9e689846179159355badfec8073dbec (patch) | |
| tree | 770dcca6bdf5f6f2a11b0e7fcbbeda6919a3fc52 /lib/classes/StudipCacheFactory.class.php | |
current code from svn, revision 62608
Diffstat (limited to 'lib/classes/StudipCacheFactory.class.php')
| -rw-r--r-- | lib/classes/StudipCacheFactory.class.php | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/lib/classes/StudipCacheFactory.class.php b/lib/classes/StudipCacheFactory.class.php new file mode 100644 index 0000000..ce79383 --- /dev/null +++ b/lib/classes/StudipCacheFactory.class.php @@ -0,0 +1,245 @@ +<?php +/** + * This factory retrieves the instance of StudipCache configured for use in + * this Stud.IP installation. + * + * @package studip + * @subpackage lib + * + * @author Marco Diedrich (mdiedric@uos) + * @author Marcus Lunzenauer (mlunzena@uos.de) + * @copyright 2007 (c) Authors + * @since 1.6 + * @license GPL2 or any later version + */ + +class StudipCacheFactory +{ + /** + * the default cache class + * + * @var string + */ + const DEFAULT_CACHE_CLASS = StudipDbCache::class; + + /** + * singleton instance + * + * @var StudipCache + */ + private static $cache; + + + /** + * config instance + * + * @var Config + */ + private static $config = null; + + + /** + * Returns the currently used config instance + * + * @return Config an instance of class Config used by this factory to + * determine the class of the actual implementation of + * the StudipCache interface; if no config was set, it + * returns the instance returned by Config#getInstance + * @see Config + */ + public static function getConfig() + { + return is_null(self::$config) ? Config::getInstance() : self::$config; + } + + + /** + * @param Config an instance of class Config which will be used to + * determine the class of the implementation of interface + * StudipCache + * + * @return void + */ + public static function setConfig($config) + { + self::$config = $config; + self::$cache = NULL; + } + + + /** + * Configure the file, class and arguments used for instantiation of the + * StudipCache instance. After sending this method, the previously used cache + * instance is voided and a new instance will be created on demand. + * + * @param string the absolute path to the implementing class + * @param string the name of the class + * @param array an array of custom arguments + * + * @return void + */ + public static function configure($file, $class, $arguments) + { + # TODO encoding for strings... but probably the caller should care.. + $arguments = json_encode($arguments); + + // strip leading STUDIP_BASE_PATH from file path + $file = studip_relative_path($file); + + self::unconfigure(); + + $cfg = self::getConfig(); + + $cfg->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 = Config::get()->SYSTEMCACHE; + + $cache_class = $cacheConfig['type'] ?: null; + + # default class + if (is_null($cache_class)) { + $version = new DBSchemaVersion(); + if (!$version->contains(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 = Config::get()->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(); + } +} |
