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.
   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   * Contains the import_handler_registry class.
  18   *
  19   * @package tool_moodlenet
  20   * @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
  21   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22   */
  23  namespace tool_moodlenet\local;
  24  
  25  /**
  26   * The import_handler_registry class.
  27   *
  28   * The import_handler_registry objects represent a register of modules handling various file extensions for a given course and user.
  29   * Only modules which are available to the user in the course are included in the register for that user.
  30   *
  31   * @copyright 2020 Jake Dallimore <jrhdallimore@gmail.com>
  32   * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  33   */
  34  class import_handler_registry {
  35  
  36      /**
  37       * @var array array containing the names and messages of all modules handling import of resources as a 'file' type.
  38       */
  39      protected $filehandlers = [];
  40  
  41      /**
  42       * @var array $typehandlers the array of modules registering as handlers of other, non-file types, indexed by typename.
  43       */
  44      protected $typehandlers = [];
  45  
  46      /**
  47       * @var array $registry the aggregate of all registrations made by plugins, indexed by 'file' and 'type'.
  48       */
  49      protected $registry = [];
  50  
  51      /**
  52       * @var \context_course the course context object.
  53       */
  54      protected $context;
  55  
  56      /**
  57       * @var \stdClass a course object.
  58       */
  59      protected $course;
  60  
  61      /**
  62       * @var \stdClass a user object.
  63       */
  64      protected $user;
  65  
  66      /**
  67       * The import_handler_registry constructor.
  68       *
  69       * @param \stdClass $course the course, which impacts available handlers.
  70       * @param \stdClass $user the user, which impacts available handlers.
  71       */
  72      public function __construct(\stdClass $course, \stdClass $user) {
  73          $this->course = $course;
  74          $this->user = $user;
  75          $this->context = \context_course::instance($course->id);
  76  
  77          // Generate the full list of handlers for all extensions for this user and course.
  78          $this->populate_handlers();
  79      }
  80  
  81      /**
  82       * Get all handlers for the remote resource, depending on the strategy being used to import the resource.
  83       *
  84       * @param remote_resource $resource the remote resource.
  85       * @param import_strategy $strategy an import_strategy instance.
  86       * @return import_handler_info[] the array of import_handler_info handlers.
  87       */
  88      public function get_resource_handlers_for_strategy(remote_resource $resource, import_strategy $strategy): array {
  89          return $strategy->get_handlers($this->registry, $resource);
  90      }
  91  
  92      /**
  93       * Get a specific handler for the resource, belonging to a specific module and for a specific strategy.
  94       *
  95       * @param remote_resource $resource the remote resource.
  96       * @param string $modname the name of the module, e.g. 'label'.
  97       * @param import_strategy $strategy a string representing how to treat the resource. e.g. 'file', 'link'.
  98       * @return import_handler_info|null the import_handler_info object, if found, otherwise null.
  99       */
 100      public function get_resource_handler_for_mod_and_strategy(remote_resource $resource, string $modname,
 101              import_strategy $strategy): ?import_handler_info {
 102          foreach ($strategy->get_handlers($this->registry, $resource) as $handler) {
 103              if ($handler->get_module_name() === $modname) {
 104                  return $handler;
 105              }
 106          }
 107          return null;
 108      }
 109  
 110      /**
 111       * Build up a list of extension handlers by leveraging the dndupload_register callbacks.
 112       */
 113      protected function populate_handlers() {
 114          // Generate a dndupload_handler object, just so we can call ->is_known_type() on the types being registered by plugins.
 115          // We must vet each type which is reported to be handled against the list of known, supported types.
 116          global $CFG;
 117          require_once($CFG->dirroot . '/course/dnduploadlib.php');
 118          $dndhandlers = new \dndupload_handler($this->course);
 119  
 120          // Get the list of mods enabled at site level first. We need to cross check this.
 121          $pluginman = \core_plugin_manager::instance();
 122          $sitemods = $pluginman->get_plugins_of_type('mod');
 123          $sitedisabledmods = array_filter($sitemods, function(\core\plugininfo\mod $modplugininfo){
 124              return !$modplugininfo->is_enabled();
 125          });
 126          $sitedisabledmods = array_map(function($modplugininfo) {
 127              return $modplugininfo->name;
 128          }, $sitedisabledmods);
 129  
 130          // Loop through all modules to find the registered handlers.
 131          $mods = get_plugin_list_with_function('mod', 'dndupload_register');
 132          foreach ($mods as $component => $funcname) {
 133              list($modtype, $modname) = \core_component::normalize_component($component);
 134              if (!empty($sitedisabledmods) && array_key_exists($modname, $sitedisabledmods)) {
 135                  continue; // Module is disabled at the site level.
 136              }
 137              if (!course_allowed_module($this->course, $modname, $this->user)) {
 138                  continue; // User does not have permission to add this module to the course.
 139              }
 140  
 141              if (!$resp = component_callback($component, 'dndupload_register')) {
 142                  continue;
 143              };
 144  
 145              if (isset($resp['files'])) {
 146                  foreach ($resp['files'] as $file) {
 147                      $this->register_file_handler($file['extension'], $modname, $file['message']);
 148                  }
 149              }
 150              if (isset($resp['types'])) {
 151                  foreach ($resp['types'] as $type) {
 152                      if (!$dndhandlers->is_known_type($type['identifier'])) {
 153                          throw new \coding_exception("Trying to add handler for unknown type $type");
 154                      }
 155                      $this->register_type_handler($type['identifier'], $modname, $type['message']);
 156                  }
 157              }
 158          }
 159          $this->registry = [
 160              'files' => $this->filehandlers,
 161              'types' => $this->typehandlers
 162          ];
 163      }
 164  
 165      /**
 166       * Adds a type handler to the list.
 167       *
 168       * @param string $identifier the name of the type.
 169       * @param string $module the name of the module, e.g. 'label'.
 170       * @param string $message the message describing how the module handles the type.
 171       */
 172      protected function register_type_handler(string $identifier, string $module,  string $message) {
 173          $this->typehandlers[$identifier][] = ['module' => $module, 'message' => $message];
 174      }
 175  
 176      /**
 177       * Adds a file extension handler to the list.
 178       *
 179       * @param string $extension the extension, e.g. 'png'.
 180       * @param string $module the name of the module handling this extension
 181       * @param string $message the message describing how the module handles the extension.
 182       */
 183      protected function register_file_handler(string $extension, string $module, string $message) {
 184          $extension = strtolower($extension);
 185          $this->filehandlers[$extension][] = ['module' => $module, 'message' => $message];
 186      }
 187  }
 188