/**
  * Performs custom validation for us.
  *
  * @param array $data An array of data sent to the form.
  * @param array $files An array of files sent to the form.
  * @return array An array of errors.
  */
 protected function configuration_validation($data, $files)
 {
     $errors = array();
     if (!array_key_exists('prefix', $data)) {
         $prefix = '';
     } else {
         $prefix = clean_param($data['prefix'], PARAM_ALPHANUM);
     }
     $factory = cache_factory::instance();
     $config = $factory->create_config_instance();
     foreach ($config->get_all_stores() as $store) {
         if ($store['plugin'] !== 'xcache') {
             continue;
         }
         if (empty($store['configuration']['prefix'])) {
             $storeprefix = '';
         } else {
             $storeprefix = $store['configuration']['prefix'];
         }
         if ($storeprefix === $prefix) {
             $errors['prefix'] = get_string('erroruniqueprefix');
         }
     }
     return $errors;
 }
Пример #2
0
 /**
  * Validates the configuration data.
  *
  * We need to check that prefix is unique.
  *
  * @param array $data
  * @param array $files
  * @param array $errors
  * @return array
  * @throws coding_exception
  */
 public function configuration_validation($data, $files, array $errors)
 {
     if (empty($errors['prefix'])) {
         $factory = cache_factory::instance();
         $config = $factory->create_config_instance();
         foreach ($config->get_all_stores() as $store) {
             if ($store['plugin'] === 'apcu') {
                 if (isset($store['configuration']['prefix'])) {
                     if ($data['prefix'] === $store['configuration']['prefix']) {
                         // The new store has the same prefix as an existing store, thats a problem.
                         $errors['prefix'] = get_string('prefixnotunique', 'cachestore_apcu');
                         break;
                     }
                 } else {
                     if (empty($data['prefix'])) {
                         // The existing store hasn't got a prefix and neither does the new store, that's a problem.
                         $errors['prefix'] = get_string('prefixnotunique', 'cachestore_apcu');
                         break;
                     }
                 }
             }
         }
     }
     return $errors;
 }
Пример #3
0
 /**
  * Returns an instance of the cache_factor method.
  *
  * @param bool $forcereload If set to true a new cache_factory instance will be created and used.
  * @return cache_factory
  */
 public static function instance($forcereload = false)
 {
     if ($forcereload || self::$instance === null) {
         self::$instance = new cache_factory();
     }
     return self::$instance;
 }
Пример #4
0
 /**
  * Creates the default configuration and saves it.
  *
  * This function calls config_save, however it is safe to continue using it afterwards as this function should only ever
  * be called when there is no configuration file already.
  *
  * @param bool $forcesave If set to true then we will forcefully save the default configuration file.
  * @return true|array Returns true if the default configuration was successfully created.
  *     Returns a configuration array if it could not be saved. This is a bad situation. Check your error logs.
  */
 public static function create_default_configuration($forcesave = false)
 {
     global $CFG;
     // HACK ALERT.
     // We probably need to come up with a better way to create the default stores, or at least ensure 100% that the
     // default store plugins are protected from deletion.
     $writer = new self();
     $writer->configstores = self::get_default_stores();
     $writer->configdefinitions = self::locate_definitions();
     $defaultapplication = 'default_application';
     $appdefine = defined('TEST_CACHE_USING_APPLICATION_STORE') ? TEST_CACHE_USING_APPLICATION_STORE : false;
     if ($appdefine !== false && preg_match('/^[a-zA-Z][a-zA-Z0-9_]+$/', $appdefine)) {
         $expectedstore = $appdefine;
         $expecteddefine = 'TEST_CACHESTORE_' . strtoupper($expectedstore) . '_TESTSERVERS';
         $file = $CFG->dirroot . '/cache/stores/' . $appdefine . '/lib.php';
         $class = 'cachestore_' . $appdefine;
         if (file_exists($file)) {
             require_once $file;
         }
         if (defined($expecteddefine) && class_exists($class)) {
             /** @var cache_store $class */
             $writer->configstores['test_application'] = array('use_test_store' => true, 'name' => 'test_application', 'plugin' => $expectedstore, 'alt' => $writer->configstores[$defaultapplication], 'modes' => $class::get_supported_modes(), 'features' => $class::get_supported_features());
             $defaultapplication = 'test_application';
         }
     }
     $writer->configmodemappings = array(array('mode' => cache_store::MODE_APPLICATION, 'store' => $defaultapplication, 'sort' => -1), array('mode' => cache_store::MODE_SESSION, 'store' => 'default_session', 'sort' => -1), array('mode' => cache_store::MODE_REQUEST, 'store' => 'default_request', 'sort' => -1));
     $writer->configlocks = array('default_file_lock' => array('name' => 'cachelock_file_default', 'type' => 'cachelock_file', 'dir' => 'filelocks', 'default' => true));
     $factory = cache_factory::instance();
     // We expect the cache to be initialising presently. If its not then something has gone wrong and likely
     // we are now in a loop.
     if (!$forcesave && $factory->get_state() !== cache_factory::STATE_INITIALISING) {
         return $writer->generate_configuration_array();
     }
     $factory->set_state(cache_factory::STATE_SAVING);
     $writer->config_save();
     return true;
 }
