Differences Between: [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
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 * Cache display administration helper. 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 * @author Peter Burnett <peterburnett@catalyst-au.net> 26 * @copyright 2020 Catalyst IT 27 * @copyright 2012 Sam Hemelryk 28 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 */ 30 31 namespace core_cache\local; 32 33 defined('MOODLE_INTERNAL') || die(); 34 use cache_store, cache_factory, cache_config_writer, cache_helper, core_cache_renderer; 35 36 /** 37 * A cache helper for administration tasks 38 * 39 * @package core 40 * @category cache 41 * @copyright 2020 Peter Burnett <peterburnett@catalyst-au.net> 42 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 43 */ 44 class administration_display_helper extends \core_cache\administration_helper { 45 46 /** 47 * Please do not call constructor directly. Use cache_factory::get_administration_display_helper() instead. 48 */ 49 public function __construct() { 50 // Nothing to do here. 51 } 52 53 /** 54 * Returns all of the actions that can be performed on a definition. 55 * 56 * @param context $context the system context. 57 * @param array $definitionsummary information about this cache, from the array returned by 58 * core_cache\administration_helper::get_definition_summaries(). Currently only 'sharingoptions' 59 * element is used. 60 * @return array of actions. Each action is an action_url. 61 */ 62 public function get_definition_actions(\context $context, array $definitionsummary): array { 63 global $OUTPUT; 64 if (has_capability('moodle/site:config', $context)) { 65 $actions = array(); 66 // Edit mappings. 67 $actions[] = $OUTPUT->action_link( 68 new \moodle_url('/cache/admin.php', array('action' => 'editdefinitionmapping', 69 'definition' => $definitionsummary['id'], 'sesskey' => sesskey())), 70 get_string('editmappings', 'cache') 71 ); 72 // Edit sharing. 73 if (count($definitionsummary['sharingoptions']) > 1) { 74 $actions[] = $OUTPUT->action_link( 75 new \moodle_url('/cache/admin.php', array('action' => 'editdefinitionsharing', 76 'definition' => $definitionsummary['id'], 'sesskey' => sesskey())), 77 get_string('editsharing', 'cache') 78 ); 79 } 80 // Purge. 81 $actions[] = $OUTPUT->action_link( 82 new \moodle_url('/cache/admin.php', array('action' => 'purgedefinition', 83 'definition' => $definitionsummary['id'], 'sesskey' => sesskey())), 84 get_string('purge', 'cache') 85 ); 86 return $actions; 87 } 88 return array(); 89 } 90 91 /** 92 * Returns all of the actions that can be performed on a store. 93 * 94 * @param string $name The name of the store 95 * @param array $storedetails information about this store, from the array returned by 96 * core_cache\administration_helper::get_store_instance_summaries(). 97 * @return array of actions. Each action is an action_url. 98 */ 99 public function get_store_instance_actions(string $name, array $storedetails): array { 100 global $OUTPUT; 101 $actions = array(); 102 if (has_capability('moodle/site:config', \context_system::instance())) { 103 $baseurl = new \moodle_url('/cache/admin.php', array('store' => $name, 'sesskey' => sesskey())); 104 if (empty($storedetails['default'])) { 105 $actions[] = $OUTPUT->action_link( 106 new \moodle_url($baseurl, array('action' => 'editstore', 'plugin' => $storedetails['plugin'])), 107 get_string('editstore', 'cache') 108 ); 109 110 $actions[] = $OUTPUT->action_link( 111 new \moodle_url($baseurl, array('action' => 'deletestore')), 112 get_string('deletestore', 'cache') 113 ); 114 } 115 116 $actions[] = $OUTPUT->action_link( 117 new \moodle_url($baseurl, array('action' => 'purgestore')), 118 get_string('purge', 'cache') 119 ); 120 } 121 return $actions; 122 } 123 124 /** 125 * Returns all of the actions that can be performed on a plugin. 126 * 127 * @param string $name The name of the plugin 128 * @param array $plugindetails information about this store, from the array returned by 129 * core_cache\administration_helper::get_store_plugin_summaries(). 130 * @return array of actions. Each action is an action_url. 131 */ 132 public function get_store_plugin_actions(string $name, array $plugindetails): array { 133 global $OUTPUT; 134 $actions = array(); 135 if (has_capability('moodle/site:config', \context_system::instance())) { 136 if (!empty($plugindetails['canaddinstance'])) { 137 $url = new \moodle_url('/cache/admin.php', 138 array('action' => 'addstore', 'plugin' => $name, 'sesskey' => sesskey())); 139 $actions[] = $OUTPUT->action_link( 140 $url, 141 get_string('addinstance', 'cache') 142 ); 143 } 144 } 145 return $actions; 146 } 147 148 /** 149 * Returns a form that can be used to add a store instance. 150 * 151 * @param string $plugin The plugin to add an instance of 152 * @return cachestore_addinstance_form 153 * @throws coding_exception 154 */ 155 public function get_add_store_form(string $plugin): \cachestore_addinstance_form { 156 global $CFG; // Needed for includes. 157 $plugins = \core_component::get_plugin_list('cachestore'); 158 if (!array_key_exists($plugin, $plugins)) { 159 throw new \coding_exception('Invalid cache plugin used when trying to create an edit form.'); 160 } 161 $plugindir = $plugins[$plugin]; 162 $class = 'cachestore_addinstance_form'; 163 if (file_exists($plugindir.'/addinstanceform.php')) { 164 require_once($plugindir.'/addinstanceform.php'); 165 if (class_exists('cachestore_'.$plugin.'_addinstance_form')) { 166 $class = 'cachestore_'.$plugin.'_addinstance_form'; 167 if (!array_key_exists('cachestore_addinstance_form', class_parents($class))) { 168 throw new \coding_exception('Cache plugin add instance forms must extend cachestore_addinstance_form'); 169 } 170 } 171 } 172 173 $locks = $this->get_possible_locks_for_stores($plugindir, $plugin); 174 175 $url = new \moodle_url('/cache/admin.php', array('action' => 'addstore')); 176 return new $class($url, array('plugin' => $plugin, 'store' => null, 'locks' => $locks)); 177 } 178 179 /** 180 * Returns a form that can be used to edit a store instance. 181 * 182 * @param string $plugin 183 * @param string $store 184 * @return cachestore_addinstance_form 185 * @throws coding_exception 186 */ 187 public function get_edit_store_form(string $plugin, string $store): \cachestore_addinstance_form { 188 global $CFG; // Needed for includes. 189 $plugins = \core_component::get_plugin_list('cachestore'); 190 if (!array_key_exists($plugin, $plugins)) { 191 throw new \coding_exception('Invalid cache plugin used when trying to create an edit form.'); 192 } 193 $factory = \cache_factory::instance(); 194 $config = $factory->create_config_instance(); 195 $stores = $config->get_all_stores(); 196 if (!array_key_exists($store, $stores)) { 197 throw new \coding_exception('Invalid store name given when trying to create an edit form.'); 198 } 199 $plugindir = $plugins[$plugin]; 200 $class = 'cachestore_addinstance_form'; 201 if (file_exists($plugindir.'/addinstanceform.php')) { 202 require_once($plugindir.'/addinstanceform.php'); 203 if (class_exists('cachestore_'.$plugin.'_addinstance_form')) { 204 $class = 'cachestore_'.$plugin.'_addinstance_form'; 205 if (!array_key_exists('cachestore_addinstance_form', class_parents($class))) { 206 throw new \coding_exception('Cache plugin add instance forms must extend cachestore_addinstance_form'); 207 } 208 } 209 } 210 211 $locks = $this->get_possible_locks_for_stores($plugindir, $plugin); 212 213 $url = new \moodle_url('/cache/admin.php', array('action' => 'editstore', 'plugin' => $plugin, 'store' => $store)); 214 $editform = new $class($url, array('plugin' => $plugin, 'store' => $store, 'locks' => $locks)); 215 if (isset($stores[$store]['lock'])) { 216 $editform->set_data(array('lock' => $stores[$store]['lock'])); 217 } 218 // See if the cachestore is going to want to load data for the form. 219 // If it has a customised add instance form then it is going to want to. 220 $storeclass = 'cachestore_'.$plugin; 221 $storedata = $stores[$store]; 222 if (array_key_exists('configuration', $storedata) && 223 array_key_exists('cache_is_configurable', class_implements($storeclass))) { 224 $storeclass::config_set_edit_form_data($editform, $storedata['configuration']); 225 } 226 return $editform; 227 } 228 229 /** 230 * Returns an array of suitable lock instances for use with this plugin, or false if the plugin handles locking itself. 231 * 232 * @param string $plugindir 233 * @param string $plugin 234 * @return array|false 235 */ 236 protected function get_possible_locks_for_stores(string $plugindir, string $plugin) { 237 global $CFG; // Needed for includes. 238 $supportsnativelocking = false; 239 if (file_exists($plugindir.'/lib.php')) { 240 require_once($plugindir.'/lib.php'); 241 $pluginclass = 'cachestore_'.$plugin; 242 if (class_exists($pluginclass)) { 243 $supportsnativelocking = array_key_exists('cache_is_lockable', class_implements($pluginclass)); 244 } 245 } 246 247 if (!$supportsnativelocking) { 248 $config = \cache_config::instance(); 249 $locks = array(); 250 foreach ($config->get_locks() as $lock => $conf) { 251 if (!empty($conf['default'])) { 252 $name = get_string($lock, 'cache'); 253 } else { 254 $name = $lock; 255 } 256 $locks[$lock] = $name; 257 } 258 } else { 259 $locks = false; 260 } 261 262 return $locks; 263 } 264 265 /** 266 * Processes the results of the add/edit instance form data for a plugin returning an array of config information suitable to 267 * store in configuration. 268 * 269 * @param stdClass $data The mform data. 270 * @return array 271 * @throws coding_exception 272 */ 273 public function get_store_configuration_from_data(\stdClass $data): array { 274 global $CFG; 275 $file = $CFG->dirroot.'/cache/stores/'.$data->plugin.'/lib.php'; 276 if (!file_exists($file)) { 277 throw new \coding_exception('Invalid cache plugin provided. '.$file); 278 } 279 require_once($file); 280 $class = 'cachestore_'.$data->plugin; 281 if (!class_exists($class)) { 282 throw new \coding_exception('Invalid cache plugin provided.'); 283 } 284 if (array_key_exists('cache_is_configurable', class_implements($class))) { 285 return $class::config_get_configuration_array($data); 286 } 287 return array(); 288 } 289 290 /** 291 * Returns an array of lock plugins for which we can add an instance. 292 * 293 * Suitable for use within an mform select element. 294 * 295 * @return array 296 */ 297 public function get_addable_lock_options(): array { 298 $plugins = \core_component::get_plugin_list_with_class('cachelock', '', 'lib.php'); 299 $options = array(); 300 $len = strlen('cachelock_'); 301 foreach ($plugins as $plugin => $class) { 302 $method = "$class::can_add_instance"; 303 if (is_callable($method) && !call_user_func($method)) { 304 // Can't add an instance of this plugin. 305 continue; 306 } 307 $options[substr($plugin, $len)] = get_string('pluginname', $plugin); 308 } 309 return $options; 310 } 311 312 /** 313 * Gets the form to use when adding a lock instance. 314 * 315 * @param string $plugin 316 * @param array $lockplugin 317 * @return cache_lock_form 318 * @throws coding_exception 319 */ 320 public function get_add_lock_form(string $plugin, array $lockplugin = null): \cache_lock_form { 321 global $CFG; // Needed for includes. 322 $plugins = \core_component::get_plugin_list('cachelock'); 323 if (!array_key_exists($plugin, $plugins)) { 324 throw new \coding_exception('Invalid cache lock plugin requested when trying to create a form.'); 325 } 326 $plugindir = $plugins[$plugin]; 327 $class = 'cache_lock_form'; 328 if (file_exists($plugindir.'/addinstanceform.php') && in_array('cache_is_configurable', class_implements($class))) { 329 require_once($plugindir.'/addinstanceform.php'); 330 if (class_exists('cachelock_'.$plugin.'_addinstance_form')) { 331 $class = 'cachelock_'.$plugin.'_addinstance_form'; 332 if (!array_key_exists('cache_lock_form', class_parents($class))) { 333 throw new \coding_exception('Cache lock plugin add instance forms must extend cache_lock_form'); 334 } 335 } 336 } 337 return new $class(null, array('lock' => $plugin)); 338 } 339 340 /** 341 * Gets configuration data from a new lock instance form. 342 * 343 * @param string $plugin 344 * @param stdClass $data 345 * @return array 346 * @throws coding_exception 347 */ 348 public function get_lock_configuration_from_data(string $plugin, \stdClass $data): array { 349 global $CFG; 350 $file = $CFG->dirroot.'/cache/locks/'.$plugin.'/lib.php'; 351 if (!file_exists($file)) { 352 throw new \coding_exception('Invalid cache plugin provided. '.$file); 353 } 354 require_once($file); 355 $class = 'cachelock_'.$plugin; 356 if (!class_exists($class)) { 357 throw new \coding_exception('Invalid cache plugin provided.'); 358 } 359 if (array_key_exists('cache_is_configurable', class_implements($class))) { 360 return $class::config_get_configuration_array($data); 361 } 362 return array(); 363 } 364 365 /** 366 * Handles the page actions, based on the parameter. 367 * 368 * @param string $action the action to handle. 369 * @param array $forminfo an empty array to be overridden and set. 370 * @return array the empty or overridden forminfo array. 371 */ 372 public function perform_cache_actions(string $action, array $forminfo): array { 373 switch ($action) { 374 case 'rescandefinitions' : // Rescan definitions. 375 $this->action_rescan_definition(); 376 break; 377 378 case 'addstore' : // Add the requested store. 379 $forminfo = $this->action_addstore(); 380 break; 381 382 case 'editstore' : // Edit the requested store. 383 $forminfo = $this->action_editstore(); 384 break; 385 386 case 'deletestore' : // Delete a given store. 387 $this->action_deletestore($action); 388 break; 389 390 case 'editdefinitionmapping' : // Edit definition mappings. 391 $forminfo = $this->action_editdefinitionmapping(); 392 break; 393 394 case 'editdefinitionsharing' : // Edit definition sharing. 395 $forminfo = $this->action_editdefinitionsharing(); 396 break; 397 398 case 'editmodemappings': // Edit default mode mappings. 399 $forminfo = $this->action_editmodemappings(); 400 break; 401 402 case 'purgedefinition': // Purge a specific definition. 403 $this->action_purgedefinition(); 404 break; 405 406 case 'purgestore': 407 case 'purge': // Purge a store cache. 408 $this->action_purge(); 409 break; 410 411 case 'newlockinstance': 412 $forminfo = $this->action_newlockinstance(); 413 break; 414 415 case 'deletelock': 416 // Deletes a lock instance. 417 $this->action_deletelock($action); 418 break; 419 } 420 421 return $forminfo; 422 } 423 424 /** 425 * Performs the rescan definition action. 426 * 427 * @return void 428 */ 429 public function action_rescan_definition() { 430 global $PAGE; 431 432 \cache_config_writer::update_definitions(); 433 redirect($PAGE->url); 434 } 435 436 /** 437 * Performs the add store action. 438 * 439 * @return array an array of the form to display to the user, and the page title. 440 */ 441 public function action_addstore() : array { 442 global $PAGE; 443 $storepluginsummaries = $this->get_store_plugin_summaries(); 444 445 $plugin = required_param('plugin', PARAM_PLUGIN); 446 if (!$storepluginsummaries[$plugin]['canaddinstance']) { 447 print_error('ex_unmetstorerequirements', 'cache'); 448 } 449 $mform = $this->get_add_store_form($plugin); 450 $title = get_string('addstore', 'cache', $storepluginsummaries[$plugin]['name']); 451 if ($mform->is_cancelled()) { 452 redirect($PAGE->url); 453 } else if ($data = $mform->get_data()) { 454 $config = $this->get_store_configuration_from_data($data); 455 $writer = \cache_config_writer::instance(); 456 unset($config['lock']); 457 foreach ($writer->get_locks() as $lock => $lockconfig) { 458 if ($lock == $data->lock) { 459 $config['lock'] = $data->lock; 460 } 461 } 462 $writer->add_store_instance($data->name, $data->plugin, $config); 463 redirect($PAGE->url, get_string('addstoresuccess', 'cache', $storepluginsummaries[$plugin]['name']), 5); 464 } 465 466 return array('form' => $mform, 'title' => $title); 467 } 468 469 /** 470 * Performs the edit store action. 471 * 472 * @return array an array of the form to display, and the page title. 473 */ 474 public function action_editstore(): array { 475 global $PAGE; 476 $storepluginsummaries = $this->get_store_plugin_summaries(); 477 478 $plugin = required_param('plugin', PARAM_PLUGIN); 479 $store = required_param('store', PARAM_TEXT); 480 $mform = $this->get_edit_store_form($plugin, $store); 481 $title = get_string('addstore', 'cache', $storepluginsummaries[$plugin]['name']); 482 if ($mform->is_cancelled()) { 483 redirect($PAGE->url); 484 } else if ($data = $mform->get_data()) { 485 $config = $this->get_store_configuration_from_data($data); 486 $writer = \cache_config_writer::instance(); 487 488 unset($config['lock']); 489 foreach ($writer->get_locks() as $lock => $lockconfig) { 490 if ($lock == $data->lock) { 491 $config['lock'] = $data->lock; 492 } 493 } 494 $writer->edit_store_instance($data->name, $data->plugin, $config); 495 redirect($PAGE->url, get_string('editstoresuccess', 'cache', $storepluginsummaries[$plugin]['name']), 5); 496 } 497 498 return array('form' => $mform, 'title' => $title); 499 } 500 501 /** 502 * Performs the deletestore action. 503 * 504 * @param string $action the action calling to this function. 505 * @return void 506 */ 507 public function action_deletestore(string $action) { 508 global $OUTPUT, $PAGE, $SITE; 509 $notifysuccess = true; 510 $storeinstancesummaries = $this->get_store_instance_summaries(); 511 512 $store = required_param('store', PARAM_TEXT); 513 $confirm = optional_param('confirm', false, PARAM_BOOL); 514 515 if (!array_key_exists($store, $storeinstancesummaries)) { 516 $notifysuccess = false; 517 $notifications[] = array(get_string('invalidstore', 'cache'), false); 518 } else if ($storeinstancesummaries[$store]['mappings'] > 0) { 519 $notifysuccess = false; 520 $notifications[] = array(get_string('deletestorehasmappings', 'cache'), false); 521 } 522 523 if ($notifysuccess) { 524 if (!$confirm) { 525 $title = get_string('confirmstoredeletion', 'cache'); 526 $params = array('store' => $store, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey()); 527 $url = new \moodle_url($PAGE->url, $params); 528 $button = new \single_button($url, get_string('deletestore', 'cache')); 529 530 $PAGE->set_title($title); 531 $PAGE->set_heading($SITE->fullname); 532 echo $OUTPUT->header(); 533 echo $OUTPUT->heading($title); 534 $confirmation = get_string('deletestoreconfirmation', 'cache', $storeinstancesummaries[$store]['name']); 535 echo $OUTPUT->confirm($confirmation, $button, $PAGE->url); 536 echo $OUTPUT->footer(); 537 exit; 538 } else { 539 $writer = \cache_config_writer::instance(); 540 $writer->delete_store_instance($store); 541 redirect($PAGE->url, get_string('deletestoresuccess', 'cache'), 5); 542 } 543 } 544 } 545 546 /** 547 * Performs the edit definition mapping action. 548 * 549 * @return array an array of the form to display, and the page title. 550 * @throws cache_exception 551 */ 552 public function action_editdefinitionmapping(): array { 553 global $PAGE; 554 $definitionsummaries = $this->get_definition_summaries(); 555 556 $definition = required_param('definition', PARAM_SAFEPATH); 557 if (!array_key_exists($definition, $definitionsummaries)) { 558 throw new \cache_exception('Invalid cache definition requested'); 559 } 560 $title = get_string('editdefinitionmappings', 'cache', $definition); 561 $mform = new \cache_definition_mappings_form($PAGE->url, array('definition' => $definition)); 562 if ($mform->is_cancelled()) { 563 redirect($PAGE->url); 564 } else if ($data = $mform->get_data()) { 565 $writer = \cache_config_writer::instance(); 566 $mappings = array(); 567 foreach ($data->mappings as $mapping) { 568 if (!empty($mapping)) { 569 $mappings[] = $mapping; 570 } 571 } 572 $writer->set_definition_mappings($definition, $mappings); 573 redirect($PAGE->url); 574 } 575 576 return array('form' => $mform, 'title' => $title); 577 } 578 579 /** 580 * Performs the edit definition sharing action. 581 * 582 * @return array an array of the edit definition sharing form, and the page title. 583 */ 584 public function action_editdefinitionsharing(): array { 585 global $PAGE; 586 $definitionsummaries = $this->get_definition_summaries(); 587 588 $definition = required_param('definition', PARAM_SAFEPATH); 589 if (!array_key_exists($definition, $definitionsummaries)) { 590 throw new \cache_exception('Invalid cache definition requested'); 591 } 592 $title = get_string('editdefinitionsharing', 'cache', $definition); 593 $sharingoptions = $definitionsummaries[$definition]['sharingoptions']; 594 $customdata = array('definition' => $definition, 'sharingoptions' => $sharingoptions); 595 $mform = new \cache_definition_sharing_form($PAGE->url, $customdata); 596 $mform->set_data(array( 597 'sharing' => $definitionsummaries[$definition]['selectedsharingoption'], 598 'userinputsharingkey' => $definitionsummaries[$definition]['userinputsharingkey'] 599 )); 600 if ($mform->is_cancelled()) { 601 redirect($PAGE->url); 602 } else if ($data = $mform->get_data()) { 603 $component = $definitionsummaries[$definition]['component']; 604 $area = $definitionsummaries[$definition]['area']; 605 // Purge the stores removing stale data before we alter the sharing option. 606 \cache_helper::purge_stores_used_by_definition($component, $area); 607 $writer = \cache_config_writer::instance(); 608 $sharing = array_sum(array_keys($data->sharing)); 609 $userinputsharingkey = $data->userinputsharingkey; 610 $writer->set_definition_sharing($definition, $sharing, $userinputsharingkey); 611 redirect($PAGE->url); 612 } 613 614 return array('form' => $mform, 'title' => $title); 615 } 616 617 /** 618 * Performs the edit mode mappings action. 619 * 620 * @return array an array of the edit mode mappings form. 621 */ 622 public function action_editmodemappings(): array { 623 global $PAGE; 624 $storeinstancesummaries = $this->get_store_instance_summaries(); 625 $defaultmodestores = $this->get_default_mode_stores(); 626 627 $mform = new \cache_mode_mappings_form(null, $storeinstancesummaries); 628 $mform->set_data(array( 629 'mode_'.cache_store::MODE_APPLICATION => key($defaultmodestores[cache_store::MODE_APPLICATION]), 630 'mode_'.cache_store::MODE_SESSION => key($defaultmodestores[cache_store::MODE_SESSION]), 631 'mode_'.cache_store::MODE_REQUEST => key($defaultmodestores[cache_store::MODE_REQUEST]), 632 )); 633 if ($mform->is_cancelled()) { 634 redirect($PAGE->url); 635 } else if ($data = $mform->get_data()) { 636 $mappings = array( 637 cache_store::MODE_APPLICATION => array($data->{'mode_'.cache_store::MODE_APPLICATION}), 638 cache_store::MODE_SESSION => array($data->{'mode_'.cache_store::MODE_SESSION}), 639 cache_store::MODE_REQUEST => array($data->{'mode_'.cache_store::MODE_REQUEST}), 640 ); 641 $writer = cache_config_writer::instance(); 642 $writer->set_mode_mappings($mappings); 643 redirect($PAGE->url); 644 } 645 646 return array('form' => $mform); 647 } 648 649 /** 650 * Performs the purge definition action. 651 * 652 * @return void 653 */ 654 public function action_purgedefinition() { 655 global $PAGE; 656 657 $id = required_param('definition', PARAM_SAFEPATH); 658 list($component, $area) = explode('/', $id, 2); 659 $factory = cache_factory::instance(); 660 $definition = $factory->create_definition($component, $area); 661 if ($definition->has_required_identifiers()) { 662 // We will have to purge the stores used by this definition. 663 cache_helper::purge_stores_used_by_definition($component, $area); 664 } else { 665 // Alrighty we can purge just the data belonging to this definition. 666 cache_helper::purge_by_definition($component, $area); 667 } 668 669 $message = get_string('purgexdefinitionsuccess', 'cache', [ 670 'name' => $definition->get_name(), 671 'component' => $component, 672 'area' => $area, 673 ]); 674 $purgeagainlink = \html_writer::link(new \moodle_url('/cache/admin.php', [ 675 'action' => 'purgedefinition', 'sesskey' => sesskey(), 'definition' => $id]), 676 get_string('purgeagain', 'cache')); 677 redirect($PAGE->url, $message . ' ' . $purgeagainlink, 5); 678 } 679 680 /** 681 * Performs the purge action. 682 * 683 * @return void 684 */ 685 public function action_purge() { 686 global $PAGE; 687 688 $store = required_param('store', PARAM_TEXT); 689 cache_helper::purge_store($store); 690 $message = get_string('purgexstoresuccess', 'cache', ['store' => $store]); 691 $purgeagainlink = \html_writer::link(new \moodle_url('/cache/admin.php', [ 692 'action' => 'purgestore', 'sesskey' => sesskey(), 'store' => $store]), 693 get_string('purgeagain', 'cache')); 694 redirect($PAGE->url, $message . ' ' . $purgeagainlink, 5); 695 } 696 697 /** 698 * Performs the new lock instance action. 699 * 700 * @return array An array containing the new lock instance form. 701 */ 702 public function action_newlockinstance(): array { 703 global $PAGE; 704 705 // Adds a new lock instance. 706 $lock = required_param('lock', PARAM_ALPHANUMEXT); 707 $mform = $this->get_add_lock_form($lock); 708 if ($mform->is_cancelled()) { 709 redirect($PAGE->url); 710 } else if ($data = $mform->get_data()) { 711 $factory = cache_factory::instance(); 712 $config = $factory->create_config_instance(true); 713 $name = $data->name; 714 $data = $this->get_lock_configuration_from_data($lock, $data); 715 $config->add_lock_instance($name, $lock, $data); 716 redirect($PAGE->url, get_string('addlocksuccess', 'cache', $name), 5); 717 } 718 719 return array('form' => $mform); 720 } 721 722 /** 723 * Performs the delete lock action. 724 * 725 * @param string $action the action calling this function. 726 * @return void 727 */ 728 public function action_deletelock(string $action) { 729 global $OUTPUT, $PAGE, $SITE; 730 $notifysuccess = true; 731 $locks = $this->get_lock_summaries(); 732 733 $lock = required_param('lock', PARAM_ALPHANUMEXT); 734 $confirm = optional_param('confirm', false, PARAM_BOOL); 735 if (!array_key_exists($lock, $locks)) { 736 $notifysuccess = false; 737 $notifications[] = array(get_string('invalidlock', 'cache'), false); 738 } else if ($locks[$lock]['uses'] > 0) { 739 $notifysuccess = false; 740 $notifications[] = array(get_string('deletelockhasuses', 'cache'), false); 741 } 742 if ($notifysuccess) { 743 if (!$confirm) { 744 $title = get_string('confirmlockdeletion', 'cache'); 745 $params = array('lock' => $lock, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey()); 746 $url = new \moodle_url($PAGE->url, $params); 747 $button = new \single_button($url, get_string('deletelock', 'cache')); 748 749 $PAGE->set_title($title); 750 $PAGE->set_heading($SITE->fullname); 751 echo $OUTPUT->header(); 752 echo $OUTPUT->heading($title); 753 $confirmation = get_string('deletelockconfirmation', 'cache', $lock); 754 echo $OUTPUT->confirm($confirmation, $button, $PAGE->url); 755 echo $OUTPUT->footer(); 756 exit; 757 } else { 758 $writer = cache_config_writer::instance(); 759 $writer->delete_lock_instance($lock); 760 redirect($PAGE->url, get_string('deletelocksuccess', 'cache'), 5); 761 } 762 } 763 } 764 765 /** 766 * Outputs the main admin page by generating it through the renderer. 767 * 768 * @param core_cache_renderer $renderer the renderer to use to generate the page. 769 * @return string the HTML for the admin page. 770 */ 771 public function generate_admin_page(core_cache_renderer $renderer): string { 772 $context = \context_system::instance(); 773 $html = ''; 774 775 $storepluginsummaries = $this->get_store_plugin_summaries(); 776 $storeinstancesummaries = $this->get_store_instance_summaries(); 777 $definitionsummaries = $this->get_definition_summaries(); 778 $defaultmodestores = $this->get_default_mode_stores(); 779 $locks = $this->get_lock_summaries(); 780 781 $html .= $renderer->store_plugin_summaries($storepluginsummaries); 782 $html .= $renderer->store_instance_summariers($storeinstancesummaries, $storepluginsummaries); 783 $html .= $renderer->definition_summaries($definitionsummaries, $context); 784 $html .= $renderer->lock_summaries($locks); 785 $html .= $renderer->additional_lock_actions(); 786 787 $applicationstore = join(', ', $defaultmodestores[cache_store::MODE_APPLICATION]); 788 $sessionstore = join(', ', $defaultmodestores[cache_store::MODE_SESSION]); 789 $requeststore = join(', ', $defaultmodestores[cache_store::MODE_REQUEST]); 790 $editurl = new \moodle_url('/cache/admin.php', array('action' => 'editmodemappings', 'sesskey' => sesskey())); 791 $html .= $renderer->mode_mappings($applicationstore, $sessionstore, $requeststore, $editurl); 792 793 return $html; 794 } 795 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body