Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 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.
/lib/ -> licenselib.php (source)

Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  
  19  /**
  20   * A namespace contains license specific functions
  21   *
  22   * @since      Moodle 2.0
  23   * @package    core
  24   * @subpackage lib
  25   * @copyright  2010 Dongsheng Cai <dongsheng@moodle.com>
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  
  29  defined('MOODLE_INTERNAL') || die();
  30  
  31  class license_manager {
  32  
  33      /**
  34       * License is a core license and can not be updated or deleted.
  35       */
  36      const CORE_LICENSE = 0;
  37  
  38      /**
  39       * License is a custom license and can be updated and/or deleted.
  40       */
  41      const CUSTOM_LICENSE = 1;
  42  
  43      /**
  44       * Integer representation of boolean for a license that is enabled.
  45       */
  46      const LICENSE_ENABLED = 1;
  47  
  48      /**
  49       * Integer representation of boolean for a license that is disabled.
  50       */
  51      const LICENSE_DISABLED = 0;
  52  
  53      /**
  54       * Integer for moving a license up order.
  55       */
  56      const LICENSE_MOVE_UP = -1;
  57  
  58      /**
  59       * Integer for moving a license down order.
  60       */
  61      const LICENSE_MOVE_DOWN = 1;
  62  
  63      /**
  64       * Save a license record.
  65       *
  66       * @param object $license {
  67       *            shortname => string a shortname of license, will be refered by files table[required]
  68       *            fullname  => string the fullname of the license [required]
  69       *            source => string the homepage of the license type[required]
  70       *            enabled => int is it enabled?
  71       *            version  => int a version number used by moodle [required]
  72       * }
  73       */
  74      static public function save($license) {
  75  
  76          $existinglicense = self::get_license_by_shortname($license->shortname);
  77  
  78          if (!empty($existinglicense)) {
  79              $id = $existinglicense->id;
  80              if ($existinglicense->custom == self::CORE_LICENSE) {
  81                  // Can only update the enabled status and sortorder for core licenses.
  82                  $existinglicense->enabled = $license->enabled;
  83                  $existinglicense->sortorder = $license->sortorder;
  84                  $license = $existinglicense;
  85              }
  86              $license->id = $id;
  87              self::update($license);
  88          } else {
  89              self::create($license);
  90          }
  91  
  92          return true;
  93      }
  94  
  95      /**
  96       * Adding a new license type
  97       *
  98       * @deprecated Since Moodle 3.9, MDL-45184.
  99       * @todo MDL-67344 This will be deleted in Moodle 4.1.
 100       * @see license_manager::save()
 101       *
 102       * @param object $license the license record to add.
 103       *
 104       * @return bool true on success.
 105       */
 106      public function add($license) : bool {
 107          debugging('add() is deprecated. Please use license_manager::save() instead.', DEBUG_DEVELOPER);
 108  
 109          return self::save($license);
 110      }
 111  
 112      /**
 113       * Create a license record.
 114       *
 115       * @param object $license the license to create record for.
 116       */
 117      static protected function create($license) {
 118          global $DB;
 119  
 120          $licensecount = count(self::get_licenses());
 121          $license->sortorder = $licensecount + 1;
 122          // Enable all created license by default.
 123          $license->enabled = self::LICENSE_ENABLED;
 124          // API can only create custom licenses, core licenses
 125          // are directly created at install or upgrade.
 126          $license->custom = self::CUSTOM_LICENSE;
 127  
 128          $DB->insert_record('license', $license);
 129          self::reset_license_cache();
 130          // Update the config setting of active licenses.
 131          self::set_active_licenses();
 132      }
 133  
 134      /**
 135       * Read licens record(s) from database.
 136       *
 137       * @param array $params license parameters to return licenses for.
 138       *
 139       * @return array $filteredlicenses object[] of licenses.
 140       */
 141      static public function read(array $params = []) {
 142          $licenses = self::get_licenses();
 143  
 144          $filteredlicenses = [];
 145  
 146          foreach ($licenses as $shortname => $license) {
 147              $filtermatch = true;
 148              foreach ($params as $key => $value) {
 149                  if ($license->$key != $value) {
 150                      $filtermatch = false;
 151                  }
 152              }
 153              if ($filtermatch) {
 154                  $filteredlicenses[$shortname] = $license;
 155              }
 156          }
 157          return $filteredlicenses;
 158  
 159      }
 160  
 161      /**
 162       * Update a license record.
 163       *
 164       * @param object $license the license to update record for.
 165       *
 166       * @throws \moodle_exception if attempting to update a core license.
 167       */
 168      static protected function update($license) {
 169          global $DB;
 170  
 171          $DB->update_record('license', $license);
 172          self::reset_license_cache();
 173      }
 174  
 175      /**
 176       * Delete a custom license.
 177       *
 178       * @param string $licenseshortname the shortname of license.
 179       *
 180       * @throws \moodle_exception when attempting to delete a license you are not allowed to.
 181       */
 182      static public function delete($licenseshortname) {
 183          global $DB;
 184  
 185          $licensetodelete = self::get_license_by_shortname($licenseshortname);
 186  
 187          if (!empty($licensetodelete)) {
 188              if ($licensetodelete->custom == self::CUSTOM_LICENSE) {
 189                  // Check that the license is not in use by any files, if so it cannot be deleted.
 190                  $countfilesusinglicense = $DB->count_records('files', ['license' => $licenseshortname]);
 191                  if ($countfilesusinglicense > 0) {
 192                      throw new moodle_exception('cannotdeletelicenseinuse', 'license');
 193                  }
 194                  $deletedsortorder = $licensetodelete->sortorder;
 195                  $DB->delete_records('license', ['id' => $licensetodelete->id]);
 196  
 197                  // We've deleted a license, so update our list of licenses so we don't save the deleted license again.
 198                  self::reset_license_cache();
 199                  $licenses = self::get_licenses();
 200  
 201                  foreach ($licenses as $license) {
 202                      if ($license->sortorder > $deletedsortorder) {
 203                          $license->sortorder = $license->sortorder - 1;
 204                          self::save($license);
 205                      }
 206                  }
 207  
 208                  // Update the config setting of active licenses as well.
 209                  self::set_active_licenses();
 210  
 211              } else {
 212                  throw new moodle_exception('cannotdeletecore', 'license');
 213              }
 214          } else {
 215              throw new moodle_exception('licensenotfoundshortname', 'license', $licenseshortname);
 216          }
 217      }
 218  
 219      /**
 220       * Get license records.
 221       *
 222       * @return array|false object[] of license records of false if none.
 223       */
 224      static public function get_licenses() {
 225          global $DB;
 226  
 227          $cache = \cache::make('core', 'license');
 228          $licenses = $cache->get('licenses');
 229  
 230          if ($licenses === false) {
 231              $licenses = [];
 232              $records = $DB->get_records_select('license', null, null, 'sortorder ASC');
 233              foreach ($records as $license) {
 234                  $licenses[$license->shortname] = $license;
 235              }
 236              $cache->set('licenses', $licenses);
 237          }
 238  
 239          foreach ($licenses as $license) {
 240              // Localise the license names.
 241              if ($license->custom == self::CORE_LICENSE) {
 242                  $license->fullname = get_string($license->shortname, 'core_license');
 243              } else {
 244                  $license->fullname = format_string($license->fullname);
 245              }
 246          }
 247  
 248          return $licenses;
 249      }
 250  
 251      /**
 252       * Change the sort order of a license (and it's sibling license as a result).
 253       *
 254       * @param int $direction value to change sortorder of license by.
 255       * @param string $licenseshortname the shortname of license to changes sortorder for.
 256       *
 257       * @throws \moodle_exception if attempting to use invalid direction value.
 258       */
 259      static public function change_license_sortorder(int $direction, string $licenseshortname) : void {
 260  
 261          if ($direction != self::LICENSE_MOVE_UP && $direction != self::LICENSE_MOVE_DOWN) {
 262              throw new coding_exception(
 263                  'Must use a valid licence API move direction constant (LICENSE_MOVE_UP or LICENSE_MOVE_DOWN)');
 264          }
 265  
 266          $licenses = self::get_licenses();
 267          $licensetoupdate = $licenses[$licenseshortname];
 268  
 269          $currentsortorder = $licensetoupdate->sortorder;
 270          $targetsortorder = $currentsortorder + $direction;
 271  
 272          if ($targetsortorder > 0 && $targetsortorder <= count($licenses) ) {
 273              foreach ($licenses as $license) {
 274                  if ($license->sortorder == $targetsortorder) {
 275                      $license->sortorder = $license->sortorder - $direction;
 276                      self::update($license);
 277                  }
 278              }
 279              $licensetoupdate->sortorder = $targetsortorder;
 280              self::update($licensetoupdate);
 281          }
 282      }
 283  
 284      /**
 285       * Get license record by shortname
 286       *
 287       * @param string $name the shortname of license
 288       * @return object|null the license or null if no license found.
 289       */
 290      static public function get_license_by_shortname(string $name) {
 291          $licenses = self::read(['shortname' => $name]);
 292  
 293          if (!empty($licenses)) {
 294              $license = reset($licenses);
 295          } else {
 296              $license = null;
 297          }
 298  
 299          return $license;
 300      }
 301  
 302      /**
 303       * Enable a license
 304       * @param string $license the shortname of license
 305       * @return boolean
 306       */
 307      static public function enable($license) {
 308          if ($license = self::get_license_by_shortname($license)) {
 309              $license->enabled = self::LICENSE_ENABLED;
 310              self::update($license);
 311          }
 312          self::set_active_licenses();
 313  
 314          return true;
 315      }
 316  
 317      /**
 318       * Disable a license
 319       * @param string $license the shortname of license
 320       * @return boolean
 321       */
 322      static public function disable($license) {
 323          global $CFG;
 324          // Site default license cannot be disabled!
 325          if ($license == $CFG->sitedefaultlicense) {
 326              print_error('error');
 327          }
 328          if ($license = self::get_license_by_shortname($license)) {
 329              $license->enabled = self::LICENSE_DISABLED;
 330              self::update($license);
 331          }
 332          self::set_active_licenses();
 333  
 334          return true;
 335      }
 336  
 337      /**
 338       * Store active licenses in global config.
 339       */
 340      static protected function set_active_licenses() {
 341          $licenses = self::read(['enabled' => self::LICENSE_ENABLED]);
 342          $result = array();
 343          foreach ($licenses as $l) {
 344              $result[] = $l->shortname;
 345          }
 346          set_config('licenses', implode(',', $result));
 347      }
 348  
 349      /**
 350       * Get the globally configured active licenses.
 351       *
 352       * @return array of license objects.
 353       * @throws \coding_exception
 354       */
 355      static public function get_active_licenses() {
 356          global $CFG;
 357  
 358          $result = [];
 359  
 360          if (!empty($CFG->licenses)) {
 361              $activelicenses = explode(',', $CFG->licenses);
 362              $licenses = self::get_licenses();
 363              foreach ($licenses as $license) {
 364                  if (in_array($license->shortname, $activelicenses)) {
 365                      $result[$license->shortname] = $license;
 366                  }
 367              }
 368          }
 369  
 370          return $result;
 371      }
 372  
 373      /**
 374       * Get the globally configured active licenses as an array.
 375       *
 376       * @return array $licenses an associative array of licenses shaped as ['shortname' => 'fullname']
 377       */
 378      static public function get_active_licenses_as_array() {
 379          $activelicenses = self::get_active_licenses();
 380  
 381          $licenses = [];
 382          foreach ($activelicenses as $license) {
 383              $licenses[$license->shortname] = $license->fullname;
 384          }
 385  
 386          return $licenses;
 387      }
 388  
 389      /**
 390       * Install moodle built-in licenses.
 391       */
 392      static public function install_licenses() {
 393          global $CFG;
 394  
 395          require_once($CFG->libdir . '/db/upgradelib.php');
 396  
 397          upgrade_core_licenses();
 398      }
 399  
 400      /**
 401       * Reset the license cache so it rebuilds next time licenses are fetched.
 402       */
 403      static public function reset_license_cache() {
 404          $cache = \cache::make('core', 'license');
 405          $cache->delete('licenses');
 406      }
 407  }