Пример #5
0
 /**
  * Disables as much of the cache API as possible.
  *
  * All of the magic associated with the disabled cache is wrapped into this function.
  * In switching out the factory for the disabled factory it gains full control over the initialisation of objects
  * and can use all of the disabled alternatives.
  * Simple!
  *
  * This function has been marked as protected so that it cannot be abused through the public API presently.
  * Perhaps in the future we will allow this, however as per the build up to the first release containing
  * MUC it was decided that this was just to risky and abusable.
  */
 protected static function disable()
 {
     global $CFG;
     require_once $CFG->dirroot . '/cache/disabledlib.php';
     self::$instance = new cache_factory_disabled();
 }
Пример #6
0
 case 'purgestore':
 case 'purge':
     // Purge a store cache.
     $store = required_param('store', PARAM_TEXT);
     cache_helper::purge_store($store);
     redirect($PAGE->url, get_string('purgestoresuccess', 'cache'), 5);
     break;
 case 'newlockinstance':
     // Adds a new lock instance.
     $lock = required_param('lock', PARAM_ALPHANUMEXT);
     $mform = cache_administration_helper::get_add_lock_form($lock);
     if ($mform->is_cancelled()) {
         redirect($PAGE->url);
     } else {
         if ($data = $mform->get_data()) {
             $factory = cache_factory::instance();
             $config = $factory->create_config_instance(true);
             $name = $data->name;
             $data = cache_administration_helper::get_lock_configuration_from_data($lock, $data);
             $config->add_lock_instance($name, $lock, $data);
             redirect($PAGE->url, get_string('addlocksuccess', 'cache', $name), 5);
         }
     }
     break;
 case 'deletelock':
     // Deletes a lock instance.
     $lock = required_param('lock', PARAM_ALPHANUMEXT);
     $confirm = optional_param('confirm', false, PARAM_BOOL);
     if (!array_key_exists($lock, $locks)) {
         $notifysuccess = false;
         $notification = get_string('invalidlock', 'cache');
Пример #7
0
 /**
  * Gets all of the stores that are to be used for the given definition.
  *
  * @param cache_definition $definition
  * @return array
  */
 public function get_stores_for_definition(cache_definition $definition)
 {
     // Check if MUC has been disabled.
     $factory = cache_factory::instance();
     if ($factory->stores_disabled()) {
         // Yip its been disabled.
         // To facilitate this we are going to always return an empty array of stores to use.
         // This will force all cache instances to use the cachestore_dummy.
         // MUC will still be used essentially so that code using it will still continue to function but because no cache stores
         // are being used interaction with MUC will be purely based around a static var.
         return array();
     }
     $availablestores = $this->get_stores($definition->get_mode(), $definition->get_requirements_bin());
     $stores = array();
     $id = $definition->get_id();
     // Now get any mappings and give them priority.
     foreach ($this->configdefinitionmappings as $mapping) {
         if ($mapping['definition'] !== $id) {
             continue;
         }
         $storename = $mapping['store'];
         if (!array_key_exists($storename, $availablestores)) {
             continue;
         }
         if (array_key_exists($storename, $stores)) {
             $store = $stores[$storename];
             unset($stores[$storename]);
             $stores[$storename] = $store;
         } else {
             $stores[$storename] = $availablestores[$storename];
         }
     }
     if (empty($stores) && !$definition->is_for_mappings_only()) {
         $mode = $definition->get_mode();
         // Load the default stores.
         foreach ($this->configmodemappings as $mapping) {
             if ($mapping['mode'] === $mode && array_key_exists($mapping['store'], $availablestores)) {
                 $store = $availablestores[$mapping['store']];
                 if (empty($store['mappingsonly'])) {
                     $stores[$mapping['store']] = $store;
                 }
             }
         }
     }
     return $stores;
 }
 /**
  * Get an array of stores that are suitable to be used for a given definition.
  *
  * @param string $component
  * @param string $area
  * @return array Array containing 3 elements
  *      1. An array of currently used stores
  *      2. An array of suitable stores
  *      3. An array of default stores
  */
 public static function get_definition_store_options($component, $area)
 {
     $factory = cache_factory::instance();
     $definition = $factory->create_definition($component, $area);
     $config = cache_config::instance();
     $currentstores = $config->get_stores_for_definition($definition);
     $possiblestores = $config->get_stores($definition->get_mode(), $definition->get_requirements_bin());
     $defaults = array();
     foreach ($currentstores as $key => $store) {
         if (!empty($store['default'])) {
             $defaults[] = $key;
             unset($currentstores[$key]);
         }
     }
     foreach ($possiblestores as $key => $store) {
         if ($store['default']) {
             unset($possiblestores[$key]);
             $possiblestores[$key] = $store;
         }
     }
     return array($currentstores, $possiblestores, $defaults);
 }
Пример #9
0
 /**
  * Returns stores suitable for use with a given definition.
  *
  * @param cache_definition $definition
  * @return cache_store[]
  */
 public static function get_stores_suitable_for_definition(cache_definition $definition)
 {
     $factory = cache_factory::instance();
     $stores = array();
     if ($factory->is_initialising() || $factory->stores_disabled()) {
         // No suitable stores here.
         return $stores;
     } else {
         $stores = self::get_cache_stores($definition);
         // If mappingsonly is set, having 0 stores is ok.
         if (count($stores) === 0 && !$definition->is_for_mappings_only()) {
             // No suitable stores we found for the definition. We need to come up with a sensible default.
             // If this has happened we can be sure that the user has mapped custom stores to either the
             // mode of the definition. The first alternative to try is the system default for the mode.
             // e.g. the default file store instance for application definitions.
             $config = $factory->create_config_instance();
             foreach ($config->get_stores($definition->get_mode()) as $name => $details) {
                 if (!empty($details['default'])) {
                     $stores[] = $factory->create_store_from_config($name, $details, $definition);
                     break;
                 }
             }
         }
     }
     return $stores;
 }
Пример #10
0
 /**
  * Test the hash_key functionality.
  */
 public function test_hash_key()
 {
     global $CFG;
     $currentdebugging = $CFG->debug;
     $CFG->debug = E_ALL;
     // First with simplekeys
     $instance = cache_config_phpunittest::instance(true);
     $instance->phpunit_add_definition('phpunit/hashtest', array('mode' => cache_store::MODE_APPLICATION, 'component' => 'phpunit', 'area' => 'hashtest', 'simplekeys' => true));
     $factory = cache_factory::instance();
     $definition = $factory->create_definition('phpunit', 'hashtest');
     $result = cache_helper::hash_key('test', $definition);
     $this->assertEquals('test-' . $definition->generate_single_key_prefix(), $result);
     try {
         cache_helper::hash_key('test/test', $definition);
         $this->fail('Invalid key was allowed, you should see this.');
     } catch (coding_exception $e) {
         $this->assertEquals('test/test', $e->debuginfo);
     }
     // Second without simple keys
     $instance->phpunit_add_definition('phpunit/hashtest2', array('mode' => cache_store::MODE_APPLICATION, 'component' => 'phpunit', 'area' => 'hashtest2', 'simplekeys' => false));
     $definition = $factory->create_definition('phpunit', 'hashtest2');
     $result = cache_helper::hash_key('test', $definition);
     $this->assertEquals(sha1($definition->generate_single_key_prefix() . '-test'), $result);
     $result = cache_helper::hash_key('test/test', $definition);
     $this->assertEquals(sha1($definition->generate_single_key_prefix() . '-test/test'), $result);
     $CFG->debug = $currentdebugging;
 }
Пример #11
0
 /**
  * Purges a cache of all information on a given event.
  *
  * @param string $event
  */
 public static function purge_by_event($event)
 {
     $instance = cache_config::instance();
     $invalidationeventset = false;
     $factory = cache_factory::instance();
     foreach ($instance->get_definitions() as $name => $definitionarr) {
         $definition = cache_definition::load($name, $definitionarr);
         if ($definition->invalidates_on_event($event)) {
             // Purge the cache.
             $cache = $factory->create_cache($definition);
             $cache->purge();
             // We need to flag the event in the "Event invalidation" cache if it hasn't already happened.
             if ($invalidationeventset === false) {
                 // Get the event invalidation cache.
                 $cache = cache::make('core', 'eventinvalidation');
                 // Create a key to invalidate all.
                 $data = array('purged' => cache::now());
                 // Set that data back to the cache.
                 $cache->set($event, $data);
                 // This only needs to occur once.
                 $invalidationeventset = true;
             }
         }
     }
 }
Пример #12
0
 /**
  * Test disabling the cache.
  */
 public function test_disable()
 {
     global $CFG;
     $configfile = $CFG->dataroot . '/muc/config.php';
     // That's right, we're deleting the config file.
     $this->assertTrue(@unlink($configfile));
     // Disable the cache
     cache_phpunit_factory::phpunit_disable();
     // Check we get the expected disabled factory.
     $factory = cache_factory::instance();
     $this->assertInstanceOf('cache_factory_disabled', $factory);
     // Check we get the expected disabled config.
     $config = $factory->create_config_instance();
     $this->assertInstanceOf('cache_config_disabled', $config);
     // Check we get the expected disabled caches.
     $cache = cache::make('phpunit', 'disable');
     $this->assertInstanceOf('cache_disabled', $cache);
     $cache = cache::make_from_params(cache_store::MODE_APPLICATION, 'phpunit', 'disable');
     $this->assertInstanceOf('cache_disabled', $cache);
     $this->assertFalse(file_exists($configfile));
     $this->assertFalse($cache->get('test'));
     $this->assertFalse($cache->set('test', 'test'));
     $this->assertFalse($cache->delete('test'));
     $this->assertTrue($cache->purge());
     cache_factory::reset();
     $factory = cache_factory::instance(true);
     $config = $factory->create_config_instance();
     $this->assertEquals('cache_config_phpunittest', get_class($config));
 }
Пример #13
0
 /**
  * Test that the default stores all support searching.
  */
 public function test_defaults_support_searching()
 {
     $instance = cache_config_testing::instance(true);
     $instance->phpunit_add_definition('phpunit/search1', array('mode' => cache_store::MODE_APPLICATION, 'component' => 'phpunit', 'area' => 'search1', 'requiresearchable' => true));
     $instance->phpunit_add_definition('phpunit/search2', array('mode' => cache_store::MODE_SESSION, 'component' => 'phpunit', 'area' => 'search2', 'requiresearchable' => true));
     $instance->phpunit_add_definition('phpunit/search3', array('mode' => cache_store::MODE_REQUEST, 'component' => 'phpunit', 'area' => 'search3', 'requiresearchable' => true));
     $factory = cache_factory::instance();
     // Test application cache is searchable.
     $definition = $factory->create_definition('phpunit', 'search1');
     $this->assertInstanceOf('cache_definition', $definition);
     $this->assertEquals(cache_store::IS_SEARCHABLE, $definition->get_requirements_bin() & cache_store::IS_SEARCHABLE);
     $cache = $factory->create_cache($definition);
     $this->assertInstanceOf('cache_application', $cache);
     $this->assertArrayHasKey('cache_is_searchable', $cache->phpunit_get_store_implements());
     // Test session cache is searchable.
     $definition = $factory->create_definition('phpunit', 'search2');
     $this->assertInstanceOf('cache_definition', $definition);
     $this->assertEquals(cache_store::IS_SEARCHABLE, $definition->get_requirements_bin() & cache_store::IS_SEARCHABLE);
     $cache = $factory->create_cache($definition);
     $this->assertInstanceOf('cache_session', $cache);
     $this->assertArrayHasKey('cache_is_searchable', $cache->phpunit_get_store_implements());
     // Test request cache is searchable.
     $definition = $factory->create_definition('phpunit', 'search3');
     $this->assertInstanceOf('cache_definition', $definition);
     $this->assertEquals(cache_store::IS_SEARCHABLE, $definition->get_requirements_bin() & cache_store::IS_SEARCHABLE);
     $cache = $factory->create_cache($definition);
     $this->assertInstanceOf('cache_request', $cache);
     $this->assertArrayHasKey('cache_is_searchable', $cache->phpunit_get_store_implements());
 }
Пример #14
0
 /**
  * Cleans old session data from cache stores used for session based definitions.
  *
  * @param bool $output If set to true output will be given.
  */
 public static function clean_old_session_data($output = false)
 {
     global $CFG;
     if ($output) {
         mtrace('Cleaning up stale session data from cache stores.');
     }
     $factory = cache_factory::instance();
     $config = $factory->create_config_instance();
     $definitions = $config->get_definitions();
     $purgetime = time() - $CFG->sessiontimeout;
     foreach ($definitions as $definitionarray) {
         // We are only interested in session caches.
         if (!($definitionarray['mode'] & cache_store::MODE_SESSION)) {
             continue;
         }
         $definition = $factory->create_definition($definitionarray['component'], $definitionarray['area']);
         $stores = $config->get_stores_for_definition($definition);
         // Turn them into store instances.
         $stores = self::initialise_cachestore_instances($stores, $definition);
         // Initialise all of the stores used for that definition.
         foreach ($stores as $store) {
             // If the store doesn't support searching we can skip it.
             if (!$store instanceof cache_is_searchable) {
                 debugging('Cache stores used for session definitions should ideally be searchable.', DEBUG_DEVELOPER);
                 continue;
             }
             // Get all of the keys.
             $keys = $store->find_by_prefix(cache_session::KEY_PREFIX);
             $todelete = array();
             foreach ($store->get_many($keys) as $key => $value) {
                 if (strpos($key, cache_session::KEY_PREFIX) !== 0 || !is_array($value) || !isset($value['lastaccess'])) {
                     continue;
                 }
                 if ((int) $value['lastaccess'] < $purgetime || true) {
                     $todelete[] = $key;
                 }
             }
             if (count($todelete)) {
                 $outcome = (int) $store->delete_many($todelete);
                 if ($output) {
                     $strdef = s($definition->get_id());
                     $strstore = s($store->my_name());
                     mtrace("- Removed {$outcome} old {$strdef} sessions from the '{$strstore}' cache store.");
                 }
             }
         }
     }
 }
Пример #15
0
 /**
  * Test purge routines.
  */
 public function test_purge_routines()
 {
     $instance = cache_config_phpunittest::instance(true);
     $instance->phpunit_add_definition('phpunit/purge1', array('mode' => cache_store::MODE_APPLICATION, 'component' => 'phpunit', 'area' => 'purge1'));
     $instance->phpunit_add_definition('phpunit/purge2', array('mode' => cache_store::MODE_APPLICATION, 'component' => 'phpunit', 'area' => 'purge2', 'requireidentifiers' => array('id')));
     $factory = cache_factory::instance();
     $definition = $factory->create_definition('phpunit', 'purge1');
     $this->assertFalse($definition->has_required_identifiers());
     $cache = $factory->create_cache($definition);
     $this->assertInstanceOf('cache_application', $cache);
     $this->assertTrue($cache->set('test', 'test'));
     $this->assertTrue($cache->has('test'));
     cache_helper::purge_by_definition('phpunit', 'purge1');
     $this->assertFalse($cache->has('test'));
     $factory = cache_factory::instance();
     $definition = $factory->create_definition('phpunit', 'purge2');
     $this->assertTrue($definition->has_required_identifiers());
     $cache = $factory->create_cache($definition);
     $this->assertInstanceOf('cache_application', $cache);
     $this->assertTrue($cache->set('test', 'test'));
     $this->assertTrue($cache->has('test'));
     cache_helper::purge_stores_used_by_definition('phpunit', 'purge2');
     $this->assertFalse($cache->has('test'));
     try {
         cache_helper::purge_by_definition('phpunit', 'purge2');
         $this->fail('Should not be able to purge a definition required identifiers without providing them.');
     } catch (coding_exception $ex) {
         $this->assertContains('Identifier required for cache has not been provided', $ex->getMessage());
     }
 }
Пример #16
0
 /**
  * Returns the site identifier.
  *
  * @return string
  */
 public static function get_site_identifier()
 {
     if (is_null(self::$siteidentifier)) {
         $factory = cache_factory::instance();
         $config = $factory->create_config_instance();
         self::$siteidentifier = $config->get_site_identifier();
     }
     return self::$siteidentifier;
 }
Пример #17
0
 /**
  * Creates a new cache instance based upon the given params.
  *
  * @param int $mode One of cache_store::MODE_*
  * @param string $component The component this cache relates to.
  * @param string $area The area this cache relates to.
  * @param array $identifiers Any additional identifiers that should be provided to the definition.
  * @param array $options An array of options, available options are:
  *   - simplekeys : Set to true if the keys you will use are a-zA-Z0-9_
  *   - simpledata : Set to true if the type of the data you are going to store is scalar, or an array of scalar vars
  *   - staticacceleration : If set to true the cache will hold onto data passing through it.
  *   - staticaccelerationsize : The max size for the static acceleration array.
  * @return cache_application|cache_session|cache_store
  */
 public static function make_from_params($mode, $component, $area, array $identifiers = array(), array $options = array())
 {
     $factory = cache_factory::instance();
     return $factory->create_cache_from_params($mode, $component, $area, $identifiers, $options);
 }
Пример #18
0
 /**
  * Gets an instance of the cache_configuration class.
  *
  * @return cache_config
  */
 public static function instance()
 {
     $factory = cache_factory::instance();
     return $factory->create_config_instance();
 }