Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.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  namespace mod_bigbluebuttonbn\local\plugins;
  17  
  18  use cache_helper;
  19  use context_system;
  20  use core_component;
  21  use core_plugin_manager;
  22  use flexible_table;
  23  use html_writer;
  24  use mod_bigbluebuttonbn\extension;
  25  use moodle_url;
  26  use pix_icon;
  27  
  28  /**
  29   * Class that handles the display and configuration of the list of extension plugins.
  30   *
  31   * This is directly taken from the mod_assign code. We might need to have a global API there for this.
  32   *
  33   * @package   mod_bigbluebuttonbn
  34   * @copyright 2023 onwards, Blindside Networks Inc
  35   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   * @author    Laurent David (laurent@call-learning.fr)
  37   */
  38  class admin_plugin_manager {
  39      /** @var object the url of the manage submission plugin page */
  40      private $pageurl;
  41  
  42      /**
  43       * Constructor for this assignment plugin manager
  44       *
  45       */
  46      public function __construct() {
  47          $this->pageurl = new moodle_url(admin_page_manage_extensions::ADMIN_PAGE_URL);
  48      }
  49  
  50      /**
  51       * This is the entry point for this controller class.
  52       *
  53       * @param string|null $action - The action to perform
  54       * @param string|null $plugin - Optional name of a plugin type to perform the action on
  55       * @return void
  56       */
  57      public function execute(?string $action = null, ?string $plugin = null): void {
  58          if (empty($action) || empty($plugin)) {
  59              $action = 'view';
  60          }
  61          $this->check_permissions();
  62  
  63          $actionname = "plugins_$action";
  64          if (method_exists($this, $actionname)) {
  65              $nextaction = $this->$actionname($plugin);
  66              if ($nextaction) {
  67                  $this->execute($nextaction, $plugin);
  68              }
  69          }
  70      }
  71  
  72      /**
  73       * Check this user has permission to edit the list of installed plugins
  74       *
  75       * @return void
  76       */
  77      private function check_permissions(): void {
  78          require_login();
  79          $systemcontext = context_system::instance();
  80          require_capability('moodle/site:config', $systemcontext);
  81      }
  82  
  83      /**
  84       * Write the HTML for the submission plugins table.
  85       *
  86       * @return void
  87       */
  88      private function plugins_view(): void {
  89          global $OUTPUT, $CFG;
  90          require_once($CFG->libdir . '/tablelib.php');
  91          $this->print_header();
  92          $table = new flexible_table(extension::BBB_EXTENSION_PLUGIN_NAME . 'pluginsadminttable');
  93          $table->define_baseurl($this->pageurl);
  94          $table->define_columns([
  95              'pluginname',
  96              'version',
  97              'hideshow',
  98              'order',
  99              'settings',
 100              'uninstall'
 101          ]);
 102          $table->define_headers([
 103              get_string('subplugintype_bbbext', 'mod_bigbluebuttonbn'),
 104              get_string('version'), get_string('hide') . '/' . get_string('show'),
 105              get_string('order'),
 106              get_string('settings'),
 107              get_string('uninstallplugin', 'core_admin')
 108          ]);
 109          $table->set_attribute('id', extension::BBB_EXTENSION_PLUGIN_NAME . 'plugins');
 110          $table->set_attribute('class', 'admintable generaltable');
 111          $table->setup();
 112  
 113          $plugins = $this->get_sorted_plugins_list();
 114          $instances = core_plugin_manager::instance()->get_plugins_of_type(extension::BBB_EXTENSION_PLUGIN_NAME);
 115  
 116          foreach ($plugins as $idx => $plugin) {
 117              $componentname = extension::BBB_EXTENSION_PLUGIN_NAME . '_' . $plugin;
 118              $typebasedir = "";
 119              if (in_array($plugin, array_keys($instances))) {
 120                  $typebasedir = ($instances[$plugin])->typerootdir;
 121              }
 122              $row = [];
 123              $class = '';
 124              $pluginversion = get_config($componentname, 'version');
 125              $row[] = get_string('pluginname', $componentname);
 126              $row[] = $pluginversion;
 127              $visible = !get_config($componentname, 'disabled');
 128  
 129              if ($visible) {
 130                  $row[] = $this->format_icon_link('hide', $plugin, 't/hide', get_string('disable'));
 131              } else {
 132                  $row[] = $this->format_icon_link('show', $plugin, 't/show', get_string('enable'));
 133                  $class = 'dimmed_text';
 134              }
 135  
 136              $movelinks = '';
 137              if (!$idx == 0) {
 138                  $movelinks .= $this->format_icon_link('moveup', $plugin, 't/up', get_string('up')) . ' ';
 139              } else {
 140                  $movelinks .= $OUTPUT->spacer(['width' => 16]);
 141              }
 142              if ($idx != count($plugins) - 1) {
 143                  $movelinks .= $this->format_icon_link('movedown', $plugin, 't/down', get_string('down')) . ' ';
 144              }
 145              $row[] = $movelinks;
 146  
 147              $exists = file_exists($typebasedir . '/' . $plugin . '/settings.php');
 148              // We do not display settings for plugin who have not yet been installed (so have no version yet).
 149              if (!empty($pluginversion) && $exists) {
 150                  $row[] = html_writer::link(
 151                      new moodle_url('/admin/settings.php', ['section' => $componentname]),
 152                      get_string('settings')
 153                  );
 154              } else {
 155                  $row[] = '&nbsp;';
 156              }
 157              $url = core_plugin_manager::instance()->get_uninstall_url(
 158                  $componentname,
 159                  'manage'
 160              );
 161              if ($url) {
 162                  $row[] = html_writer::link($url, get_string('uninstallplugin', 'core_admin'));
 163              } else {
 164                  $row[] = '&nbsp;';
 165              }
 166  
 167              $table->add_data($row, $class);
 168          }
 169  
 170          $table->finish_output();
 171          $this->print_footer();
 172      }
 173  
 174      /**
 175       * Write the page header
 176       *
 177       * @return void
 178       */
 179      private function print_header(): void {
 180          global $OUTPUT;
 181          $pageidentifier = 'manage' . extension::BBB_EXTENSION_PLUGIN_NAME . 'plugins';
 182          admin_externalpage_setup($pageidentifier);
 183          echo $OUTPUT->header();
 184          echo $OUTPUT->heading(get_string($pageidentifier, 'mod_bigbluebuttonbn'));
 185      }
 186  
 187      /**
 188       * Return a list of plugins sorted by the order defined in the admin interface
 189       *
 190       * @return array The list of plugins
 191       */
 192      public function get_sorted_plugins_list(): array {
 193          $names = core_component::get_plugin_list(extension::BBB_EXTENSION_PLUGIN_NAME);
 194  
 195          $result = [];
 196  
 197          foreach ($names as $name => $path) {
 198              $idx = get_config(extension::BBB_EXTENSION_PLUGIN_NAME . '_' . $name, 'sortorder');
 199              if (!$idx) {
 200                  $idx = 0;
 201              }
 202              while (array_key_exists($idx, $result)) {
 203                  $idx += 1;
 204              }
 205              $result[$idx] = $name;
 206          }
 207          ksort($result);
 208  
 209          return $result;
 210      }
 211  
 212      /**
 213       * Util function for writing an action icon link
 214       *
 215       * @param string $action URL parameter to include in the link
 216       * @param string $plugin URL parameter to include in the link
 217       * @param string $icon The key to the icon to use (e.g. 't/up')
 218       * @param string $alt The string description of the link used as the title and alt text
 219       * @return string The icon/link
 220       */
 221      private function format_icon_link(string $action, string $plugin, string $icon, string $alt): string {
 222          global $OUTPUT;
 223          return $OUTPUT->action_icon(
 224                  new moodle_url(
 225                      $this->pageurl,
 226                      ['action' => $action, 'plugin' => $plugin, 'sesskey' => sesskey()]
 227                  ),
 228                  new pix_icon($icon, $alt, 'moodle', ['title' => $alt]),
 229                  null,
 230                  ['title' => $alt]
 231              );
 232      }
 233  
 234      /**
 235       * Write the page footer
 236       *
 237       * @return void
 238       */
 239      private function print_footer(): void {
 240          global $OUTPUT;
 241          echo $OUTPUT->footer();
 242      }
 243  
 244      /**
 245       * Hide this plugin.
 246       *
 247       * @param string $plugin - The plugin to hide
 248       * @return string The next page to display
 249       */
 250      private function plugins_hide(string $plugin): string {
 251          $class = \core_plugin_manager::resolve_plugininfo_class(extension::BBB_EXTENSION_PLUGIN_NAME);
 252          $class::enable_plugin($plugin, false);
 253          cache_helper::purge_by_event('mod_bigbluebuttonbn/pluginenabledisabled');
 254          return 'view';
 255      }
 256  
 257      /**
 258       * Show this plugin.
 259       *
 260       * @param string $plugin - The plugin to show
 261       * @return string The next page to display
 262       */
 263      private function plugins_show(string $plugin): string {
 264          $class = \core_plugin_manager::resolve_plugininfo_class(extension::BBB_EXTENSION_PLUGIN_NAME);
 265          $class::enable_plugin($plugin, true);
 266          cache_helper::purge_by_event('mod_bigbluebuttonbn/pluginenabledisabled');
 267          return 'view';
 268      }
 269  
 270      /**
 271       * Move this plugin up
 272       *
 273       * We need this function so we can call directly (without the dir parameter)
 274       * @param string $plugintomove - The plugin to move
 275       * @return string The next page to display
 276       */
 277      private function plugins_moveup(string $plugintomove): string {
 278          return $this->move_plugin($plugintomove, 'up');
 279      }
 280  
 281      /**
 282       * Move this plugin down
 283       *
 284       * We need this function so we can call directly (without the dir parameter)
 285       * @param string $plugintomove - The plugin to move
 286       * @return string The next page to display
 287       */
 288      private function plugins_movedown(string $plugintomove): string {
 289          return $this->move_plugin($plugintomove, 'down');
 290      }
 291  
 292      /**
 293       * Change the order of this plugin.
 294       *
 295       * @param string $plugintomove - The plugin to move
 296       * @param string $dir - up or down
 297       * @return string The next page to display
 298       */
 299      private function move_plugin(string $plugintomove, string $dir): string {
 300          $plugins = $this->get_sorted_plugins_list();
 301          $plugins = array_values($plugins);
 302          $currentindex = array_search($plugintomove, $plugins);
 303          if ($currentindex === false) {
 304              return 'view';
 305          }
 306          // Make the switch.
 307          if ($dir === 'up') {
 308              if ($currentindex > 0) {
 309                  $tempplugin = $plugins[$currentindex - 1];
 310                  $plugins[$currentindex - 1] = $plugins[$currentindex];
 311                  $plugins[$currentindex] = $tempplugin;
 312              }
 313          } else if ($dir === 'down') {
 314              if ($currentindex < (count($plugins) - 1)) {
 315                  $tempplugin = $plugins[$currentindex + 1];
 316                  $plugins[$currentindex + 1] = $plugins[$currentindex];
 317                  $plugins[$currentindex] = $tempplugin;
 318              }
 319          }
 320  
 321          // Save the new normal order.
 322          foreach ($plugins as $key => $plugin) {
 323              set_config('sortorder', $key, extension::BBB_EXTENSION_PLUGIN_NAME . '_' . $plugin);
 324          }
 325          return 'view';
 326      }
 327  }