Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.
/cache/ -> admin.php (source)

Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 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   * The administration and management interface for the cache setup and configuration.
  19   *
  20   * This file is part of Moodle's cache API, affectionately called MUC.
  21   *
  22   * @package    core
  23   * @category   cache
  24   * @copyright  2012 Sam Hemelryk
  25   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  26   */
  27  
  28  require_once('../config.php');
  29  require_once($CFG->dirroot.'/lib/adminlib.php');
  30  require_once($CFG->dirroot.'/cache/locallib.php');
  31  require_once($CFG->dirroot.'/cache/forms.php');
  32  
  33  // The first time the user visits this page we are going to reparse the definitions.
  34  // Just ensures that everything is up to date.
  35  // We flag is session so that this only happens once as people are likely to hit
  36  // this page several times if making changes.
  37  if (empty($SESSION->cacheadminreparsedefinitions)) {
  38      cache_helper::update_definitions();
  39      $SESSION->cacheadminreparsedefinitions = true;
  40  }
  41  
  42  $action = optional_param('action', null, PARAM_ALPHA);
  43  
  44  admin_externalpage_setup('cacheconfig');
  45  $context = context_system::instance();
  46  
  47  $storeinstancesummaries = cache_administration_helper::get_store_instance_summaries();
  48  $storepluginsummaries = cache_administration_helper::get_store_plugin_summaries();
  49  $definitionsummaries = cache_administration_helper::get_definition_summaries();
  50  $defaultmodestores = cache_administration_helper::get_default_mode_stores();
  51  $locks = cache_administration_helper::get_lock_summaries();
  52  
  53  $title = new lang_string('cacheadmin', 'cache');
  54  $mform = null;
  55  $notifications = array();
  56  $notifysuccess = true;
  57  
  58  if (!empty($action) && confirm_sesskey()) {
  59      switch ($action) {
  60          case 'rescandefinitions' : // Rescan definitions.
  61              cache_config_writer::update_definitions();
  62              redirect($PAGE->url);
  63              break;
  64          case 'addstore' : // Add the requested store.
  65              $plugin = required_param('plugin', PARAM_PLUGIN);
  66              if (!$storepluginsummaries[$plugin]['canaddinstance']) {
  67                  print_error('ex_unmetstorerequirements', 'cache');
  68              }
  69              $mform = cache_administration_helper::get_add_store_form($plugin);
  70              $title = get_string('addstore', 'cache', $storepluginsummaries[$plugin]['name']);
  71              if ($mform->is_cancelled()) {
  72                  redirect($PAGE->url);
  73              } else if ($data = $mform->get_data()) {
  74                  $config = cache_administration_helper::get_store_configuration_from_data($data);
  75                  $writer = cache_config_writer::instance();
  76                  unset($config['lock']);
  77                  foreach ($writer->get_locks() as $lock => $lockconfig) {
  78                      if ($lock == $data->lock) {
  79                          $config['lock'] = $data->lock;
  80                      }
  81                  }
  82                  $writer->add_store_instance($data->name, $data->plugin, $config);
  83                  redirect($PAGE->url, get_string('addstoresuccess', 'cache', $storepluginsummaries[$plugin]['name']), 5);
  84              }
  85              break;
  86          case 'editstore' : // Edit the requested store.
  87              $plugin = required_param('plugin', PARAM_PLUGIN);
  88              $store = required_param('store', PARAM_TEXT);
  89              $mform = cache_administration_helper::get_edit_store_form($plugin, $store);
  90              $title = get_string('addstore', 'cache', $storepluginsummaries[$plugin]['name']);
  91              if ($mform->is_cancelled()) {
  92                  redirect($PAGE->url);
  93              } else if ($data = $mform->get_data()) {
  94                  $config = cache_administration_helper::get_store_configuration_from_data($data);
  95                  $writer = cache_config_writer::instance();
  96  
  97                  unset($config['lock']);
  98                  foreach ($writer->get_locks() as $lock => $lockconfig) {
  99                      if ($lock == $data->lock) {
 100                          $config['lock'] = $data->lock;
 101                      }
 102                  }
 103                  $writer->edit_store_instance($data->name, $data->plugin, $config);
 104                  redirect($PAGE->url, get_string('editstoresuccess', 'cache', $storepluginsummaries[$plugin]['name']), 5);
 105              }
 106              break;
 107          case 'deletestore' : // Delete a given store.
 108              $store = required_param('store', PARAM_TEXT);
 109              $confirm = optional_param('confirm', false, PARAM_BOOL);
 110  
 111              if (!array_key_exists($store, $storeinstancesummaries)) {
 112                  $notifysuccess = false;
 113                  $notifications[] = array(get_string('invalidstore', 'cache'), false);
 114              } else if ($storeinstancesummaries[$store]['mappings'] > 0) {
 115                  $notifysuccess = false;
 116                  $notifications[] = array(get_string('deletestorehasmappings', 'cache'), false);
 117              }
 118  
 119              if ($notifysuccess) {
 120                  if (!$confirm) {
 121                      $title = get_string('confirmstoredeletion', 'cache');
 122                      $params = array('store' => $store, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey());
 123                      $url = new moodle_url($PAGE->url, $params);
 124                      $button = new single_button($url, get_string('deletestore', 'cache'));
 125  
 126                      $PAGE->set_title($title);
 127                      $PAGE->set_heading($SITE->fullname);
 128                      echo $OUTPUT->header();
 129                      echo $OUTPUT->heading($title);
 130                      $confirmation = get_string('deletestoreconfirmation', 'cache', $storeinstancesummaries[$store]['name']);
 131                      echo $OUTPUT->confirm($confirmation, $button, $PAGE->url);
 132                      echo $OUTPUT->footer();
 133                      exit;
 134                  } else {
 135                      $writer = cache_config_writer::instance();
 136                      $writer->delete_store_instance($store);
 137                      redirect($PAGE->url, get_string('deletestoresuccess', 'cache'), 5);
 138                  }
 139              }
 140              break;
 141          case 'editdefinitionmapping' : // Edit definition mappings.
 142              $definition = required_param('definition', PARAM_SAFEPATH);
 143              if (!array_key_exists($definition, $definitionsummaries)) {
 144                  throw new cache_exception('Invalid cache definition requested');
 145              }
 146              $title = get_string('editdefinitionmappings', 'cache', $definition);
 147              $mform = new cache_definition_mappings_form($PAGE->url, array('definition' => $definition));
 148              if ($mform->is_cancelled()) {
 149                  redirect($PAGE->url);
 150              } else if ($data = $mform->get_data()) {
 151                  $writer = cache_config_writer::instance();
 152                  $mappings = array();
 153                  foreach ($data->mappings as $mapping) {
 154                      if (!empty($mapping)) {
 155                          $mappings[] = $mapping;
 156                      }
 157                  }
 158                  $writer->set_definition_mappings($definition, $mappings);
 159                  redirect($PAGE->url);
 160              }
 161              break;
 162          case 'editdefinitionsharing' :
 163              $definition = required_param('definition', PARAM_SAFEPATH);
 164              if (!array_key_exists($definition, $definitionsummaries)) {
 165                  throw new cache_exception('Invalid cache definition requested');
 166              }
 167              $title = get_string('editdefinitionsharing', 'cache', $definition);
 168              $sharingoptions = $definitionsummaries[$definition]['sharingoptions'];
 169              $customdata = array('definition' => $definition, 'sharingoptions' => $sharingoptions);
 170              $mform = new cache_definition_sharing_form($PAGE->url, $customdata);
 171              $mform->set_data(array(
 172                  'sharing' => $definitionsummaries[$definition]['selectedsharingoption'],
 173                  'userinputsharingkey' => $definitionsummaries[$definition]['userinputsharingkey']
 174              ));
 175              if ($mform->is_cancelled()) {
 176                  redirect($PAGE->url);
 177              } else if ($data = $mform->get_data()) {
 178                  $component = $definitionsummaries[$definition]['component'];
 179                  $area = $definitionsummaries[$definition]['area'];
 180                  // Purge the stores removing stale data before we alter the sharing option.
 181                  cache_helper::purge_stores_used_by_definition($component, $area);
 182                  $writer = cache_config_writer::instance();
 183                  $sharing = array_sum(array_keys($data->sharing));
 184                  $userinputsharingkey = $data->userinputsharingkey;
 185                  $writer->set_definition_sharing($definition, $sharing, $userinputsharingkey);
 186                  redirect($PAGE->url);
 187              }
 188              break;
 189          case 'editmodemappings': // Edit default mode mappings.
 190              $mform = new cache_mode_mappings_form(null, $storeinstancesummaries);
 191              $mform->set_data(array(
 192                  'mode_'.cache_store::MODE_APPLICATION => key($defaultmodestores[cache_store::MODE_APPLICATION]),
 193                  'mode_'.cache_store::MODE_SESSION => key($defaultmodestores[cache_store::MODE_SESSION]),
 194                  'mode_'.cache_store::MODE_REQUEST => key($defaultmodestores[cache_store::MODE_REQUEST]),
 195              ));
 196              if ($mform->is_cancelled()) {
 197                  redirect($PAGE->url);
 198              } else if ($data = $mform->get_data()) {
 199                  $mappings = array(
 200                      cache_store::MODE_APPLICATION => array($data->{'mode_'.cache_store::MODE_APPLICATION}),
 201                      cache_store::MODE_SESSION => array($data->{'mode_'.cache_store::MODE_SESSION}),
 202                      cache_store::MODE_REQUEST => array($data->{'mode_'.cache_store::MODE_REQUEST}),
 203                  );
 204                  $writer = cache_config_writer::instance();
 205                  $writer->set_mode_mappings($mappings);
 206                  redirect($PAGE->url);
 207              }
 208              break;
 209  
 210          case 'purgedefinition': // Purge a specific definition.
 211              $id = required_param('definition', PARAM_SAFEPATH);
 212              list($component, $area) = explode('/', $id, 2);
 213              $factory = cache_factory::instance();
 214              $definition = $factory->create_definition($component, $area);
 215              if ($definition->has_required_identifiers()) {
 216                  // We will have to purge the stores used by this definition.
 217                  cache_helper::purge_stores_used_by_definition($component, $area);
 218              } else {
 219                  // Alrighty we can purge just the data belonging to this definition.
 220                  cache_helper::purge_by_definition($component, $area);
 221              }
 222  
 223              $message = get_string('purgexdefinitionsuccess', 'cache', [
 224                          'name' => $definition->get_name(),
 225                          'component' => $component,
 226                          'area' => $area,
 227                      ]);
 228              $purgeagainlink = html_writer::link(new moodle_url('/cache/admin.php', [
 229                      'action' => 'purgedefinition', 'sesskey' => sesskey(), 'definition' => $id]),
 230                      get_string('purgeagain', 'cache'));
 231              redirect($PAGE->url, $message . ' ' . $purgeagainlink, 5);
 232              break;
 233  
 234          case 'purgestore':
 235          case 'purge': // Purge a store cache.
 236              $store = required_param('store', PARAM_TEXT);
 237              cache_helper::purge_store($store);
 238              $message = get_string('purgexstoresuccess', 'cache', ['store' => $store]);
 239              $purgeagainlink = html_writer::link(new moodle_url('/cache/admin.php', [
 240                      'action' => 'purgestore', 'sesskey' => sesskey(), 'store' => $store]),
 241                      get_string('purgeagain', 'cache'));
 242              redirect($PAGE->url, $message . ' ' . $purgeagainlink, 5);
 243              break;
 244  
 245          case 'newlockinstance':
 246              // Adds a new lock instance.
 247              $lock = required_param('lock', PARAM_ALPHANUMEXT);
 248              $mform = cache_administration_helper::get_add_lock_form($lock);
 249              if ($mform->is_cancelled()) {
 250                  redirect($PAGE->url);
 251              } else if ($data = $mform->get_data()) {
 252                  $factory = cache_factory::instance();
 253                  $config = $factory->create_config_instance(true);
 254                  $name = $data->name;
 255                  $data = cache_administration_helper::get_lock_configuration_from_data($lock, $data);
 256                  $config->add_lock_instance($name, $lock, $data);
 257                  redirect($PAGE->url, get_string('addlocksuccess', 'cache', $name), 5);
 258              }
 259              break;
 260          case 'deletelock':
 261              // Deletes a lock instance.
 262              $lock = required_param('lock', PARAM_ALPHANUMEXT);
 263              $confirm = optional_param('confirm', false, PARAM_BOOL);
 264              if (!array_key_exists($lock, $locks)) {
 265                  $notifysuccess = false;
 266                  $notifications[] = array(get_string('invalidlock', 'cache'), false);
 267              } else if ($locks[$lock]['uses'] > 0) {
 268                  $notifysuccess = false;
 269                  $notifications[] = array(get_string('deletelockhasuses', 'cache'), false);
 270              }
 271              if ($notifysuccess) {
 272                  if (!$confirm) {
 273                      $title = get_string('confirmlockdeletion', 'cache');
 274                      $params = array('lock' => $lock, 'confirm' => 1, 'action' => $action, 'sesskey' => sesskey());
 275                      $url = new moodle_url($PAGE->url, $params);
 276                      $button = new single_button($url, get_string('deletelock', 'cache'));
 277  
 278                      $PAGE->set_title($title);
 279                      $PAGE->set_heading($SITE->fullname);
 280                      echo $OUTPUT->header();
 281                      echo $OUTPUT->heading($title);
 282                      $confirmation = get_string('deletelockconfirmation', 'cache', $lock);
 283                      echo $OUTPUT->confirm($confirmation, $button, $PAGE->url);
 284                      echo $OUTPUT->footer();
 285                      exit;
 286                  } else {
 287                      $writer = cache_config_writer::instance();
 288                      $writer->delete_lock_instance($lock);
 289                      redirect($PAGE->url, get_string('deletelocksuccess', 'cache'), 5);
 290                  }
 291              }
 292              break;
 293      }
 294  }
 295  
 296  // Add cache store warnings to the list of notifications.
 297  // Obviously as these are warnings they are show as failures.
 298  foreach (cache_helper::warnings($storeinstancesummaries) as $warning) {
 299      $notifications[] = array($warning, false);
 300  }
 301  
 302  $PAGE->set_title($title);
 303  $PAGE->set_heading($SITE->fullname);
 304  /* @var core_cache_renderer $renderer */
 305  $renderer = $PAGE->get_renderer('core_cache');
 306  
 307  echo $renderer->header();
 308  echo $renderer->heading($title);
 309  echo $renderer->notifications($notifications);
 310  
 311  if ($mform instanceof moodleform) {
 312      $mform->display();
 313  } else {
 314      echo $renderer->store_plugin_summaries($storepluginsummaries);
 315      echo $renderer->store_instance_summariers($storeinstancesummaries, $storepluginsummaries);
 316      echo $renderer->definition_summaries($definitionsummaries, $context);
 317      echo $renderer->lock_summaries($locks);
 318  
 319      $applicationstore = join(', ', $defaultmodestores[cache_store::MODE_APPLICATION]);
 320      $sessionstore = join(', ', $defaultmodestores[cache_store::MODE_SESSION]);
 321      $requeststore = join(', ', $defaultmodestores[cache_store::MODE_REQUEST]);
 322      $editurl = new moodle_url('/cache/admin.php', array('action' => 'editmodemappings', 'sesskey' => sesskey()));
 323      echo $renderer->mode_mappings($applicationstore, $sessionstore, $requeststore, $editurl);
 324  }
 325  
 326  echo $renderer->footer();