From 4399e4759a07d2f38e8519860dcf3eb337275643 Mon Sep 17 00:00:00 2001 From: Tom Dickman Date: Thu, 31 Oct 2019 12:32:17 +1100 Subject: [PATCH 1/3] MDL-45184 tool_licenses: Add custom licenses This feature adds an admin tool for creating custom licenses. Now custom licenses can be added and amended in Moodle, and the site default can be set to a custom license. Core licenses remain hard-coded and are uneditable, so they will always require update within Moodle core updates, and maintain their internationalisation through core language strings. This also includes fundamental changes to the license API including the addition of license caching and deprecation of no longer required admin settings for license management. --- admin/settings/license.php | 45 ++ admin/settings/plugins.php | 14 - admin/settings/top.php | 1 + .../amd/build/delete_license.min.js | 2 + .../amd/build/delete_license.min.js.map | 1 + .../licensemanager/amd/src/delete_license.js | 51 +++ .../classes/form/edit_license.php | 124 ++++++ admin/tool/licensemanager/classes/helper.php | 154 +++++++ admin/tool/licensemanager/classes/manager.php | 247 +++++++++++ .../classes/output/renderer.php | 96 +++++ .../licensemanager/classes/output/table.php | 186 ++++++++ .../classes/privacy/provider.php | 47 ++ .../licensemanager/index.php} | 40 +- .../lang/en/tool_licensemanager.php | 52 +++ admin/tool/licensemanager/settings.php | 33 ++ .../tests/behat/delete_license.feature | 29 ++ .../tests/behat/edit_license.feature | 83 ++++ .../tests/behat/license_manager.feature | 38 ++ .../tool/licensemanager/tests/helper_test.php | 44 ++ .../licensemanager/tests/manager_test.php | 199 +++++++++ admin/tool/licensemanager/version.php | 31 ++ lang/en/admin.php | 8 +- lang/en/cache.php | 1 + lang/en/deprecated.txt | 2 + lang/en/license.php | 9 +- lib/adminlib.php | 85 ++-- lib/classes/plugin_manager.php | 9 +- lib/db/caches.php | 7 + lib/db/install.xml | 3 + lib/db/upgrade.php | 35 ++ lib/db/upgradelib.php | 121 ++++++ lib/form/filemanager.js | 28 +- lib/form/filemanager.php | 13 +- lib/licenselib.php | 408 +++++++++++++----- lib/tests/licenselib_test.php | 345 +++++++++++++++ lib/tests/upgradelib_test.php | 29 ++ repository/filepicker.js | 53 ++- repository/lib.php | 17 +- version.php | 2 +- 39 files changed, 2430 insertions(+), 262 deletions(-) create mode 100644 admin/settings/license.php create mode 100644 admin/tool/licensemanager/amd/build/delete_license.min.js create mode 100644 admin/tool/licensemanager/amd/build/delete_license.min.js.map create mode 100644 admin/tool/licensemanager/amd/src/delete_license.js create mode 100644 admin/tool/licensemanager/classes/form/edit_license.php create mode 100644 admin/tool/licensemanager/classes/helper.php create mode 100644 admin/tool/licensemanager/classes/manager.php create mode 100644 admin/tool/licensemanager/classes/output/renderer.php create mode 100644 admin/tool/licensemanager/classes/output/table.php create mode 100644 admin/tool/licensemanager/classes/privacy/provider.php rename admin/{licenses.php => tool/licensemanager/index.php} (55%) create mode 100644 admin/tool/licensemanager/lang/en/tool_licensemanager.php create mode 100644 admin/tool/licensemanager/settings.php create mode 100644 admin/tool/licensemanager/tests/behat/delete_license.feature create mode 100644 admin/tool/licensemanager/tests/behat/edit_license.feature create mode 100644 admin/tool/licensemanager/tests/behat/license_manager.feature create mode 100644 admin/tool/licensemanager/tests/helper_test.php create mode 100644 admin/tool/licensemanager/tests/manager_test.php create mode 100644 admin/tool/licensemanager/version.php create mode 100644 lib/tests/licenselib_test.php diff --git a/admin/settings/license.php b/admin/settings/license.php new file mode 100644 index 00000000000..bd9ad8fd09a --- /dev/null +++ b/admin/settings/license.php @@ -0,0 +1,45 @@ +. + +/** + * This file defines the settings pages for licenses. + * + * @package core + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +require_once($CFG->libdir . '/licenselib.php'); + +if ($hassiteconfig) { + + $temp = new admin_settingpage('licensesettings', new lang_string('licensesettings', 'admin')); + + $licenses = license_manager::get_active_licenses_as_array(); + + $temp->add(new admin_setting_configselect('sitedefaultlicense', + new lang_string('configsitedefaultlicense', 'admin'), + new lang_string('configsitedefaultlicensehelp', 'admin'), + 'unknown', + $licenses)); + $temp->add(new admin_setting_configcheckbox('rememberuserlicensepref', + new lang_string('rememberuserlicensepref', 'admin'), + new lang_string('rememberuserlicensepref_help', 'admin'), + 1)); + $ADMIN->add('license', $temp); +} diff --git a/admin/settings/plugins.php b/admin/settings/plugins.php index 278d4f35eb0..4eb6ec4a7a2 100644 --- a/admin/settings/plugins.php +++ b/admin/settings/plugins.php @@ -182,20 +182,6 @@ if ($hassiteconfig) { $plugin->load_settings($ADMIN, 'mlbackendsettings', $hassiteconfig); } -/// License types - $ADMIN->add('modules', new admin_category('licensesettings', new lang_string('licenses'))); - $temp = new admin_settingpage('managelicenses', new lang_string('managelicenses', 'admin')); - - require_once($CFG->libdir . '/licenselib.php'); - $licenses = array(); - $array = explode(',', $CFG->licenses); - foreach ($array as $value) { - $licenses[$value] = new lang_string($value, 'license'); - } - $temp->add(new admin_setting_configselect('sitedefaultlicense', new lang_string('configsitedefaultlicense','admin'), new lang_string('configsitedefaultlicensehelp','admin'), 'allrightsreserved', $licenses)); - $temp->add(new admin_setting_managelicenses()); - $ADMIN->add('licensesettings', $temp); - /// Filter plugins $ADMIN->add('modules', new admin_category('filtersettings', new lang_string('managefilters'))); diff --git a/admin/settings/top.php b/admin/settings/top.php index 8c922d1196c..87178430ea1 100644 --- a/admin/settings/top.php +++ b/admin/settings/top.php @@ -32,6 +32,7 @@ $ADMIN->add('root', new admin_category('analytics', new lang_string('analytics', $ADMIN->add('root', new admin_category('competencies', new lang_string('competencies', 'core_competency'))); $ADMIN->add('root', new admin_category('badges', new lang_string('badges'), empty($CFG->enablebadges))); $ADMIN->add('root', new admin_category('h5p', new lang_string('h5p', 'core_h5p'))); +$ADMIN->add('root', new admin_category('license', new lang_string('license'))); $ADMIN->add('root', new admin_category('location', new lang_string('location','admin'))); $ADMIN->add('root', new admin_category('language', new lang_string('language'))); $ADMIN->add('root', new admin_category('messaging', new lang_string('messagingcategory', 'admin'))); diff --git a/admin/tool/licensemanager/amd/build/delete_license.min.js b/admin/tool/licensemanager/amd/build/delete_license.min.js new file mode 100644 index 00000000000..17dd2af256b --- /dev/null +++ b/admin/tool/licensemanager/amd/build/delete_license.min.js @@ -0,0 +1,2 @@ +define ("tool_licensemanager/delete_license",["jquery","core/modal_factory","core/modal_events","core/url","core/str"],function(a,b,c,d,e){var f=a(".delete-license");b.create({type:b.types.SAVE_CANCEL,title:e.get_string("deletelicense","tool_licensemanager"),body:e.get_string("deletelicenseconfirmmessage","tool_licensemanager"),preShowCallback:function preShowCallback(b,c){b=a(b);var e={action:"delete",license:b.data("license")};c.deleteURL=d.relativeUrl("/admin/tool/licensemanager/index.php",e,!0)},large:!0},f).done(function(a){a.getRoot().on(c.save,function(b){b.preventDefault();window.location.href=a.deleteURL})})}); +//# sourceMappingURL=delete_license.min.js.map diff --git a/admin/tool/licensemanager/amd/build/delete_license.min.js.map b/admin/tool/licensemanager/amd/build/delete_license.min.js.map new file mode 100644 index 00000000000..caee9ae810d --- /dev/null +++ b/admin/tool/licensemanager/amd/build/delete_license.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/delete_license.js"],"names":["define","$","ModalFactory","ModalEvents","Url","String","trigger","create","type","types","SAVE_CANCEL","title","get_string","body","preShowCallback","triggerElement","modal","params","data","deleteURL","relativeUrl","large","done","getRoot","on","save","e","preventDefault","window","location","href"],"mappings":"AAwBAA,OAAM,sCAAC,CAAC,QAAD,CAAW,oBAAX,CAAiC,mBAAjC,CAAsD,UAAtD,CAAkE,UAAlE,CAAD,CACF,SAASC,CAAT,CAAYC,CAAZ,CAA0BC,CAA1B,CAAuCC,CAAvC,CAA4CC,CAA5C,CAAoD,CAEhD,GAAIC,CAAAA,CAAO,CAAGL,CAAC,CAAC,iBAAD,CAAf,CACAC,CAAY,CAACK,MAAb,CAAoB,CAChBC,IAAI,CAAEN,CAAY,CAACO,KAAb,CAAmBC,WADT,CAEhBC,KAAK,CAAEN,CAAM,CAACO,UAAP,CAAkB,eAAlB,CAAmC,qBAAnC,CAFS,CAGhBC,IAAI,CAAER,CAAM,CAACO,UAAP,CAAkB,6BAAlB,CAAiD,qBAAjD,CAHU,CAIhBE,eAAe,CAAE,yBAASC,CAAT,CAAyBC,CAAzB,CAAgC,CAC7CD,CAAc,CAAGd,CAAC,CAACc,CAAD,CAAlB,CACA,GAAIE,CAAAA,CAAM,CAAG,CACT,OAAU,QADD,CAET,QAAWF,CAAc,CAACG,IAAf,CAAoB,SAApB,CAFF,CAAb,CAIAF,CAAK,CAACG,SAAN,CAAkBf,CAAG,CAACgB,WAAJ,CAAgB,sCAAhB,CAAwDH,CAAxD,IACrB,CAXe,CAYhBI,KAAK,GAZW,CAApB,CAaGf,CAbH,EAcKgB,IAdL,CAcU,SAASN,CAAT,CAAgB,CAClBA,CAAK,CAACO,OAAN,GAAgBC,EAAhB,CAAmBrB,CAAW,CAACsB,IAA/B,CAAqC,SAASC,CAAT,CAAY,CAE7CA,CAAC,CAACC,cAAF,GAEAC,MAAM,CAACC,QAAP,CAAgBC,IAAhB,CAAuBd,CAAK,CAACG,SAChC,CALD,CAMH,CArBL,CAsBH,CA1BC,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Modal for confirming deletion of a custom license.\n *\n * @module tool_licensemanager/delete_license\n * @class delete_license\n * @package tool_licensemanager\n * @copyright 2019 Tom Dickman \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/modal_factory', 'core/modal_events', 'core/url', 'core/str'],\n function($, ModalFactory, ModalEvents, Url, String) {\n\n var trigger = $('.delete-license');\n ModalFactory.create({\n type: ModalFactory.types.SAVE_CANCEL,\n title: String.get_string('deletelicense', 'tool_licensemanager'),\n body: String.get_string('deletelicenseconfirmmessage', 'tool_licensemanager'),\n preShowCallback: function(triggerElement, modal) {\n triggerElement = $(triggerElement);\n let params = {\n 'action': 'delete',\n 'license': triggerElement.data('license')\n };\n modal.deleteURL = Url.relativeUrl('/admin/tool/licensemanager/index.php', params, true);\n },\n large: true,\n }, trigger)\n .done(function(modal) {\n modal.getRoot().on(ModalEvents.save, function(e) {\n // Stop the default save button behaviour which is to close the modal.\n e.preventDefault();\n // Redirect to delete url.\n window.location.href = modal.deleteURL;\n });\n });\n });\n"],"file":"delete_license.min.js"} \ No newline at end of file diff --git a/admin/tool/licensemanager/amd/src/delete_license.js b/admin/tool/licensemanager/amd/src/delete_license.js new file mode 100644 index 00000000000..6abdcec052e --- /dev/null +++ b/admin/tool/licensemanager/amd/src/delete_license.js @@ -0,0 +1,51 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Modal for confirming deletion of a custom license. + * + * @module tool_licensemanager/delete_license + * @class delete_license + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['jquery', 'core/modal_factory', 'core/modal_events', 'core/url', 'core/str'], + function($, ModalFactory, ModalEvents, Url, String) { + + var trigger = $('.delete-license'); + ModalFactory.create({ + type: ModalFactory.types.SAVE_CANCEL, + title: String.get_string('deletelicense', 'tool_licensemanager'), + body: String.get_string('deletelicenseconfirmmessage', 'tool_licensemanager'), + preShowCallback: function(triggerElement, modal) { + triggerElement = $(triggerElement); + let params = { + 'action': 'delete', + 'license': triggerElement.data('license') + }; + modal.deleteURL = Url.relativeUrl('/admin/tool/licensemanager/index.php', params, true); + }, + large: true, + }, trigger) + .done(function(modal) { + modal.getRoot().on(ModalEvents.save, function(e) { + // Stop the default save button behaviour which is to close the modal. + e.preventDefault(); + // Redirect to delete url. + window.location.href = modal.deleteURL; + }); + }); + }); diff --git a/admin/tool/licensemanager/classes/form/edit_license.php b/admin/tool/licensemanager/classes/form/edit_license.php new file mode 100644 index 00000000000..624ce80fa01 --- /dev/null +++ b/admin/tool/licensemanager/classes/form/edit_license.php @@ -0,0 +1,124 @@ +. + +/** + * Form for creating/updating a custom license. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_licensemanager\form; + +use moodleform; +use tool_licensemanager\helper; +use tool_licensemanager\manager; + +defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); + +global $CFG; +require_once($CFG->libdir . '/formslib.php'); + +/** + * Form for creating/updating a custom license. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class edit_license extends moodleform { + + /** + * @var string the action form is taking. + */ + private $action; + + /** + * @var string license shortname if editing or empty string if creating license. + */ + private $licenseshortname; + + /** + * edit_license constructor. + * + * @param string $action the license_manager action to be taken by form. + * @param string $licenseshortname the shortname of the license to edit. + */ + public function __construct(string $action, string $licenseshortname) { + $this->action = $action; + $this->licenseshortname = $licenseshortname; + + if ($action == manager::ACTION_UPDATE && !empty($licenseshortname)) { + parent::__construct(helper::get_update_license_url($licenseshortname)); + } else { + parent::__construct(helper::get_create_license_url()); + } + } + + /** + * Form definition for creation and editing of licenses. + */ + public function definition() { + + $mform = $this->_form; + + $mform->addElement('text', 'shortname', get_string('shortname', 'tool_licensemanager')); + $mform->setType('shortname', PARAM_ALPHANUMEXT); + // Shortname is only editable when user is creating a license. + if ($this->action != manager::ACTION_CREATE) { + $mform->freeze('shortname'); + } else { + $mform->addRule('shortname', get_string('shortnamerequirederror', 'tool_licensemanager'), 'required'); + } + + $mform->addElement('text', 'fullname', get_string('fullname', 'tool_licensemanager')); + $mform->setType('fullname', PARAM_TEXT); + $mform->addRule('fullname', get_string('fullnamerequirederror', 'tool_licensemanager'), 'required'); + + $mform->addElement('text', 'source', get_string('source', 'tool_licensemanager')); + $mform->setType('source', PARAM_URL); + $mform->addHelpButton('source', 'source', 'tool_licensemanager'); + $mform->addRule('source', get_string('sourcerequirederror', 'tool_licensemanager'), 'required'); + + $mform->addElement('date_selector', 'version', get_string('version', 'tool_licensemanager'), get_string('from')); + $mform->addHelpButton('version', 'version', 'tool_licensemanager'); + + $this->add_action_buttons(); + } + + /** + * Validate form data and return errors (if any). + * + * @param array $data array of ("fieldname"=>value) of submitted data + * @param array $files array of uploaded files "element_name"=>tmp_file_path + * @return array of "element_name"=>"error_description" if there are errors, + * or an empty array if everything is OK (true allowed for backwards compatibility too). + */ + public function validation($data, $files) { + $errors = parent::validation($data, $files); + + if (array_key_exists('source', $data) && !filter_var($data['source'], FILTER_VALIDATE_URL)) { + $errors['source'] = get_string('invalidurl', 'tool_licensemanager'); + } + + if (array_key_exists('version', $data) && $data['version'] > time()) { + $errors['version'] = get_string('versioncannotbefuture', 'tool_licensemanager'); + } + + return $errors; + } +} diff --git a/admin/tool/licensemanager/classes/helper.php b/admin/tool/licensemanager/classes/helper.php new file mode 100644 index 00000000000..b71a9aac185 --- /dev/null +++ b/admin/tool/licensemanager/classes/helper.php @@ -0,0 +1,154 @@ +. + +/** + * License manager helper class. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_licensemanager; + +use moodle_url; + +defined('MOODLE_INTERNAL') || die(); + +/** + * License manager helper class. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class helper { + + /** + * Moodle relative path to the licenses manager. + */ + const MANAGER_PATH = '/admin/tool/licensemanager/index.php'; + + /** + * Get the URL for viewing the license manager interface. + * + * @return \moodle_url + */ + public static function get_licensemanager_url() : moodle_url { + global $CFG; + + $url = new moodle_url($CFG->wwwroot . self::MANAGER_PATH, + ['sesskey' => sesskey()]); + + return $url; + } + + /** + * Get the URL for endpoint enabling a license. + * + * @param string $licenseshortname the shortname of license to enable. + * + * @return \moodle_url + */ + public static function get_enable_license_url(string $licenseshortname) : moodle_url { + $url = new moodle_url(self::MANAGER_PATH, + ['action' => manager::ACTION_ENABLE, 'license' => $licenseshortname, 'sesskey' => sesskey()]); + + return $url; + } + + /** + * Get the URL for endpoint disabling a license. + * + * @param string $licenseshortname the shortname of license to disable. + * + * @return \moodle_url + */ + public static function get_disable_license_url(string $licenseshortname) : moodle_url { + $url = new moodle_url(self::MANAGER_PATH, + ['action' => manager::ACTION_DISABLE, 'license' => $licenseshortname, 'sesskey' => sesskey()]); + + return $url; + } + + /** + * Get the URL endpoint to create a new license. + * + * @return \moodle_url + */ + public static function get_create_license_url() : moodle_url { + $url = new moodle_url(self::MANAGER_PATH, + ['action' => manager::ACTION_CREATE, 'sesskey' => sesskey()]); + + return $url; + } + + /** + * Get the URL endpoint to update an existing license. + * + * @param string $licenseshortname the shortname of license to update. + * + * @return \moodle_url + */ + public static function get_update_license_url(string $licenseshortname) : moodle_url { + $url = new moodle_url(self::MANAGER_PATH, + ['action' => manager::ACTION_UPDATE, 'license' => $licenseshortname, 'sesskey' => sesskey()]); + + return $url; + } + + /** + * Get the URL endpoint to move a license up order. + * + * @param string $licenseshortname the shortname of license to move up. + * + * @return \moodle_url + */ + public static function get_moveup_license_url(string $licenseshortname) : moodle_url { + $url = new moodle_url(self::MANAGER_PATH, + ['action' => manager::ACTION_MOVE_UP, 'license' => $licenseshortname, 'sesskey' => sesskey()]); + + return $url; + } + + /** + * Get the URL endpoint to move a license down order. + * + * @param string $licenseshortname the shortname of license to move down. + * + * @return \moodle_url + */ + public static function get_movedown_license_url(string $licenseshortname) : moodle_url { + $url = new moodle_url(self::MANAGER_PATH, + ['action' => manager::ACTION_MOVE_DOWN, 'license' => $licenseshortname, 'sesskey' => sesskey()]); + + return $url; + } + + /** + * Convert a license version number string to a UNIX epoch. + * + * @param string $version + * + * @return int $epoch + */ + public static function convert_version_to_epoch(string $version) : int { + $date = substr($version, 0, 8); + $epoch = strtotime($date); + + return $epoch; + } +} diff --git a/admin/tool/licensemanager/classes/manager.php b/admin/tool/licensemanager/classes/manager.php new file mode 100644 index 00000000000..2f3ad2cee20 --- /dev/null +++ b/admin/tool/licensemanager/classes/manager.php @@ -0,0 +1,247 @@ +. + +/** + * License manager. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_licensemanager; + +use tool_licensemanager\form\edit_license; +use license_manager; +use stdClass; + +defined('MOODLE_INTERNAL') || die(); + +/** + * License manager, main controller for tool_licensemanager. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class manager { + + /** + * Action for creating a new custom license. + */ + const ACTION_CREATE = 'create'; + + /** + * Action for updating a custom license's details. + */ + const ACTION_UPDATE = 'update'; + + /** + * Action for deleting a custom license. + */ + const ACTION_DELETE = 'delete'; + + /** + * Action for disabling a custom license. + */ + const ACTION_DISABLE = 'disable'; + + /** + * Action for enabling a custom license. + */ + const ACTION_ENABLE = 'enable'; + + /** + * Action for displaying the license list view. + */ + const ACTION_VIEW_LICENSE_MANAGER = 'viewlicensemanager'; + + /** + * Action for moving a license up order. + */ + const ACTION_MOVE_UP = 'moveup'; + + /** + * Action for moving a license down order. + */ + const ACTION_MOVE_DOWN = 'movedown'; + + /** + * Entry point for internal license manager. + * + * @param string $action the api action to carry out. + * @param string|object $license the license object or shortname of license to carry action out on. + */ + public function execute(string $action, $license) : void { + + admin_externalpage_setup('licensemanager'); + + // Convert license to a string if it's a full license object. + if (is_object($license)) { + $license = $license->shortname; + } + + $viewmanager = true; + + switch ($action) { + case self::ACTION_DISABLE: + license_manager::disable($license); + break; + + case self::ACTION_ENABLE: + license_manager::enable($license); + break; + + case self::ACTION_DELETE: + license_manager::delete($license); + break; + + case self::ACTION_CREATE: + case self::ACTION_UPDATE: + $viewmanager = $this->edit($action, $license); + break; + + case self::ACTION_MOVE_UP: + case self::ACTION_MOVE_DOWN: + $this->change_license_order($action, $license); + break; + + case self::ACTION_VIEW_LICENSE_MANAGER: + default: + break; + } + if ($viewmanager) { + $this->view_license_manager(); + } + } + + /** + * Edit an existing license or create a new license. + * + * @param string $action the form action to carry out. + * @param string $licenseshortname the shortname of the license to edit. + * + * @return bool true if license editing complete, false otherwise. + */ + private function edit(string $action, string $licenseshortname) : bool { + + if ($action != self::ACTION_CREATE && $action != self::ACTION_UPDATE) { + throw new \coding_exception('license edit actions are limited to create and update'); + } + + $form = new form\edit_license($action, $licenseshortname); + + if ($form->is_cancelled()) { + return true; + } else if ($data = $form->get_data()) { + + $license = new stdClass(); + if ($action == self::ACTION_CREATE) { + // Check that license shortname isn't already in use. + if (!empty(license_manager::get_license_by_shortname($data->shortname))) { + print_error('duplicatelicenseshortname', 'tool_licensemanager', + helper::get_licensemanager_url(), + $data->shortname); + } + $license->shortname = $data->shortname; + } else { + if (empty(license_manager::get_license_by_shortname($licenseshortname))) { + print_error('licensenotfoundshortname', 'license', + helper::get_licensemanager_url(), + $licenseshortname); + } + $license->shortname = $licenseshortname; + } + $license->fullname = $data->fullname; + $license->source = $data->source; + // Legacy date format maintained to prevent breaking on upgrade. + $license->version = date('Ymd', $data->version) . '00'; + + license_manager::save($license); + + return true; + } else { + $this->view_license_editor($action, $licenseshortname, $form); + + return false; + } + } + + /** + * Change license order by moving up or down license order. + * + * @param string $direction which direction to move, up or down. + * @param string $licenseshortname the shortname of the license to move up or down order. + */ + private function change_license_order(string $direction, string $licenseshortname) : void { + + if (!empty($licenseshortname)) { + if ($direction == self::ACTION_MOVE_UP) { + license_manager::change_license_sortorder(license_manager::LICENSE_MOVE_UP, $licenseshortname); + } else if ($direction == self::ACTION_MOVE_DOWN) { + license_manager::change_license_sortorder(license_manager::LICENSE_MOVE_DOWN, $licenseshortname); + } + } + } + + /** + * View the license editor to create or edit a license. + * + * @param string $action + * @param string $licenseshortname the shortname of the license to create/edit. + * @param \tool_licensemanager\form\edit_license $form the form for submitting edit data. + */ + private function view_license_editor(string $action, string $licenseshortname, edit_license $form) : void { + global $PAGE; + + $renderer = $PAGE->get_renderer('tool_licensemanager'); + + if ($action == self::ACTION_UPDATE && $license = license_manager::get_license_by_shortname($licenseshortname)) { + $return = $renderer->render_edit_licence_headers($licenseshortname); + + $form->set_data(['shortname' => $license->shortname]); + $form->set_data(['fullname' => $license->fullname]); + $form->set_data(['source' => $license->source]); + $form->set_data(['version' => helper::convert_version_to_epoch($license->version)]); + + } else { + $return = $renderer->render_create_licence_headers(); + } + $return .= $form->render(); + $return .= $renderer->footer(); + + echo $return; + } + + /** + * View the license manager. + */ + private function view_license_manager() : void { + global $PAGE; + + $PAGE->requires->js_call_amd('tool_licensemanager/delete_license'); + + $renderer = $PAGE->get_renderer('tool_licensemanager'); + $html = $renderer->header(); + $html .= $renderer->heading(get_string('licensemanager', 'tool_licensemanager')); + + $table = new \tool_licensemanager\output\table(); + $html .= $renderer->render($table); + $html .= $renderer->footer(); + + echo $html; + } +} diff --git a/admin/tool/licensemanager/classes/output/renderer.php b/admin/tool/licensemanager/classes/output/renderer.php new file mode 100644 index 00000000000..19ac8d419a4 --- /dev/null +++ b/admin/tool/licensemanager/classes/output/renderer.php @@ -0,0 +1,96 @@ +. + +/** + * Renderer for 'tool_licensemanager' component. + * + * @package tool_licensemanager + * @copyright Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_licensemanager\output; + +defined('MOODLE_INTERNAL') || die(); + +use license_manager; +use plugin_renderer_base; +use tool_licensemanager\helper; + +/** + * Renderer class for 'tool_licensemanager' component. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class renderer extends plugin_renderer_base { + + /** + * Render the headers for create license form. + * + * @return string html fragment for display. + */ + public function render_create_licence_headers() : string { + + $this->page->navbar->add(get_string('createlicense', 'tool_licensemanager'), + helper::get_create_license_url()); + + $return = $this->header(); + $return .= $this->heading(get_string('createlicense', 'tool_licensemanager')); + + return $return; + } + + /** + * Render the headers for edit license form. + * + * @param string $licenseshortname the shortname of license to edit. + * + * @return string html fragment for display. + */ + public function render_edit_licence_headers(string $licenseshortname) : string { + + $this->page->navbar->add(get_string('editlicense', 'tool_licensemanager'), + helper::get_update_license_url($licenseshortname)); + + $return = $this->header(); + $return .= $this->heading(get_string('editlicense', 'tool_licensemanager')); + + return $return; + } + + /** + * Render the license manager table. + * + * @param \renderable $table the renderable. + * + * @return string HTML. + */ + public function render_table(\renderable $table) { + $licenses = license_manager::get_licenses(); + + // Add the create license button. + $html = $table->create_license_link(); + + // Add the table containing licenses for management. + $html .= $this->box_start('generalbox editorsui'); + $html .= $table->create_license_manager_table($licenses, $this); + $html .= $this->box_end(); + + return $html; + } +} diff --git a/admin/tool/licensemanager/classes/output/table.php b/admin/tool/licensemanager/classes/output/table.php new file mode 100644 index 00000000000..ff01ae9d23c --- /dev/null +++ b/admin/tool/licensemanager/classes/output/table.php @@ -0,0 +1,186 @@ +. + +/** + * Renderable for display of license manager table. + * + * @package tool_licensemanager + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_licensemanager\output; + +use html_table; +use html_table_cell; +use html_table_row; +use html_writer; +use license_manager; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Renderable for display of license manager table. + * + * @package tool_licensemanager + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class table implements \renderable { + + /** + * 'Create License' link. + * + * @return string HTML string. + */ + public function create_license_link() { + $link = html_writer::link(\tool_licensemanager\helper::get_create_license_url(), + get_string('createlicensebuttontext', 'tool_licensemanager'), + ['class' => 'btn btn-secondary mb-3']); + + return $link; + } + + /** + * Create the HTML table for license management. + * + * @param array $licenses + * @param \renderer_base $output + * + * @return string HTML for license manager table. + */ + public function create_license_manager_table(array $licenses, \renderer_base $output) { + $table = new html_table(); + $table->head = [ + get_string('enable'), + get_string('license', 'tool_licensemanager'), + get_string('version'), + get_string('order'), + get_string('edit'), + get_string('delete'), + ]; + $table->colclasses = [ + 'text-center', + 'text-left', + 'text-left', + 'text-center', + 'text-center', + 'text-center', + ]; + $table->id = 'manage-licenses'; + $table->attributes['class'] = 'admintable generaltable'; + $table->data = []; + + $rownumber = 0; + $rowcount = count($licenses); + + foreach ($licenses as $key => $value) { + $canmoveup = $rownumber > 0; + $canmovedown = $rownumber < $rowcount - 1; + $table->data[] = $this->get_license_table_row_data($value, $canmoveup, $canmovedown, $output); + $rownumber++; + } + + $html = html_writer::table($table); + + return $html; + } + + /** + * Get table row data for a license. + * + * @param object $license the license to populate row data for. + * @param bool $canmoveup can this row move up. + * @param bool $canmovedown can this row move down. + * @param \renderer_base $output the renderer + * + * @return \html_table_row of columns values for row. + */ + protected function get_license_table_row_data($license, bool $canmoveup, bool $canmovedown, \renderer_base $output) { + global $CFG; + + $summary = $license->fullname . ' ('. $license->shortname . ')'; + if (!empty($license->source)) { + $summary .= html_writer::empty_tag('br'); + $summary .= html_writer::link($license->source, $license->source, ['target' => '_blank']); + } + $summarycell = new html_table_cell($summary); + $summarycell->attributes['class'] = 'license-summary'; + $versioncell = new html_table_cell($license->version); + $versioncell->attributes['class'] = 'license-version'; + + if ($license->shortname == $CFG->sitedefaultlicense) { + $hideshow = $output->pix_icon('t/locked', get_string('sitedefaultlicenselock', 'tool_licensemanager')); + } else { + if ($license->enabled == license_manager::LICENSE_ENABLED) { + $hideshow = html_writer::link(\tool_licensemanager\helper::get_disable_license_url($license->shortname), + $output->pix_icon('t/hide', get_string('disablelicensename', 'tool_licensemanager', $license->fullname))); + } else { + $hideshow = html_writer::link(\tool_licensemanager\helper::get_enable_license_url($license->shortname), + $output->pix_icon('t/show', get_string('enablelicensename', 'tool_licensemanager', $license->fullname))); + } + + if ($license->custom == license_manager::CUSTOM_LICENSE) { + // Link url is added by the JS `delete_license` modal used for confirmation of deletion, to avoid + // link being usable before JavaScript loads on page. + $deletelicense = html_writer::link('#', $output->pix_icon('i/trash', + get_string('deletelicensename', 'tool_licensemanager', $license->fullname)), + ['class' => 'delete-license', 'data-license' => $license->shortname]); + } else { + $deletelicense = ''; + } + } + $hideshowcell = new html_table_cell($hideshow); + $hideshowcell->attributes['class'] = 'license-status'; + + if ($license->custom == license_manager::CUSTOM_LICENSE) { + $editlicense = html_writer::link(\tool_licensemanager\helper::get_update_license_url($license->shortname), + $output->pix_icon('t/editinline', get_string('editlicensename', 'tool_licensemanager', $license->fullname)), + ['class' => 'edit-license']); + } else { + $editlicense = ''; + } + $editlicensecell = new html_table_cell($editlicense); + $editlicensecell->attributes['class'] = 'edit-license'; + + $spacer = $output->pix_icon('spacer', '', 'moodle', ['class' => 'iconsmall']); + $updown = ''; + if ($canmoveup) { + $updown .= html_writer::link(\tool_licensemanager\helper::get_moveup_license_url($license->shortname), + $output->pix_icon('t/up', get_string('movelicenseupname', 'tool_licensemanager', $license->fullname), + 'moodle', ['class' => 'iconsmall']), + ['class' => 'move-up']) . ''; + } else { + $updown .= $spacer; + } + + if ($canmovedown) { + $updown .= ' '.html_writer::link(\tool_licensemanager\helper::get_movedown_license_url($license->shortname), + $output->pix_icon('t/down', get_string('movelicensedownname', 'tool_licensemanager', $license->fullname), + 'moodle', ['class' => 'iconsmall']), + ['class' => 'move-down']); + } else { + $updown .= $spacer; + } + $updowncell = new html_table_cell($updown); + $updowncell->attributes['class'] = 'license-order'; + + $row = new html_table_row([$hideshowcell, $summarycell, $versioncell, $updowncell, $editlicensecell, $deletelicense]); + $row->attributes['data-license'] = $license->shortname; + $row->attributes['class'] = strtolower(get_string('license', 'tool_licensemanager')); + + return $row; + } +} diff --git a/admin/tool/licensemanager/classes/privacy/provider.php b/admin/tool/licensemanager/classes/privacy/provider.php new file mode 100644 index 00000000000..b4eb6115dac --- /dev/null +++ b/admin/tool/licensemanager/classes/privacy/provider.php @@ -0,0 +1,47 @@ +. + +/** + * Privacy Subsystem implementation for tool_licensemanager implementing null_provider. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_licensemanager\privacy; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Privacy Subsystem implementation for tool_licensemanager implementing null_provider. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class provider implements \core_privacy\local\metadata\null_provider { + + /** + * Get the language string identifier with the component's language + * file to explain why this plugin stores no data. + * + * @return string + */ + public static function get_reason() : string { + return 'privacy:metadata'; + } +} diff --git a/admin/licenses.php b/admin/tool/licensemanager/index.php similarity index 55% rename from admin/licenses.php rename to admin/tool/licensemanager/index.php index 820e7758a69..123dd9db6e0 100644 --- a/admin/licenses.php +++ b/admin/tool/licensemanager/index.php @@ -1,5 +1,4 @@ . /** - * Allows admin to configure licenses. + * License manager page. + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -require_once('../config.php'); -require_once($CFG->libdir.'/adminlib.php'); -require_once($CFG->libdir.'/licenselib.php'); +require_once('../../../config.php'); +require_once($CFG->libdir . '/adminlib.php'); +require_once($CFG->libdir . '/licenselib.php'); require_admin(); -$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=managelicenses"; +$returnurl = \tool_licensemanager\helper::get_licensemanager_url(); $action = optional_param('action', '', PARAM_ALPHANUMEXT); $license = optional_param('license', '', PARAM_SAFEDIR); -//////////////////////////////////////////////////////////////////////////////// -// process actions - if (!confirm_sesskey()) { redirect($returnurl); } -$return = true; -switch ($action) { - case 'disable': - license_manager::disable($license); - break; +// Route via the manager. +$licensemanager = new \tool_licensemanager\manager(); +$PAGE->set_context(context_system::instance()); +$PAGE->set_url(\tool_licensemanager\helper::get_licensemanager_url()); +$PAGE->set_title(get_string('licensemanager', 'tool_licensemanager')); - case 'enable': - license_manager::enable($license); - break; - - default: - break; -} - -if ($return) { - redirect ($returnurl); -} +$licensemanager->execute($action, $license); diff --git a/admin/tool/licensemanager/lang/en/tool_licensemanager.php b/admin/tool/licensemanager/lang/en/tool_licensemanager.php new file mode 100644 index 00000000000..97e372a21b8 --- /dev/null +++ b/admin/tool/licensemanager/lang/en/tool_licensemanager.php @@ -0,0 +1,52 @@ +. + +/** + * Strings for component 'tool_licensemanager', language 'en' + * + * @package tool_licensemanager + * @copyright 2019 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +$string['pluginname'] = 'License manager'; +$string['createlicense'] = 'Create custom licence'; +$string['createlicensebuttontext'] = 'Create licence'; +$string['deletelicense'] = 'Delete licence'; +$string['deletelicenseconfirmmessage'] = 'Are you sure you want to delete this licence?'; +$string['deletelicensename'] = 'Delete license \'{$a}\''; +$string['disablelicensename'] = 'Disable licence \'{$a}\''; +$string['duplicatelicenseshortname'] = 'Licence shortname must be unique, duplicate value found.'; +$string['editlicense'] = 'Edit licence'; +$string['editlicensename'] = 'Edit licence \'{$a}\''; +$string['enablelicensename'] = 'Enable licence \'{$a}\''; +$string['fullname'] = 'Licence full name'; +$string['fullnamerequirederror'] = 'You must enter a full name for the licence.'; +$string['invalidurl'] = 'Invalid source URL'; +$string['license'] = 'Licence'; +$string['licensemanager'] = 'Licence manager'; +$string['movelicensedownname'] = 'Move \'{$a}\' license down order'; +$string['movelicenseupname'] = 'Move \'{$a}\' license up order'; +$string['privacy:metadata'] = 'The tool_licensemanager plugin stores no personal data.'; +$string['shortname'] = 'Licence short name'; +$string['sitedefaultlicenselock'] = 'This is the site default license. It cannot be disabled.'; +$string['shortnamerequirederror'] = 'You must enter a short name for the licence.'; +$string['source'] = 'Licence source'; +$string['source_help'] = 'The URL (with http:// or https:// prefix) where the licence terms and conditions can be found.'; +$string['sourcerequirederror'] = 'You must enter a valid URL for licence source.'; +$string['version'] = 'Licence version'; +$string['versioncannotbefuture'] = 'Licence version cannot be set to a future date.'; +$string['version_help'] = 'Publication date of the licence version being utilised.'; + diff --git a/admin/tool/licensemanager/settings.php b/admin/tool/licensemanager/settings.php new file mode 100644 index 00000000000..ffb61e71a84 --- /dev/null +++ b/admin/tool/licensemanager/settings.php @@ -0,0 +1,33 @@ +. + +/** + * Settings page. + * + * @package tool_licensemanager + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die; + +if ($hassiteconfig) { + $temp = new admin_externalpage('licensemanager', + get_string('licensemanager', 'tool_licensemanager'), + \tool_licensemanager\helper::get_licensemanager_url()); + + $ADMIN->add('license', $temp); +} diff --git a/admin/tool/licensemanager/tests/behat/delete_license.feature b/admin/tool/licensemanager/tests/behat/delete_license.feature new file mode 100644 index 00000000000..f5405ecfa6f --- /dev/null +++ b/admin/tool/licensemanager/tests/behat/delete_license.feature @@ -0,0 +1,29 @@ +@tool @tool_licensemanager +Feature: Delete custom licenses + In order to manage custom licenses + As an admin + I need to be able to delete custom licenses but not standard Moodle licenses + + @javascript + Scenario: I can delete a custom license + Given I log in as "admin" + And I navigate to "Licence > Licence manager" in site administration + And I click on "Create licence" "link" + And I set the following fields to these values: + | shortname | MIT | + | fullname | MIT Licence | + | source | https://opensource.org/licenses/MIT | + | version[day] | 1 | + | version[month] | March | + | version[year] | 2019 | + And I press "Save changes" + And I click on "Delete" "icon" in the "MIT" "table_row" + And I click on "Save changes" "button" in the "Delete licence" "dialogue" + Then I should not see "MIT Licence" in the "manage-licenses" "table" + And I log out + + Scenario: I cannot delete a standard Moodle license + Given I log in as "admin" + And I navigate to "Licence > Licence manager" in site administration + Then I should see "Licence not specified" in the "unknown" "table_row" + And I should not see "Delete" in the "unknown" "table_row" diff --git a/admin/tool/licensemanager/tests/behat/edit_license.feature b/admin/tool/licensemanager/tests/behat/edit_license.feature new file mode 100644 index 00000000000..d8dbfb347ae --- /dev/null +++ b/admin/tool/licensemanager/tests/behat/edit_license.feature @@ -0,0 +1,83 @@ +@tool @tool_licensemanager +Feature: Custom licences + In order to use custom licences + As an admin + I need to be able to add custom licences + + Scenario: I am able to create custom licences + Given I log in as "admin" + And I navigate to "Licence > Licence manager" in site administration + And I click on "Create licence" "link" + And I set the following fields to these values: + | shortname | MIT | + | fullname | MIT Licence | + | source | https://opensource.org/licenses/MIT | + | version[day] | 1 | + | version[month] | January | + | version[year] | 2020 | + And I press "Save changes" + Then I should see "Licence manager" + And I should see "MIT Licence" in the "MIT" "table_row" + And I should see "https://opensource.org/licenses/MIT" in the "MIT" "table_row" + And I log out + + Scenario: I am only be able to make custom license with a valid url source (including scheme). + Given I log in as "admin" + And I navigate to "Licence > Licence manager" in site administration + And I click on "Create licence" "link" + And I set the following fields to these values: + | shortname | MIT | + | fullname | MIT Licence | + | source | opensource.org/licenses/MIT | + | version[day] | 1 | + | version[month] | January | + | version[year] | 2020 | + And I press "Save changes" + Then I should see "Invalid source URL" + And I set the following fields to these values: + | source | mailto:tomdickman@catalyst-au.net | + And I press "Save changes" + Then I should see "Invalid source URL" + And I set the following fields to these values: + | source | https://opensource.org/licenses/MIT | + And I press "Save changes" + Then I should see "Licence manager" + And I should see "MIT Licence" in the "MIT" "table_row" + And I should see "https://opensource.org/licenses/MIT" in the "MIT" "table_row" + And I log out + + Scenario: Custom license version format must be YYYYMMDD00 + Given I log in as "admin" + And I navigate to "Licence > Licence manager" in site administration + And I click on "Create licence" "link" + And I set the following fields to these values: + | shortname | MIT | + | fullname | MIT Licence | + | source | https://opensource.org/licenses/MIT | + | version[day] | 1 | + | version[month] | March | + | version[year] | 2019 | + And I press "Save changes" + Then I should see "Licence manager" + And I should see "2019030100" in the "MIT" "table_row" + And I log out + + @javascript + Scenario: Custom license short name should not be editable after first creation + Given I log in as "admin" + And I navigate to "Licence > Licence manager" in site administration + And I click on "Create licence" "link" + And I set the following fields to these values: + | shortname | MIT | + | fullname | MIT Licence | + | source | https://opensource.org/licenses/MIT | + | version[day] | 1 | + | version[month] | March | + | version[year] | 2019 | + And I press "Save changes" + And I should see "Licence manager" + And I should see "MIT Licence" in the "MIT" "table_row" + And I click on "Edit" "icon" in the "MIT" "table_row" + Then I should see "Edit licence" + And the "shortname" "field" should be disabled + And I log out diff --git a/admin/tool/licensemanager/tests/behat/license_manager.feature b/admin/tool/licensemanager/tests/behat/license_manager.feature new file mode 100644 index 00000000000..eae3cc19086 --- /dev/null +++ b/admin/tool/licensemanager/tests/behat/license_manager.feature @@ -0,0 +1,38 @@ +@tool @tool_licensemanager +Feature: License manager + In order to manage licenses + As an admin + I need to be able to view and alter licence preferences in the license manager. + + Scenario: I should be able to see the default Moodle licences. + Given I log in as "admin" + When I navigate to "Licence > Licence manager" in site administration + Then I should see "Licence not specified" in the "unknown" "table_row" + And I should see "All rights reserved" in the "allrightsreserved" "table_row" + And I should see "Public domain" in the "public" "table_row" + And I should see "Creative Commons" in the "cc" "table_row" + And I should see "Creative Commons - NoDerivs" in the "cc-nd" "table_row" + And I should see "Creative Commons - No Commercial NoDerivs" in the "cc-nc-nd" "table_row" + And I should see "Creative Commons - No Commercial" in the "cc-nc" "table_row" + And I should see "Creative Commons - No Commercial ShareAlike" in the "cc-nc-sa" "table_row" + And I should see "Creative Commons - ShareAlike" in the "cc-sa" "table_row" + And I log out + + @javascript + Scenario: I should be able to enable and disable licenses + Given I log in as "admin" + And I navigate to "Licence > Licence settings" in site administration + When I set the field "Default site licence" to "Public domain" + And I press "Save changes" + And I navigate to "Licence > Licence manager" in site administration + Then "Default" "icon" should exist in the "public" "table_row" + And "Enable" "icon" should not exist in the "public" "table_row" + And "Default" "icon" should not exist in the "cc" "table_row" + When I navigate to "Licence > Licence settings" in site administration + And I set the field "Default site licence" to "Creative Commons" + And I press "Save changes" + And I navigate to "Licence > Licence manager" in site administration + Then "Default" "icon" should exist in the "cc" "table_row" + And "Enable" "icon" should not exist in the "cc" "table_row" + And "Default" "icon" should not exist in the "public" "table_row" + And I log out diff --git a/admin/tool/licensemanager/tests/helper_test.php b/admin/tool/licensemanager/tests/helper_test.php new file mode 100644 index 00000000000..14c34c6a137 --- /dev/null +++ b/admin/tool/licensemanager/tests/helper_test.php @@ -0,0 +1,44 @@ +. + +/** + * Tests for tool_licensemanager helper class. + * + * @package tool_licensemanager + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Tests for tool_licensemanager helper class. + * + * @package tool_licensemanager + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group tool_licensemanager + */ +class helper_test extends advanced_testcase { + + public function test_convert_version_to_epoch() { + + $version = '2020010100'; + $expected = strtotime(20200101); + + $this->assertEquals($expected, \tool_licensemanager\helper::convert_version_to_epoch($version)); + } +} diff --git a/admin/tool/licensemanager/tests/manager_test.php b/admin/tool/licensemanager/tests/manager_test.php new file mode 100644 index 00000000000..e86cf68d633 --- /dev/null +++ b/admin/tool/licensemanager/tests/manager_test.php @@ -0,0 +1,199 @@ +. + +/** + * Tests for tool_licensemanager manager class. + * + * @package tool_licensemanager + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->libdir . '/formslib.php'); +require_once($CFG->libdir . '/licenselib.php'); + +/** + * Tests for tool_licensemanager manager class. + * + * @package tool_licensemanager + * @copyright 2020 Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @group tool_licensemanager + */ +class manager_test extends advanced_testcase { + + /** + * Test editing a license. + */ + public function test_edit_existing_license() { + $this->resetAfterTest(); + + // Create initial custom license to edit. + $testlicense = new stdClass(); + $testlicense->shortname = 'my-lic'; + $testlicense->fullname = 'My License'; + $testlicense->source = 'https://fakeurl.net'; + $testlicense->version = date('Ymd', time()) . '00'; + $testlicense->custom = license_manager::CUSTOM_LICENSE; + + license_manager::save($testlicense); + license_manager::enable($testlicense->shortname); + + $manager = new \tool_licensemanager\manager(); + + // Attempt to submit form data with altered details. + $formdata = [ + 'shortname' => 'new-value', + 'fullname' => 'New License Name', + 'source' => 'https://updatedfakeurl.net', + 'version' => time() + ]; + + // Attempt to submit form data with an altered shortname. + \tool_licensemanager\form\edit_license::mock_submit($formdata); + + // We're testing a private method, so we need to setup reflector magic. + $method = new ReflectionMethod('\tool_licensemanager\manager', 'edit'); + $method->setAccessible(true); // Allow accessing of private method. + $method->invoke($manager, \tool_licensemanager\manager::ACTION_UPDATE, $testlicense->shortname); + + // Should not create a new license when updating an existing license. + $this->assertEmpty(license_manager::get_license_by_shortname($formdata['shortname'])); + + $actual = license_manager::get_license_by_shortname('my-lic'); + // Should not be able to update the shortname of the license. + $this->assertNotSame($formdata['shortname'], $actual->shortname); + // Should be able to update other details of the license. + $this->assertSame($formdata['fullname'], $actual->fullname); + $this->assertSame($formdata['source'], $actual->source); + $this->assertSame(date('Ymd', $formdata['version']) . '00', $actual->version); + } + + public function test_edit_license_not_exists() { + $manager = new \tool_licensemanager\manager(); + + // We're testing a private method, so we need to setup reflector magic. + $method = new ReflectionMethod('\tool_licensemanager\manager', 'edit'); + $method->setAccessible(true); // Allow accessing of private method. + + // Attempt to update a license that doesn't exist. + $formdata = [ + 'shortname' => 'new-value', + 'fullname' => 'New License Name', + 'source' => 'https://updatedfakeurl.net', + 'version' => time() + ]; + \tool_licensemanager\form\edit_license::mock_submit($formdata); + + // Should not be able to update a license with a shortname that doesn't exist. + $this->expectException('moodle_exception'); + $method->invoke($manager, \tool_licensemanager\manager::ACTION_UPDATE, $formdata['shortname']); + } + + public function test_edit_license_no_shortname() { + $manager = new \tool_licensemanager\manager(); + + // We're testing a private method, so we need to setup reflector magic. + $method = new ReflectionMethod('\tool_licensemanager\manager', 'edit'); + $method->setAccessible(true); // Allow accessing of private method. + + // Attempt to update a license without passing license shortname. + $formdata = [ + 'fullname' => 'New License Name', + 'source' => 'https://updatedfakeurl.net', + 'version' => time() + ]; + \tool_licensemanager\form\edit_license::mock_submit($formdata); + + // Should not be able to update empty license shortname. + $this->expectException('moodle_exception'); + $method->invoke($manager, \tool_licensemanager\manager::ACTION_UPDATE, ''); + } + + /** + * Test creating a new license. + */ + public function test_edit_create_license() { + $this->resetAfterTest(); + + $licensecount = count(license_manager::get_licenses()); + + $manager = new \tool_licensemanager\manager(); + + $formdata = [ + 'shortname' => 'new-value', + 'fullname' => 'My License', + 'source' => 'https://fakeurl.net', + 'version' => time() + ]; + + // Attempt to submit form data for a new license. + \tool_licensemanager\form\edit_license::mock_submit($formdata); + + // We're testing a private method, so we need to setup reflector magic. + $method = new ReflectionMethod('\tool_licensemanager\manager', 'edit'); + $method->setAccessible(true); // Allow accessing of private method. + $method->invoke($manager, \tool_licensemanager\manager::ACTION_CREATE, $formdata['shortname']); + + // Should create a new license in database. + $this->assertCount($licensecount + 1, license_manager::get_licenses()); + $actual = license_manager::get_license_by_shortname($formdata['shortname']); + $this->assertSame($formdata['shortname'], $actual->shortname); + $this->assertSame($formdata['fullname'], $actual->fullname); + $this->assertSame($formdata['source'], $actual->source); + $this->assertSame(date('Ymd', $formdata['version']) . '00', $actual->version); + + // Attempt to submit form data for a duplicate license. + \tool_licensemanager\form\edit_license::mock_submit($formdata); + + // Should not be able to create duplicate licenses. + $this->expectException('moodle_exception'); + $method->invoke($manager, \tool_licensemanager\manager::ACTION_CREATE, $formdata['shortname']); + } + + /** + * Test changing the order of licenses. + */ + public function test_change_license_order() { + $this->resetAfterTest(); + + $licenseorder = array_keys(license_manager::get_licenses()); + $initialposition = array_search('cc-nc', $licenseorder); + + $manager = new tool_licensemanager\manager(); + + // We're testing a private method, so we need to setup reflector magic. + $method = new ReflectionMethod('\tool_licensemanager\manager', 'change_license_order'); + $method->setAccessible(true); // Allow accessing of private method. + $method->invoke($manager, \tool_licensemanager\manager::ACTION_MOVE_UP, 'cc-nc'); + + $licenseorder = array_keys(license_manager::get_licenses()); + $newposition = array_search('cc-nc', $licenseorder); + + $this->assertLessThan($initialposition, $newposition); + + $initialposition = array_search('allrightsreserved', $licenseorder); + $method->invoke($manager, \tool_licensemanager\manager::ACTION_MOVE_DOWN, 'allrightsreserved'); + $licenseorder = array_keys(license_manager::get_licenses()); + $newposition = array_search('cc-nc', $licenseorder); + + $this->assertGreaterThan($initialposition, $newposition); + } + +} diff --git a/admin/tool/licensemanager/version.php b/admin/tool/licensemanager/version.php new file mode 100644 index 00000000000..faf9c51949d --- /dev/null +++ b/admin/tool/licensemanager/version.php @@ -0,0 +1,31 @@ +. + +/** + * Version details for component 'tool_licensemanager'. + * + * @package tool_licensemanager + * @copyright Tom Dickman + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->version = 2020050600; +$plugin->requires = 2020050200; // Requires this Moodle version. +$plugin->component = 'tool_licensemanager'; + +$plugin->maturity = MATURITY_STABLE; diff --git a/lang/en/admin.php b/lang/en/admin.php index 08ccfaad6dc..19c40d75fd5 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -81,7 +81,6 @@ $string['autolang'] = 'Language autodetect'; $string['autologinguests'] = 'Auto-login guests'; $string['searchareas'] = 'Search areas'; $string['availableto'] = 'Available to'; -$string['availablelicenses'] = 'Available licences'; $string['backgroundcolour'] = 'Transparent colour'; $string['backups'] = 'Backups'; $string['backup_shortname'] = 'Use course name in backup filename'; @@ -763,7 +762,6 @@ $string['managecustomfields'] = 'Manage custom field types'; $string['manageformats'] = 'Manage course formats'; $string['manageformatsgotosettings'] = 'Default format can be changed in {$a}'; $string['managelang'] = 'Manage'; -$string['managelicenses'] = 'Manage licences'; $string['manageqbehaviours'] = 'Manage question behaviours'; $string['manageqtypes'] = 'Manage question types'; $string['maturity50'] = 'Alpha'; @@ -1046,6 +1044,8 @@ $string['registration_help'] = 'By registering: $string['registrationwarning'] = 'Your site is not yet registered.'; $string['registrationwarningcontactadmin'] = 'Your site is not yet registered. Please notify your administrator.'; $string['releasenoteslink'] = 'For information about this version of Moodle, please see the online Release Notes'; +$string['rememberuserlicensepref'] = 'Remember user licence preference'; +$string['rememberuserlicensepref_help'] = 'If enabled, the last licence selected by the user is preselected when uploading a file in the file picker. Otherwise, the default site licence is preselected.'; $string['rememberusername'] = 'Remember username'; $string['rememberusername_desc'] = 'Enable if you want to store permanent cookies with usernames during user login. Permanent cookies may be considered a privacy issue if used without consent.'; $string['reportsmanage'] = 'Manage reports'; @@ -1461,3 +1461,7 @@ $string['registermoodleorgli2'] = 'Statistics about your site will be added to t $string['registerwithmoodleorg'] = 'Register your site'; $string['configrequestcategoryselection'] = 'Allow the selection of a category when requesting a course.'; $string['requestcategoryselection'] = 'Enable category selection'; + +// Deprecated since Moodle 3.9. +$string['availablelicenses'] = 'Available licences'; +$string['managelicenses'] = 'Manage licences'; diff --git a/lang/en/cache.php b/lang/en/cache.php index cb595171bf7..30dcdc9e3dc 100644 --- a/lang/en/cache.php +++ b/lang/en/cache.php @@ -60,6 +60,7 @@ $string['cachedef_groupdata'] = 'Course group information'; $string['cachedef_h5p_content_type_translations'] = 'H5P content-type libraries translations'; $string['cachedef_htmlpurifier'] = 'HTML Purifier - cleaned content'; $string['cachedef_langmenu'] = 'List of available languages'; +$string['cachedef_license'] = 'List of licences'; $string['cachedef_message_time_last_message_between_users'] = 'Time created for most recent message in a conversation'; $string['cachedef_modelfirstanalyses'] = 'First analysis by model and analysable'; $string['cachedef_locking'] = 'Locking'; diff --git a/lang/en/deprecated.txt b/lang/en/deprecated.txt index 280b3bd99fb..e8608e744cf 100644 --- a/lang/en/deprecated.txt +++ b/lang/en/deprecated.txt @@ -141,3 +141,5 @@ europe/belfast,core_timezones pacific/ponape,core_timezones pacific/truk,core_timezones pacific/yap,core_timezones +availablelicenses,core_admin +managelicenses,core_admin diff --git a/lang/en/license.php b/lang/en/license.php index 1c40f7800bd..f33e68718bd 100644 --- a/lang/en/license.php +++ b/lang/en/license.php @@ -22,6 +22,7 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +// Core licenses. $string['allrightsreserved'] = 'All rights reserved'; $string['cc'] = 'Creative Commons'; $string['cc-nc'] = 'Creative Commons - No Commercial'; @@ -30,4 +31,10 @@ $string['cc-nc-sa'] = 'Creative Commons - No Commercial ShareAlike'; $string['cc-nd'] = 'Creative Commons - NoDerivs'; $string['cc-sa'] = 'Creative Commons - ShareAlike'; $string['public'] = 'Public domain'; -$string['unknown'] = 'Other'; +$string['unknown'] = 'Licence not specified'; + +// Error messages. +$string['cannotdeletecore'] = 'Cannot delete a standard licence'; +$string['cannotdeletelicenseinuse'] = 'Cannot delete a licence which is currently assigned to one or more files'; +$string['licensenotfoundshortname'] = 'Cannot find a licence with the short name \'{$a}\''; +$string['missinglicensesortorder'] = 'Cannot set licence order, one or more installed licences is missing from new order'; diff --git a/lib/adminlib.php b/lib/adminlib.php index b75e4e19c14..1541db2f81a 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -7243,40 +7243,72 @@ class admin_setting_manageantiviruses extends admin_setting { * Special class for license administration. * * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @deprecated since Moodle 3.9 MDL-45184. Please use \tool_licensemanager\manager instead. + * @todo MDL-45184 This class will be deleted in Moodle 4.3. */ class admin_setting_managelicenses extends admin_setting { /** - * Calls parent::__construct with specific arguments + * @deprecated since Moodle 3.9 MDL-45184. Please use \tool_licensemanager\manager instead. + * @todo MDL-45184 This class will be deleted in Moodle 4.3 */ public function __construct() { - $this->nosave = true; - parent::__construct('licensesui', get_string('licensesettings', 'admin'), '', ''); + global $ADMIN; + + debugging('admin_setting_managelicenses class is deprecated. Please use \tool_licensemanager\manager instead.', + DEBUG_DEVELOPER); + + // Replace admin setting load with new external page load for tool_licensemanager, if not loaded already. + if (!is_null($ADMIN->locate('licensemanager'))) { + $temp = new admin_externalpage('licensemanager', + get_string('licensemanager', 'tool_licensemanager'), + \tool_licensemanager\helper::get_licensemanager_url()); + + $ADMIN->add('license', $temp); + } } /** * Always returns true, does nothing * + * @deprecated since Moodle 3.9 MDL-45184. + * @todo MDL-45184 This method will be deleted in Moodle 4.3 + * * @return true */ public function get_setting() { + debugging('admin_setting_managelicenses class is deprecated. Please use \tool_licensemanager\manager instead.', + DEBUG_DEVELOPER); + return true; } /** * Always returns true, does nothing * + * @deprecated since Moodle 3.9 MDL-45184. + * @todo MDL-45184 This method will be deleted in Moodle 4.3 + * * @return true */ public function get_defaultsetting() { + debugging('admin_setting_managelicenses class is deprecated. Please use \tool_licensemanager\manager instead.', + DEBUG_DEVELOPER); + return true; } /** * Always returns '', does not write anything * + * @deprecated since Moodle 3.9 MDL-45184. + * @todo MDL-45184 This method will be deleted in Moodle 4.3 + * * @return string Always returns '' */ public function write_setting($data) { + debugging('admin_setting_managelicenses class is deprecated. Please use \tool_licensemanager\manager instead.', + DEBUG_DEVELOPER); + // do not write any setting return ''; } @@ -7284,53 +7316,18 @@ class admin_setting_managelicenses extends admin_setting { /** * Builds the XHTML to display the control * + * @deprecated since Moodle 3.9 MDL-45184. Please use \tool_licensemanager\manager instead. + * @todo MDL-45184 This method will be deleted in Moodle 4.3 + * * @param string $data Unused * @param string $query * @return string */ public function output_html($data, $query='') { - global $CFG, $OUTPUT; - require_once($CFG->libdir . '/licenselib.php'); - $url = "licenses.php?sesskey=" . sesskey(); + debugging('admin_setting_managelicenses class is deprecated. Please use \tool_licensemanager\manager instead.', + DEBUG_DEVELOPER); - // display strings - $txt = get_strings(array('administration', 'settings', 'name', 'enable', 'disable', 'none')); - $licenses = license_manager::get_licenses(); - - $return = $OUTPUT->heading(get_string('availablelicenses', 'admin'), 3, 'main', true); - - $return .= $OUTPUT->box_start('generalbox editorsui'); - - $table = new html_table(); - $table->head = array($txt->name, $txt->enable); - $table->colclasses = array('leftalign', 'centeralign'); - $table->id = 'availablelicenses'; - $table->attributes['class'] = 'admintable generaltable'; - $table->data = array(); - - foreach ($licenses as $value) { - $displayname = html_writer::link($value->source, get_string($value->shortname, 'license'), array('target'=>'_blank')); - - if ($value->enabled == 1) { - $hideshow = html_writer::link($url.'&action=disable&license='.$value->shortname, - $OUTPUT->pix_icon('t/hide', get_string('disable'))); - } else { - $hideshow = html_writer::link($url.'&action=enable&license='.$value->shortname, - $OUTPUT->pix_icon('t/show', get_string('enable'))); - } - - if ($value->shortname == $CFG->sitedefaultlicense) { - $displayname .= ' '.$OUTPUT->pix_icon('t/locked', get_string('default')); - $hideshow = ''; - } - - $enabled = true; - - $table->data[] =array($displayname, $hideshow); - } - $return .= html_writer::table($table); - $return .= $OUTPUT->box_end(); - return highlight($query, $return); + redirect(\tool_licensemanager\helper::get_licensemanager_url()); } } diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index ba448c94896..0d8d832e68b 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -1998,10 +1998,11 @@ class core_plugin_manager { 'tool' => array( 'analytics', 'availabilityconditions', 'behat', 'capability', 'cohortroles', 'customlang', - 'dataprivacy', 'dbtransfer', 'filetypes', 'generator', 'health', 'httpsreplace', 'innodb', 'installaddon', - 'langimport', 'log', 'lp', 'lpimportcsv', 'lpmigrate', 'messageinbound', 'mobile', 'multilangupgrade', - 'monitor', 'oauth2', 'phpunit', 'policy', 'profiling', 'recyclebin', 'replace', 'spamcleaner', 'task', - 'templatelibrary', 'uploadcourse', 'uploaduser', 'unsuproles', 'usertours', 'xmldb' + 'dataprivacy', 'dbtransfer', 'filetypes', 'generator', 'health', 'httpsreplace', 'innodb', + 'installaddon', 'langimport', 'licensemanager', 'log', 'lp', 'lpimportcsv', 'lpmigrate', 'messageinbound', + 'mobile', 'multilangupgrade', 'monitor', 'oauth2', 'phpunit', 'policy', 'profiling', 'recyclebin', + 'replace', 'spamcleaner', 'task', 'templatelibrary', 'uploadcourse', 'uploaduser', 'unsuproles', + 'usertours', 'xmldb' ), 'webservice' => array( diff --git a/lib/db/caches.php b/lib/db/caches.php index a5bd37e418e..9cfc72d2c0f 100644 --- a/lib/db/caches.php +++ b/lib/db/caches.php @@ -454,4 +454,11 @@ $definitions = array( 'mode' => cache_store::MODE_APPLICATION, 'simpledata' => true, ], + + // Cache for licenses. + 'license' => [ + 'mode' => cache_store::MODE_APPLICATION, + 'simplekeys' => false, + 'simpledata' => false + ], ); diff --git a/lib/db/install.xml b/lib/db/install.xml index 2bc9085f701..be3ac0058ba 100644 --- a/lib/db/install.xml +++ b/lib/db/install.xml @@ -2535,6 +2535,7 @@ + @@ -2853,6 +2854,8 @@ + + diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php index 1f5796e3f6f..d0d822d82b6 100644 --- a/lib/db/upgrade.php +++ b/lib/db/upgrade.php @@ -2392,5 +2392,40 @@ function xmldb_main_upgrade($oldversion) { upgrade_main_savepoint(true, 2020052000.00); } + if ($oldversion < 2020052200.01) { + + // Define field custom to be added to license. + $table = new xmldb_table('license'); + $field = new xmldb_field('custom', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); + + // Conditionally launch add field custom. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Define field sortorder to be added to license. + $field = new xmldb_field('sortorder', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0'); + + // Conditionally launch add field sortorder. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Define index license (not unique) to be added to files. + $table = new xmldb_table('files'); + $index = new xmldb_index('license', XMLDB_INDEX_NOTUNIQUE, ['license']); + + // Conditionally launch add index license. + if (!$dbman->index_exists($table, $index)) { + $dbman->add_index($table, $index); + } + + // Upgrade the core license details. + upgrade_core_licenses(); + + // Main savepoint reached. + upgrade_main_savepoint(true, 2020052200.01); + } + return true; } diff --git a/lib/db/upgradelib.php b/lib/db/upgradelib.php index d2ebc51d0a7..8e66a0f17a3 100644 --- a/lib/db/upgradelib.php +++ b/lib/db/upgradelib.php @@ -628,3 +628,124 @@ function upgrade_analytics_fix_contextids_defaults() { $params = ['zero' => '0', 'null' => 'null']; $DB->execute("UPDATE {analytics_models} set contextids = null WHERE " . $select, $params); } + +/** + * Upgrade core licenses shipped with Moodle. + */ +function upgrade_core_licenses() { + global $CFG, $DB; + + $corelicenses = []; + + $license = new stdClass(); + $license->shortname = 'unknown'; + $license->fullname = 'Licence not specified'; + $license->source = ''; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'allrightsreserved'; + $license->fullname = 'All rights reserved'; + $license->source = 'https://en.wikipedia.org/wiki/All_rights_reserved'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'public'; + $license->fullname = 'Public domain'; + $license->source = 'https://en.wikipedia.org/wiki/Public_domain'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'cc'; + $license->fullname = 'Creative Commons'; + $license->source = 'https://creativecommons.org/licenses/by/3.0/'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'cc-nd'; + $license->fullname = 'Creative Commons - NoDerivs'; + $license->source = 'https://creativecommons.org/licenses/by-nd/3.0/'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'cc-nc-nd'; + $license->fullname = 'Creative Commons - No Commercial NoDerivs'; + $license->source = 'https://creativecommons.org/licenses/by-nc-nd/3.0/'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'cc-nc'; + $license->fullname = 'Creative Commons - No Commercial'; + $license->source = 'https://creativecommons.org/licenses/by-nc/3.0/'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'cc-nc-sa'; + $license->fullname = 'Creative Commons - No Commercial ShareAlike'; + $license->source = 'https://creativecommons.org/licenses/by-nc-sa/3.0/'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + $license = new stdClass(); + $license->shortname = 'cc-sa'; + $license->fullname = 'Creative Commons - ShareAlike'; + $license->source = 'https://creativecommons.org/licenses/by-sa/3.0/'; + $license->enabled = 1; + $license->version = '2010033100'; + $license->custom = 0; + $corelicenses[] = $license; + + foreach ($corelicenses as $corelicense) { + // Check for current license to maintain idempotence. + $currentlicense = $DB->get_record('license', ['shortname' => $corelicense->shortname]); + if (!empty($currentlicense)) { + $corelicense->id = $currentlicense->id; + // Remember if the license was enabled before upgrade. + $corelicense->enabled = $currentlicense->enabled; + $DB->update_record('license', $corelicense); + } else if (!isset($CFG->upgraderunning) || during_initial_install()) { + // Only install missing core licenses if not upgrading or during initial install. + $DB->insert_record('license', $corelicense); + } + } + + // Add sortorder to all licenses. + $licenses = $DB->get_records('license'); + $sortorder = 1; + foreach ($licenses as $license) { + $license->sortorder = $sortorder++; + $DB->update_record('license', $license); + } + + // Set the license config values, used by file repository for rendering licenses at front end. + $activelicenses = $DB->get_records_menu('license', ['enabled' => 1], 'id', 'id, shortname'); + set_config('licenses', implode(',', $activelicenses)); + + $sitedefaultlicense = get_config('', 'sitedefaultlicense'); + if (empty($sitedefaultlicense) || !in_array($sitedefaultlicense, $activelicenses)) { + set_config('sitedefaultlicense', reset($activelicenses)); + } +} diff --git a/lib/form/filemanager.js b/lib/form/filemanager.js index b3ebb6ea4af..5fe7586e5cc 100644 --- a/lib/form/filemanager.js +++ b/lib/form/filemanager.js @@ -704,17 +704,29 @@ M.form_filemanager.init = function(Y, options) { this.filemanager.one('.fp-content').fp_display_filelist(options, list, this.lazyloading); this.content_scrolled(); }, - populate_licenses_select: function(node) { - if (!node) { + populateLicensesSelect: function(licensenode, filenode) { + if (!licensenode) { return; } - node.setContent(''); - var licenses = this.options.licenses; + licensenode.setContent(''); + var selectedlicense = this.filepicker_options.defaultlicense; + if (filenode) { + // File has a license already, use it. + selectedlicense = filenode.license; + } else if (this.filepicker_options.rememberuserlicensepref) { + selectedlicense = this.get_preference('recentlicense'); + } + var licenses = this.filepicker_options.licenses; for (var i in licenses) { - var option = Y.Node.create('