Search moodle.org's
Developer Documentation

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
  • /lib/ -> licenselib.php (source)

    Differences Between: [Versions 37 and 311] [Versions 38 and 311] [Versions 39 and 311]

       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  }