[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Support library for the cache PHPUnit tests. 19 * 20 * This file is part of Moodle's cache API, affectionately called MUC. 21 * It contains the components that are requried in order to use caching. 22 * 23 * @package core 24 * @category cache 25 * @copyright 2012 Sam Hemelryk 26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 */ 28 29 defined('MOODLE_INTERNAL') || die(); 30 31 require_once($CFG->dirroot.'/cache/locallib.php'); 32 33 /** 34 * Override the default cache configuration for our own maniacal purposes. 35 * 36 * This class was originally named cache_config_phpunittest but was renamed in 2.9 37 * because it is used for both unit tests and acceptance tests. 38 * 39 * @since 2.9 40 * @copyright 2012 Sam Hemelryk 41 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 42 */ 43 class cache_config_testing extends cache_config_writer { 44 45 /** 46 * Creates the default configuration and saves it. 47 * 48 * This function calls config_save, however it is safe to continue using it afterwards as this function should only ever 49 * be called when there is no configuration file already. 50 * 51 * @param bool $forcesave If set to true then we will forcefully save the default configuration file. 52 * @return true|array Returns true if the default configuration was successfully created. 53 * Returns a configuration array if it could not be saved. This is a bad situation. Check your error logs. 54 */ 55 public static function create_default_configuration($forcesave = false) { 56 global $CFG; 57 // HACK ALERT. 58 // We probably need to come up with a better way to create the default stores, or at least ensure 100% that the 59 // default store plugins are protected from deletion. 60 $writer = new self; 61 $writer->configstores = self::get_default_stores(); 62 $writer->configdefinitions = self::locate_definitions(); 63 $defaultapplication = 'default_application'; 64 65 $appdefine = defined('TEST_CACHE_USING_APPLICATION_STORE') ? TEST_CACHE_USING_APPLICATION_STORE : false; 66 if ($appdefine !== false && preg_match('/^[a-zA-Z][a-zA-Z0-9_]+$/', $appdefine)) { 67 $expectedstore = $appdefine; 68 $file = $CFG->dirroot.'/cache/stores/'.$appdefine.'/lib.php'; 69 $class = 'cachestore_'.$appdefine; 70 if (file_exists($file)) { 71 require_once($file); 72 } 73 if (class_exists($class) && $class::ready_to_be_used_for_testing()) { 74 /* @var cache_store $class */ 75 $writer->configstores['test_application'] = array( 76 'use_test_store' => true, 77 'name' => 'test_application', 78 'plugin' => $expectedstore, 79 'alt' => $writer->configstores[$defaultapplication], 80 'modes' => $class::get_supported_modes(), 81 'features' => $class::get_supported_features() 82 ); 83 $defaultapplication = 'test_application'; 84 } 85 } 86 87 $writer->configmodemappings = array( 88 array( 89 'mode' => cache_store::MODE_APPLICATION, 90 'store' => $defaultapplication, 91 'sort' => -1 92 ), 93 array( 94 'mode' => cache_store::MODE_SESSION, 95 'store' => 'default_session', 96 'sort' => -1 97 ), 98 array( 99 'mode' => cache_store::MODE_REQUEST, 100 'store' => 'default_request', 101 'sort' => -1 102 ) 103 ); 104 $writer->configlocks = array( 105 'default_file_lock' => array( 106 'name' => 'cachelock_file_default', 107 'type' => 'cachelock_file', 108 'dir' => 'filelocks', 109 'default' => true 110 ) 111 ); 112 113 $factory = cache_factory::instance(); 114 // We expect the cache to be initialising presently. If its not then something has gone wrong and likely 115 // we are now in a loop. 116 if (!$forcesave && $factory->get_state() !== cache_factory::STATE_INITIALISING) { 117 return $writer->generate_configuration_array(); 118 } 119 $factory->set_state(cache_factory::STATE_SAVING); 120 $writer->config_save(); 121 return true; 122 } 123 124 /** 125 * Returns the expected path to the configuration file. 126 * 127 * We override this function to add handling for $CFG->altcacheconfigpath. 128 * We want to support it so that people can run unit tests against alternative cache setups. 129 * However we don't want to ever make changes to the file at $CFG->altcacheconfigpath so we 130 * always use dataroot and copy the alt file there as required. 131 * 132 * @throws cache_exception 133 * @return string The absolute path 134 */ 135 protected static function get_config_file_path() { 136 global $CFG; 137 // We always use this path. 138 $configpath = $CFG->dataroot.'/muc/config.php'; 139 140 if (!empty($CFG->altcacheconfigpath)) { 141 142 // No need to check we are within a test here, this is the cache config class that gets used 143 // only when one of those is true. 144 if (!defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') || !TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH) { 145 // TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH has not being defined or is false, we want to use the default. 146 return $configpath; 147 } 148 149 $path = $CFG->altcacheconfigpath; 150 if (is_dir($path) && is_writable($path)) { 151 // Its a writable directory, thats fine. Convert it to a file. 152 $path = $CFG->altcacheconfigpath.'/cacheconfig.php'; 153 } 154 if (is_readable($path)) { 155 $directory = dirname($configpath); 156 if ($directory !== $CFG->dataroot && !file_exists($directory)) { 157 $result = make_writable_directory($directory, false); 158 if (!$result) { 159 throw new cache_exception('ex_configcannotsave', 'cache', '', null, 'Cannot create config directory. Check the permissions on your moodledata directory.'); 160 } 161 } 162 // We don't care that this fails but we should let the developer know. 163 if (!is_readable($configpath) && !@copy($path, $configpath)) { 164 debugging('Failed to copy alt cache config file to required location'); 165 } 166 } 167 } 168 169 // We always use the dataroot location. 170 return $configpath; 171 } 172 173 /** 174 * Adds a definition to the stack 175 * @param string $area 176 * @param array $properties 177 * @param bool $addmapping By default this method adds a definition and a mapping for that definition. You can 178 * however set this to false if you only want it to add the definition and not the mapping. 179 */ 180 public function phpunit_add_definition($area, array $properties, $addmapping = true) { 181 if (!array_key_exists('overrideclass', $properties)) { 182 switch ($properties['mode']) { 183 case cache_store::MODE_APPLICATION: 184 $properties['overrideclass'] = 'cache_phpunit_application'; 185 break; 186 case cache_store::MODE_SESSION: 187 $properties['overrideclass'] = 'cache_phpunit_session'; 188 break; 189 case cache_store::MODE_REQUEST: 190 $properties['overrideclass'] = 'cache_phpunit_request'; 191 break; 192 } 193 } 194 $this->configdefinitions[$area] = $properties; 195 if ($addmapping) { 196 switch ($properties['mode']) { 197 case cache_store::MODE_APPLICATION: 198 $this->phpunit_add_definition_mapping($area, 'default_application', 0); 199 break; 200 case cache_store::MODE_SESSION: 201 $this->phpunit_add_definition_mapping($area, 'default_session', 0); 202 break; 203 case cache_store::MODE_REQUEST: 204 $this->phpunit_add_definition_mapping($area, 'default_request', 0); 205 break; 206 } 207 } 208 } 209 210 /** 211 * Removes a definition. 212 * @param string $name 213 */ 214 public function phpunit_remove_definition($name) { 215 unset($this->configdefinitions[$name]); 216 } 217 218 /** 219 * Removes the configured stores so that there are none available. 220 */ 221 public function phpunit_remove_stores() { 222 $this->configstores = array(); 223 } 224 225 /** 226 * Forcefully adds a file store. 227 * 228 * @param string $name 229 */ 230 public function phpunit_add_file_store($name) { 231 $this->configstores[$name] = array( 232 'name' => $name, 233 'plugin' => 'file', 234 'configuration' => array( 235 'path' => '' 236 ), 237 'features' => 6, 238 'modes' => 3, 239 'mappingsonly' => false, 240 'class' => 'cachestore_file', 241 'default' => false, 242 'lock' => 'cachelock_file_default' 243 ); 244 } 245 246 /** 247 * Forcefully adds a session store. 248 * 249 * @param string $name 250 */ 251 public function phpunit_add_session_store($name) { 252 $this->configstores[$name] = array( 253 'name' => $name, 254 'plugin' => 'session', 255 'configuration' => array(), 256 'features' => 14, 257 'modes' => 2, 258 'default' => true, 259 'class' => 'cachestore_session', 260 'lock' => 'cachelock_file_default', 261 ); 262 } 263 264 /** 265 * Forcefully injects a definition => store mapping. 266 * 267 * This function does no validation, you should only be calling if it you know 268 * exactly what to expect. 269 * 270 * @param string $definition 271 * @param string $store 272 * @param int $sort 273 */ 274 public function phpunit_add_definition_mapping($definition, $store, $sort) { 275 $this->configdefinitionmappings[] = array( 276 'store' => $store, 277 'definition' => $definition, 278 'sort' => (int)$sort 279 ); 280 } 281 282 /** 283 * Overrides the default site identifier used by the Cache API so that we can be sure of what it is. 284 * 285 * @return string 286 */ 287 public function get_site_identifier() { 288 global $CFG; 289 return $CFG->wwwroot.'phpunit'; 290 } 291 } 292 293 /** 294 * This is a deprecated class. It has been renamed to cache_config_testing. 295 * 296 * This was deprecated in Moodle 2.9 but will be removed at the next major release 297 * as it is only used during testing and its highly unlikely anyone has used this. 298 * 299 * @deprecated since 2.9 300 * @todo MDL-55267 This will be deleted in Moodle 3.3. 301 * @copyright 2014 Sam Hemelryk 302 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 303 */ 304 class cache_config_phpunittest extends cache_config_testing { 305 // We can't do anything here to warn the user. 306 // The cache can be utilised before sessions have even been started. 307 } 308 309 /** 310 * Dummy object for testing cacheable object interface and interaction 311 * 312 * @copyright 2012 Sam Hemelryk 313 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 314 */ 315 class cache_phpunit_dummy_object extends stdClass implements cacheable_object { 316 /** 317 * Test property 1 318 * @var string 319 */ 320 public $property1; 321 /** 322 * Test property 1 323 * @var string 324 */ 325 public $property2; 326 /** 327 * Constructor 328 * @param string $property1 329 * @param string $property2 330 */ 331 public function __construct($property1, $property2) { 332 $this->property1 = $property1; 333 $this->property2 = $property2; 334 } 335 /** 336 * Prepares this object for caching 337 * @return array 338 */ 339 public function prepare_to_cache() { 340 return array($this->property1.'_ptc', $this->property2.'_ptc'); 341 } 342 /** 343 * Returns this object from the cache 344 * @param array $data 345 * @return cache_phpunit_dummy_object 346 */ 347 public static function wake_from_cache($data) { 348 return new cache_phpunit_dummy_object(array_shift($data).'_wfc', array_shift($data).'_wfc'); 349 } 350 } 351 352 /** 353 * Dummy data source object for testing data source interface and implementation 354 * 355 * @copyright 2012 Sam Hemelryk 356 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 357 */ 358 class cache_phpunit_dummy_datasource implements cache_data_source { 359 /** 360 * Returns an instance of this object for use with the cache. 361 * 362 * @param cache_definition $definition 363 * @return cache_phpunit_dummy_datasource 364 */ 365 public static function get_instance_for_cache(cache_definition $definition) { 366 return new cache_phpunit_dummy_datasource(); 367 } 368 369 /** 370 * Loads a key for the cache. 371 * 372 * @param string $key 373 * @return string 374 */ 375 public function load_for_cache($key) { 376 return $key.' has no value really.'; 377 } 378 379 /** 380 * Loads many keys for the cache 381 * 382 * @param array $keys 383 * @return array 384 */ 385 public function load_many_for_cache(array $keys) { 386 $return = array(); 387 foreach ($keys as $key) { 388 $return[$key] = $key.' has no value really.'; 389 } 390 return $return; 391 } 392 } 393 394 /** 395 * PHPUnit application cache loader. 396 * 397 * Used to expose things we could not otherwise see within an application cache. 398 * 399 * @copyright 2012 Sam Hemelryk 400 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 401 */ 402 class cache_phpunit_application extends cache_application { 403 404 /** 405 * Returns the class of the store immediately associated with this cache. 406 * @return string 407 */ 408 public function phpunit_get_store_class() { 409 return get_class($this->get_store()); 410 } 411 412 /** 413 * Returns all the interfaces the cache store implements. 414 * @return array 415 */ 416 public function phpunit_get_store_implements() { 417 return class_implements($this->get_store()); 418 } 419 420 /** 421 * Returns the given key directly from the static acceleration array. 422 * 423 * @param string $key 424 * @return false|mixed 425 */ 426 public function phpunit_static_acceleration_get($key) { 427 return $this->static_acceleration_get($key); 428 } 429 } 430 431 /** 432 * PHPUnit session cache loader. 433 * 434 * Used to expose things we could not otherwise see within an session cache. 435 * 436 * @copyright 2012 Sam Hemelryk 437 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 438 */ 439 class cache_phpunit_session extends cache_session { 440 441 /** 442 * Returns the class of the store immediately associated with this cache. 443 * @return string 444 */ 445 public function phpunit_get_store_class() { 446 return get_class($this->get_store()); 447 } 448 449 /** 450 * Returns all the interfaces the cache store implements. 451 * @return array 452 */ 453 public function phpunit_get_store_implements() { 454 return class_implements($this->get_store()); 455 } 456 } 457 458 /** 459 * PHPUnit request cache loader. 460 * 461 * Used to expose things we could not otherwise see within an request cache. 462 * 463 * @copyright 2012 Sam Hemelryk 464 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 465 */ 466 class cache_phpunit_request extends cache_request { 467 468 /** 469 * Returns the class of the store immediately associated with this cache. 470 * @return string 471 */ 472 public function phpunit_get_store_class() { 473 return get_class($this->get_store()); 474 } 475 476 /** 477 * Returns all the interfaces the cache store implements. 478 * @return array 479 */ 480 public function phpunit_get_store_implements() { 481 return class_implements($this->get_store()); 482 } 483 } 484 485 /** 486 * Dummy overridden cache loader class that we can use to test overriding loader functionality. 487 * 488 * @copyright 2012 Sam Hemelryk 489 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 490 */ 491 class cache_phpunit_dummy_overrideclass extends cache_application { 492 // Satisfying the code pre-checker is just part of my day job. 493 } 494 495 /** 496 * Cache PHPUnit specific factory. 497 * 498 * @copyright 2012 Sam Hemelryk 499 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 500 */ 501 class cache_phpunit_factory extends cache_factory { 502 /** 503 * Exposes the cache_factory's disable method. 504 * 505 * Perhaps one day that method will be made public, for the time being it is protected. 506 */ 507 public static function phpunit_disable() { 508 parent::disable(); 509 } 510 511 /** 512 * Creates a store instance given its name and configuration. 513 * 514 * If the store has already been instantiated then the original object will be returned. (reused) 515 * 516 * @param string $name The name of the store (must be unique remember) 517 * @param array $details 518 * @param cache_definition $definition The definition to instantiate it for. 519 * @return boolean|cache_store 520 */ 521 public function create_store_from_config($name, array $details, cache_definition $definition) { 522 523 if (isset($details['use_test_store'])) { 524 // name, plugin, alt 525 $class = 'cachestore_'.$details['plugin']; 526 $method = 'initialise_unit_test_instance'; 527 if (class_exists($class) && method_exists($class, $method)) { 528 $instance = $class::$method($definition); 529 530 if ($instance) { 531 return $instance; 532 } 533 } 534 $details = $details['alt']; 535 $name = $details['name']; 536 } 537 538 return parent::create_store_from_config($name, $details, $definition); 539 } 540 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |