Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 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   * Class with front-end (editing form) functionality.
  19   *
  20   * This is a base class of a class implemented by each component, and also has
  21   * static methods.
  22   *
  23   * @package core_availability
  24   * @copyright 2014 The Open University
  25   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  26   */
  27  
  28  namespace core_availability;
  29  
  30  defined('MOODLE_INTERNAL') || die();
  31  
  32  /**
  33   * Class with front-end (editing form) functionality.
  34   *
  35   * This is a base class of a class implemented by each component, and also has
  36   * static methods.
  37   *
  38   * @package core_availability
  39   * @copyright 2014 The Open University
  40   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  41   */
  42  abstract class frontend {
  43      /**
  44       * Decides whether this plugin should be available in a given course. The
  45       * plugin can do this depending on course or system settings.
  46       *
  47       * Default returns true.
  48       *
  49       * @param \stdClass $course Course object
  50       * @param \cm_info $cm Course-module currently being edited (null if none)
  51       * @param \section_info $section Section currently being edited (null if none)
  52       */
  53      protected function allow_add($course, \cm_info $cm = null,
  54              \section_info $section = null) {
  55          return true;
  56      }
  57  
  58      /**
  59       * Gets a list of string identifiers (in the plugin's language file) that
  60       * are required in JavaScript for this plugin. The default returns nothing.
  61       *
  62       * You do not need to include the 'title' string (which is used by core) as
  63       * this is automatically added.
  64       *
  65       * @return array Array of required string identifiers
  66       */
  67      protected function get_javascript_strings() {
  68          return array();
  69      }
  70  
  71      /**
  72       * Gets additional parameters for the plugin's initInner function.
  73       *
  74       * Default returns no parameters.
  75       *
  76       * @param \stdClass $course Course object
  77       * @param \cm_info $cm Course-module currently being edited (null if none)
  78       * @param \section_info $section Section currently being edited (null if none)
  79       * @return array Array of parameters for the JavaScript function
  80       */
  81      protected function get_javascript_init_params($course, \cm_info $cm = null,
  82              \section_info $section = null) {
  83          return array();
  84      }
  85  
  86      /**
  87       * Gets the Frankenstyle component name for this plugin.
  88       *
  89       * @return string The component name for this plugin
  90       */
  91      protected function get_component() {
  92          return preg_replace('~^(availability_.*?)\\\\frontend$~', '$1', get_class($this));
  93      }
  94  
  95      /**
  96       * Includes JavaScript for the main system and all plugins.
  97       *
  98       * @param \stdClass $course Course object
  99       * @param \cm_info $cm Course-module currently being edited (null if none)
 100       * @param \section_info $section Section currently being edited (null if none)
 101       */
 102      public static function include_all_javascript($course, \cm_info $cm = null,
 103              \section_info $section = null) {
 104          global $PAGE;
 105  
 106          // Prepare array of required YUI modules. It is bad for performance to
 107          // make multiple yui_module calls, so we group all the plugin modules
 108          // into a single call (the main init function will call init for each
 109          // plugin).
 110          $modules = array('moodle-core_availability-form', 'base', 'node',
 111                  'panel', 'moodle-core-notification-dialogue', 'json');
 112  
 113          // Work out JS to include for all components.
 114          $pluginmanager = \core_plugin_manager::instance();
 115          $enabled = $pluginmanager->get_enabled_plugins('availability');
 116          $componentparams = new \stdClass();
 117          foreach ($enabled as $plugin => $info) {
 118              // Create plugin front-end object.
 119              $class = '\availability_' . $plugin . '\frontend';
 120              $frontend = new $class();
 121  
 122              // Add to array of required YUI modules.
 123              $component = $frontend->get_component();
 124              $modules[] = 'moodle-' . $component . '-form';
 125  
 126              // Get parameters for this plugin.
 127              $componentparams->{$plugin} = array($component,
 128                      $frontend->allow_add($course, $cm, $section),
 129                      $frontend->get_javascript_init_params($course, $cm, $section));
 130  
 131              // Include strings for this plugin.
 132              $identifiers = $frontend->get_javascript_strings();
 133              $identifiers[] = 'title';
 134              $identifiers[] = 'description';
 135              $PAGE->requires->strings_for_js($identifiers, $component);
 136          }
 137  
 138          // Include all JS (in one call). The init function runs on DOM ready.
 139          $PAGE->requires->yui_module($modules,
 140                  'M.core_availability.form.init', array($componentparams), null, true);
 141  
 142          // Include main strings.
 143          $PAGE->requires->strings_for_js(array('none', 'cancel', 'delete', 'choosedots'),
 144                  'moodle');
 145          $PAGE->requires->strings_for_js(array('addrestriction', 'invalid',
 146                  'listheader_sign_before', 'listheader_sign_pos',
 147                  'listheader_sign_neg', 'listheader_single',
 148                  'listheader_multi_after', 'listheader_multi_before',
 149                  'listheader_multi_or', 'listheader_multi_and',
 150                  'unknowncondition', 'hide_verb', 'hidden_individual',
 151                  'show_verb', 'shown_individual', 'hidden_all', 'shown_all',
 152                  'condition_group', 'condition_group_info', 'and', 'or',
 153                  'label_multi', 'label_sign', 'setheading', 'itemheading',
 154                  'missingplugin'),
 155                  'availability');
 156      }
 157  
 158      /**
 159       * For use within forms, reports any validation errors from the availability
 160       * field.
 161       *
 162       * @param array $data Form data fields
 163       * @param array $errors Error array
 164       */
 165      public static function report_validation_errors(array $data, array &$errors) {
 166          // Empty value is allowed!
 167          if ($data['availabilityconditionsjson'] === '') {
 168              return;
 169          }
 170  
 171          // Decode value.
 172          $decoded = json_decode($data['availabilityconditionsjson']);
 173          if (!$decoded) {
 174              // This shouldn't be possible.
 175              throw new \coding_exception('Invalid JSON from availabilityconditionsjson field');
 176          }
 177          if (!empty($decoded->errors)) {
 178              $error = '';
 179              foreach ($decoded->errors as $stringinfo) {
 180                  list ($component, $stringname) = explode(':', $stringinfo);
 181                  if ($error !== '') {
 182                      $error .= ' ';
 183                  }
 184                  $error .= get_string($stringname, $component);
 185              }
 186              $errors['availabilityconditionsjson'] = $error;
 187          }
 188      }
 189  
 190      /**
 191       * Converts an associative array into an array of objects with two fields.
 192       *
 193       * This is necessary because JavaScript associative arrays/objects are not
 194       * ordered (at least officially according to the language specification).
 195       *
 196       * @param array $inarray Associative array key => value
 197       * @param string $keyname Name to use for key in resulting array objects
 198       * @param string $valuename Name to use for value in resulting array objects
 199       * @return array Non-associative (numeric) array
 200       */
 201      protected static function convert_associative_array_for_js(array $inarray,
 202              $keyname, $valuename) {
 203          $result = array();
 204          foreach ($inarray as $key => $value) {
 205              $result[] = (object)array($keyname => $key, $valuename => $value);
 206          }
 207          return $result;
 208      }
 209  }