Merge branch 'MDL-76867-master' of https://github.com/andrewnicols/moodle
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
define("core_admin/block_management_table",["exports","./plugin_management_table","core_table/dynamic","core/ajax","core/pending","core/notification"],(function(_exports,_plugin_management_table,_dynamic,_ajax,_pending,_notification){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_plugin_management_table=_interopRequireDefault(_plugin_management_table),_pending=_interopRequireDefault(_pending);class _default extends _plugin_management_table.default{constructor(){super(),this.addClickHandler(this.handleBlockProtectToggle)}setBlockProtectState(plugin,state){return(0,_ajax.call)([{methodname:"core_admin_set_block_protection",args:{plugin:plugin,state:state}}])[0]}async handleBlockProtectToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="toggleprotectstate"]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setBlockProtectState(stateToggle.dataset.plugin,"1"===stateToggle.dataset.targetState?1:0);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="toggleprotectstate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),pendingPromise.resolve()}}}return _exports.default=_default,_exports.default}));
|
||||
|
||||
//# sourceMappingURL=block_management_table.min.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"block_management_table.min.js","sources":["../src/block_management_table.js"],"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 <http://www.gnu.org/licenses/>.\n\nimport PluginManagementTable from './plugin_management_table';\nimport {refreshTableContent} from 'core_table/dynamic';\nimport {call as fetchMany} from 'core/ajax';\nimport Pending from 'core/pending';\nimport {fetchNotifications} from 'core/notification';\n\nexport default class extends PluginManagementTable {\n constructor() {\n super();\n this.addClickHandler(this.handleBlockProtectToggle);\n }\n\n /**\n * Set the block protection state.\n *\n * @param {string} plugin\n * @param {number} state\n * @returns {Promise}\n */\n setBlockProtectState(plugin, state) {\n return fetchMany([{\n methodname: 'core_admin_set_block_protection',\n args: {\n plugin,\n state,\n },\n }])[0];\n }\n\n /**\n * Handle toggling of block protection.\n *\n * @param {HTMLElement} tableRoot\n * @param {Event} e\n */\n async handleBlockProtectToggle(tableRoot, e) {\n const stateToggle = e.target.closest('[data-action=\"toggleprotectstate\"]');\n if (stateToggle) {\n e.preventDefault();\n const pendingPromise = new Pending('core_table/dynamic:processAction');\n\n await this.setBlockProtectState(\n stateToggle.dataset.plugin,\n stateToggle.dataset.targetState === '1' ? 1 : 0\n );\n\n const [updatedRoot] = await Promise.all([\n refreshTableContent(tableRoot),\n fetchNotifications(),\n ]);\n\n // Refocus on the link that as pressed in the first place.\n updatedRoot.querySelector(`[data-action=\"toggleprotectstate\"][data-plugin=\"${stateToggle.dataset.plugin}\"]`).focus();\n pendingPromise.resolve();\n }\n }\n}\n"],"names":["_interopRequireDefault","obj","__esModule","default","_plugin_management_table","_pending","_default","PluginManagementTable","constructor","super","this","addClickHandler","handleBlockProtectToggle","setBlockProtectState","plugin","state","fetchMany","call","methodname","args","async","tableRoot","e","stateToggle","target","closest","preventDefault","pendingPromise","Pending","dataset","targetState","updatedRoot","Promise","all","refreshTableContent","fetchNotifications","querySelector","concat","focus","resolve","_exports"],"mappings":"0OAkBmC,SAAAA,uBAAAC,KAAAA,OAAAA,KAAAA,IAAAC,WAAAD,IAAAE,CAAAA,QAAAF,IAAA,iFAHnCG,yBAAAJ,uBAAAI,0BAGAC,SAAAL,uBAAAK,UAGe,MAAAC,iBAAcC,yBAAAA,QACzBC,cACIC,QACAC,KAAKC,gBAAgBD,KAAKE,yBAC9B,CASAC,qBAAqBC,OAAQC,OACzB,OAAO,EAAAC,MAASC,MAAC,CAAC,CACdC,WAAY,kCACZC,KAAM,CACFL,cACAC,gBAEJ,EACR,CAQAK,+BAA+BC,UAAWC,GACtC,MAAMC,YAAcD,EAAEE,OAAOC,QAAQ,sCACrC,GAAIF,YAAa,CACbD,EAAEI,iBACF,MAAMC,eAAiB,IAAIC,SAAOzB,QAAC,0CAE7BO,KAAKG,qBACPU,YAAYM,QAAQf,OACgB,MAApCS,YAAYM,QAAQC,YAAsB,EAAI,GAGlD,MAAOC,mBAAqBC,QAAQC,IAAI,EACpC,EAAAC,SAAmBA,qBAACb,YACpB,EAAAc,cAAkBA,wBAItBJ,YAAYK,cAAaC,mDAAAA,OAAoDd,YAAYM,QAAQf,OAAW,OAACwB,QAC7GX,eAAeY,SACnB,CACJ,EACH,OAAAC,SAAArC,QAAAG,SAAAkC,SAAArC,OAAA"}
|
||||
@@ -0,0 +1,3 @@
|
||||
define("core_admin/plugin_management_table",["exports","core_table/dynamic","core_table/local/dynamic/selectors","core/ajax","core/pending","core/notification"],(function(_exports,_dynamic,Selectors,_ajax,_pending,_notification){var obj;function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _defineProperty(obj,key,value){return(key=function(arg){var key=function(input,hint){if("object"!=typeof input||null===input)return input;var prim=input[Symbol.toPrimitive];if(void 0!==prim){var res=prim.call(input,hint||"default");if("object"!=typeof res)return res;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===hint?String:Number)(input)}(arg,"string");return"symbol"==typeof key?key:String(key)}(key))in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Selectors=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(Selectors),_pending=(obj=_pending)&&obj.__esModule?obj:{default:obj};let watching=!1;return _exports.default=class{constructor(){_defineProperty(this,"clickHandlers",[]),this.addClickHandler(this.handleStateToggle),this.addClickHandler(this.handleMoveUpDown),this.registerEventListeners()}static init(){watching||(watching=!0,new this)}addClickHandler(handler){this.clickHandlers.push(handler.bind(this))}registerEventListeners(){document.addEventListener("click",function(e){const tableRoot=this.getTableRoot(e);tableRoot&&this.clickHandlers.forEach((handler=>handler(tableRoot,e)))}.bind(this))}getTableRoot(e){const tableRoot=e.target.closest(Selectors.main.region);return tableRoot||!1}setPluginState(methodname,plugin,state){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,state:state}}])[0]}setPluginOrder(methodname,plugin,direction){return(0,_ajax.call)([{methodname:methodname,args:{plugin:plugin,direction:direction}}])[0]}async handleStateToggle(tableRoot,e){const stateToggle=e.target.closest('[data-action="togglestate"][data-toggle-method]');if(stateToggle){e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:togglestate");await this.setPluginState(stateToggle.dataset.toggleMethod,stateToggle.dataset.plugin,"1"===stateToggle.dataset.state?0:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]);updatedRoot.querySelector('[data-action="togglestate"][data-plugin="'.concat(stateToggle.dataset.plugin,'"]')).focus(),pendingPromise.resolve()}}async handleMoveUpDown(tableRoot,e){const actionLink=e.target.closest('[data-action="move"][data-method][data-direction]');if(!actionLink)return;e.preventDefault();const pendingPromise=new _pending.default("core_table/dynamic:processAction");await this.setPluginOrder(actionLink.dataset.method,actionLink.dataset.plugin,"up"===actionLink.dataset.direction?-1:1);const[updatedRoot]=await Promise.all([(0,_dynamic.refreshTableContent)(tableRoot),(0,_notification.fetchNotifications)()]),exactMatch=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"][data-direction="').concat(actionLink.dataset.direction,'"]'));var _updatedRoot$querySel;exactMatch?exactMatch.focus():null===(_updatedRoot$querySel=updatedRoot.querySelector('[data-action="move"][data-plugin="'.concat(actionLink.dataset.plugin,'"]')))||void 0===_updatedRoot$querySel||_updatedRoot$querySel.focus();pendingPromise.resolve()}},_exports.default}));
|
||||
|
||||
//# sourceMappingURL=plugin_management_table.min.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,72 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import PluginManagementTable from './plugin_management_table';
|
||||
import {refreshTableContent} from 'core_table/dynamic';
|
||||
import {call as fetchMany} from 'core/ajax';
|
||||
import Pending from 'core/pending';
|
||||
import {fetchNotifications} from 'core/notification';
|
||||
|
||||
export default class extends PluginManagementTable {
|
||||
constructor() {
|
||||
super();
|
||||
this.addClickHandler(this.handleBlockProtectToggle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block protection state.
|
||||
*
|
||||
* @param {string} plugin
|
||||
* @param {number} state
|
||||
* @returns {Promise}
|
||||
*/
|
||||
setBlockProtectState(plugin, state) {
|
||||
return fetchMany([{
|
||||
methodname: 'core_admin_set_block_protection',
|
||||
args: {
|
||||
plugin,
|
||||
state,
|
||||
},
|
||||
}])[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle toggling of block protection.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @param {Event} e
|
||||
*/
|
||||
async handleBlockProtectToggle(tableRoot, e) {
|
||||
const stateToggle = e.target.closest('[data-action="toggleprotectstate"]');
|
||||
if (stateToggle) {
|
||||
e.preventDefault();
|
||||
const pendingPromise = new Pending('core_table/dynamic:processAction');
|
||||
|
||||
await this.setBlockProtectState(
|
||||
stateToggle.dataset.plugin,
|
||||
stateToggle.dataset.targetState === '1' ? 1 : 0
|
||||
);
|
||||
|
||||
const [updatedRoot] = await Promise.all([
|
||||
refreshTableContent(tableRoot),
|
||||
fetchNotifications(),
|
||||
]);
|
||||
|
||||
// Refocus on the link that as pressed in the first place.
|
||||
updatedRoot.querySelector(`[data-action="toggleprotectstate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
|
||||
pendingPromise.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
import {refreshTableContent} from 'core_table/dynamic';
|
||||
import * as Selectors from 'core_table/local/dynamic/selectors';
|
||||
import {call as fetchMany} from 'core/ajax';
|
||||
import Pending from 'core/pending';
|
||||
import {fetchNotifications} from 'core/notification';
|
||||
|
||||
let watching = false;
|
||||
|
||||
export default class {
|
||||
/**
|
||||
* @property {function[]} clickHandlers a list of handlers to call on click.
|
||||
*/
|
||||
clickHandlers = [];
|
||||
|
||||
constructor() {
|
||||
this.addClickHandler(this.handleStateToggle);
|
||||
this.addClickHandler(this.handleMoveUpDown);
|
||||
this.registerEventListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise an instance of the class.
|
||||
*
|
||||
* This is just a way of making it easier to initialise an instance of the class from PHP.
|
||||
*/
|
||||
static init() {
|
||||
if (watching) {
|
||||
return;
|
||||
}
|
||||
watching = true;
|
||||
new this();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a click handler to the list of handlers.
|
||||
*
|
||||
* @param {Function} handler A handler to call on a click event
|
||||
*/
|
||||
addClickHandler(handler) {
|
||||
this.clickHandlers.push(handler.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the event listeners for this instance.
|
||||
*/
|
||||
registerEventListeners() {
|
||||
document.addEventListener('click', function(e) {
|
||||
const tableRoot = this.getTableRoot(e);
|
||||
|
||||
if (!tableRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clickHandlers.forEach((handler) => handler(tableRoot, e));
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table root from an event.
|
||||
*
|
||||
* @param {Event} e
|
||||
* @returns {HTMLElement|bool}
|
||||
*/
|
||||
getTableRoot(e) {
|
||||
const tableRoot = e.target.closest(Selectors.main.region);
|
||||
if (!tableRoot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return tableRoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin state (enabled or disabled)
|
||||
*
|
||||
* @param {string} methodname The web service to call
|
||||
* @param {string} plugin The name of the plugin to set the state for
|
||||
* @param {number} state The state to set
|
||||
* @returns {Promise}
|
||||
*/
|
||||
setPluginState(methodname, plugin, state) {
|
||||
return fetchMany([{
|
||||
methodname,
|
||||
args: {
|
||||
plugin,
|
||||
state,
|
||||
},
|
||||
}])[0];
|
||||
}
|
||||
|
||||
setPluginOrder(methodname, plugin, direction) {
|
||||
return fetchMany([{
|
||||
methodname,
|
||||
args: {
|
||||
plugin,
|
||||
direction,
|
||||
},
|
||||
}])[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle state toggling.
|
||||
*
|
||||
* @param {HTMLElement} tableRoot
|
||||
* @param {Event} e
|
||||
*/
|
||||
async handleStateToggle(tableRoot, e) {
|
||||
const stateToggle = e.target.closest('[data-action="togglestate"][data-toggle-method]');
|
||||
if (stateToggle) {
|
||||
e.preventDefault();
|
||||
const pendingPromise = new Pending('core_table/dynamic:togglestate');
|
||||
|
||||
await this.setPluginState(
|
||||
stateToggle.dataset.toggleMethod,
|
||||
stateToggle.dataset.plugin,
|
||||
stateToggle.dataset.state === '1' ? 0 : 1
|
||||
);
|
||||
|
||||
const [updatedRoot] = await Promise.all([
|
||||
refreshTableContent(tableRoot),
|
||||
fetchNotifications(),
|
||||
]);
|
||||
|
||||
// Refocus on the link that as pressed in the first place.
|
||||
updatedRoot.querySelector(`[data-action="togglestate"][data-plugin="${stateToggle.dataset.plugin}"]`).focus();
|
||||
pendingPromise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
async handleMoveUpDown(tableRoot, e) {
|
||||
const actionLink = e.target.closest('[data-action="move"][data-method][data-direction]');
|
||||
if (!actionLink) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
const pendingPromise = new Pending('core_table/dynamic:processAction');
|
||||
|
||||
await this.setPluginOrder(
|
||||
actionLink.dataset.method,
|
||||
actionLink.dataset.plugin,
|
||||
actionLink.dataset.direction === 'up' ? -1 : 1,
|
||||
);
|
||||
|
||||
const [updatedRoot] = await Promise.all([
|
||||
refreshTableContent(tableRoot),
|
||||
fetchNotifications(),
|
||||
]);
|
||||
|
||||
// Refocus on the link that as pressed in the first place.
|
||||
const exactMatch = updatedRoot.querySelector(
|
||||
`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"][data-direction="${actionLink.dataset.direction}"]`
|
||||
);
|
||||
if (exactMatch) {
|
||||
exactMatch.focus();
|
||||
} else {
|
||||
// The move link is not present anymore, so we need to focus on the other one.
|
||||
updatedRoot.querySelector(`[data-action="move"][data-plugin="${actionLink.dataset.plugin}"]`)?.focus();
|
||||
}
|
||||
|
||||
pendingPromise.resolve();
|
||||
}
|
||||
}
|
||||
+76
-226
@@ -1,244 +1,94 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Allows the admin to configure blocks (hide/show, uninstall and configure)
|
||||
/**
|
||||
* Allows the admin to configure blocks (hide/show, uninstall and configure)
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @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.'/blocklib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
require_once('../config.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
require_once("{$CFG->libdir}/blocklib.php");
|
||||
require_once("{$CFG->libdir}/tablelib.php");
|
||||
|
||||
admin_externalpage_setup('manageblocks');
|
||||
admin_externalpage_setup('manageblocks');
|
||||
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$hide = optional_param('hide', 0, PARAM_INT);
|
||||
$show = optional_param('show', 0, PARAM_INT);
|
||||
$unprotect = optional_param('unprotect', 0, PARAM_INT);
|
||||
$protect = optional_param('protect', 0, PARAM_INT);
|
||||
$plugin = optional_param('plugin', '', PARAM_PLUGIN);
|
||||
$action = optional_param('action', '', PARAM_ALPHA);
|
||||
$unprotect = optional_param('unprotect', 0, PARAM_PLUGIN);
|
||||
$protect = optional_param('protect', 0, PARAM_PLUGIN);
|
||||
|
||||
/// Print headings
|
||||
$strmanageblocks = get_string('manageblocks');
|
||||
|
||||
$strmanageblocks = get_string('manageblocks');
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
$strversion = get_string('version');
|
||||
$strhide = get_string('hide');
|
||||
$strshow = get_string('show');
|
||||
$strsettings = get_string('settings');
|
||||
$strcourses = get_string('blockinstances', 'admin');
|
||||
$strname = get_string('name');
|
||||
$strshowblockcourse = get_string('showblockcourse');
|
||||
$strprotecthdr = get_string('blockprotect', 'admin'). $OUTPUT->help_icon('blockprotect','admin');
|
||||
$strprotect = get_string('blockprotect', 'admin');
|
||||
$strunprotect = get_string('blockunprotect', 'admin');
|
||||
// If data submitted, then process and store.
|
||||
if (!empty($plugin) && !empty($action) && confirm_sesskey()) {
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$pluginname = get_string('pluginname', "block_{$plugin}");
|
||||
|
||||
if ($action === 'disable' && $manager::enable_plugin($plugin, 0)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
} else if ($action === 'enable' && $manager::enable_plugin($plugin, 1)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
|
||||
// If data submitted, then process and store.
|
||||
if (!empty($hide) && confirm_sesskey()) {
|
||||
if (!$block = $DB->get_record('block', ['id' => $hide])) {
|
||||
throw new \moodle_exception('blockdoesnotexist', 'error');
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$class::enable_plugin($block->name, false);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
|
||||
if (!empty($show) && confirm_sesskey() ) {
|
||||
if (!$block = $DB->get_record('block', ['id' => $show])) {
|
||||
throw new \moodle_exception('blockdoesnotexist', 'error');
|
||||
}
|
||||
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('block');
|
||||
$class::enable_plugin($block->name, true);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
|
||||
if (!empty($protect) && confirm_sesskey()) {
|
||||
block_manager::protect_block((int)$protect);
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
if (!empty($unprotect) && confirm_sesskey()) {
|
||||
block_manager::unprotect_block((int)$unprotect);
|
||||
admin_get_root(true, false); // settings not required - only pages
|
||||
}
|
||||
|
||||
$undeletableblocktypes = block_manager::get_undeletable_block_types();
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($strmanageblocks);
|
||||
|
||||
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info');
|
||||
/// Main display starts here
|
||||
|
||||
// Get & sort the existing blocks, Select the id, name & visible fields along with count of number of total blocks & course blocks.
|
||||
|
||||
$sql = "SELECT b.id, b.name, b.visible, COUNT(DISTINCT binst.id) as totalcount, COUNT(DISTINCT bcinst.id) as courseviewcount
|
||||
FROM {block} b
|
||||
LEFT JOIN {block_instances} binst ON binst.blockname = b.name
|
||||
LEFT JOIN {block_instances} bcinst ON bcinst.blockname = b.name AND bcinst.pagetypepattern = 'course-view-*'
|
||||
GROUP BY b.id, b.name, b.visible, binst.blockname, bcinst.blockname
|
||||
ORDER BY b.name ASC";
|
||||
if (!$blocks = $DB->get_records_sql($sql)) {
|
||||
throw new \moodle_exception('noblocks', 'error'); // Should never happen.
|
||||
// Redirect back to the page with out any params.
|
||||
redirect(new moodle_url('/admin/blocks.php'));
|
||||
}
|
||||
|
||||
$incompatible = array();
|
||||
if (!empty($protect) && confirm_sesskey()) {
|
||||
block_manager::protect_block($protect);
|
||||
$pluginname = get_string('pluginname', "block_{$protect}");
|
||||
\core\notification::add(
|
||||
get_string('blockprotected', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
|
||||
/// Print the table of all blocks
|
||||
if (!empty($unprotect) && confirm_sesskey()) {
|
||||
block_manager::unprotect_block($unprotect);
|
||||
$pluginname = get_string('pluginname', "block_{$unprotect}");
|
||||
\core\notification::add(
|
||||
get_string('blockunprotected', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
|
||||
$table = new flexible_table('admin-blocks-compatible');
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($strmanageblocks);
|
||||
echo $OUTPUT->notification(get_string('noteunneededblocks', 'admin'), 'info', false);
|
||||
|
||||
$table->define_columns(array('name', 'instances', 'version', 'hideshow', 'undeletable', 'settings', 'uninstall'));
|
||||
$table->define_headers(array($strname, $strcourses, $strversion, $strhide.'/'.$strshow, $strprotecthdr, $strsettings, $struninstall));
|
||||
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
|
||||
$table->set_attribute('class', 'admintable blockstable generaltable');
|
||||
$table->set_attribute('id', 'compatibleblockstable');
|
||||
$table->setup();
|
||||
$tablerows = array();
|
||||
|
||||
// Sort blocks using current locale.
|
||||
$blocknames = array();
|
||||
foreach ($blocks as $blockid=>$block) {
|
||||
$blockname = $block->name;
|
||||
if (file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
|
||||
$blocknames[$blockid] = get_string('pluginname', 'block_'.$blockname);
|
||||
} else {
|
||||
$blocknames[$blockid] = $blockname;
|
||||
}
|
||||
}
|
||||
core_collator::asort($blocknames);
|
||||
|
||||
foreach ($blocknames as $blockid=>$strblockname) {
|
||||
$block = $blocks[$blockid];
|
||||
$blockname = $block->name;
|
||||
$dbversion = get_config('block_'.$block->name, 'version');
|
||||
|
||||
if (!file_exists("$CFG->dirroot/blocks/$blockname/block_$blockname.php")) {
|
||||
$blockobject = false;
|
||||
$strblockname = '<span class="notifyproblem">'.$strblockname.' ('.get_string('missingfromdisk').')</span>';
|
||||
$plugin = new stdClass();
|
||||
$plugin->version = $dbversion;
|
||||
|
||||
} else {
|
||||
$plugin = new stdClass();
|
||||
$plugin->version = '???';
|
||||
if (file_exists("$CFG->dirroot/blocks/$blockname/version.php")) {
|
||||
include("$CFG->dirroot/blocks/$blockname/version.php");
|
||||
}
|
||||
|
||||
if (!$blockobject = block_instance($block->name)) {
|
||||
$incompatible[] = $block;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$blockname, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
} else {
|
||||
$uninstall = '';
|
||||
}
|
||||
|
||||
$settings = ''; // By default, no configuration
|
||||
if ($blockobject and $blockobject->has_config()) {
|
||||
$blocksettings = admin_get_root()->locate('blocksetting' . $block->name);
|
||||
|
||||
if ($blocksettings instanceof admin_externalpage) {
|
||||
$settings = '<a href="' . $blocksettings->url . '">' . get_string('settings') . '</a>';
|
||||
} else if ($blocksettings instanceof admin_settingpage) {
|
||||
$settings = '<a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/settings.php?section=blocksetting'.$block->name.'">'.$strsettings.'</a>';
|
||||
} else if (!file_exists($CFG->dirroot.'/blocks/'.$block->name.'/settings.php')) {
|
||||
// If the block's settings node was not found, we check that the block really provides the settings.php file.
|
||||
// Note that blocks can inject their settings to other nodes in the admin tree without using the default locations.
|
||||
// This can be done by assigning null to $setting in settings.php and it is a valid case.
|
||||
debugging('Warning: block_'.$block->name.' returns true in has_config() but does not provide a settings.php file',
|
||||
DEBUG_DEVELOPER);
|
||||
}
|
||||
}
|
||||
|
||||
// MDL-11167, blocks can be placed on mymoodle, or the blogs page
|
||||
// and it should not show up on course search page
|
||||
|
||||
$totalcount = $blocks[$blockid]->totalcount;
|
||||
$count = $blocks[$blockid]->courseviewcount;
|
||||
if ($count>0) {
|
||||
$blocklist = "<a href=\"{$CFG->wwwroot}/course/search.php?blocklist=$blockid&sesskey=".sesskey()."\" ";
|
||||
$blocklist .= "title=\"$strshowblockcourse\" >$totalcount</a>";
|
||||
}
|
||||
else {
|
||||
$blocklist = "$totalcount";
|
||||
}
|
||||
$class = ''; // Nothing fancy, by default
|
||||
|
||||
if (!$blockobject) {
|
||||
// ignore
|
||||
$visible = '';
|
||||
} else if ($blocks[$blockid]->visible) {
|
||||
$visible = '<a href="blocks.php?hide='.$blockid.'&sesskey='.sesskey().'" title="'.$strhide.'">'.
|
||||
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
|
||||
} else {
|
||||
$visible = '<a href="blocks.php?show='.$blockid.'&sesskey='.sesskey().'" title="'.$strshow.'">'.
|
||||
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
|
||||
if ($dbversion == $plugin->version) {
|
||||
$version = $dbversion;
|
||||
} else {
|
||||
$version = "$dbversion ($plugin->version)";
|
||||
}
|
||||
|
||||
if (!$blockobject) {
|
||||
// ignore
|
||||
$undeletable = '';
|
||||
} else if (in_array($blockname, $undeletableblocktypes)) {
|
||||
$undeletable = '<a href="blocks.php?unprotect='.$blockid.'&sesskey='.sesskey().'" title="'.$strunprotect.'">'.
|
||||
$OUTPUT->pix_icon('t/unlock', $strunprotect) . '</a>';
|
||||
} else {
|
||||
$undeletable = '<a href="blocks.php?protect='.$blockid.'&sesskey='.sesskey().'" title="'.$strprotect.'">'.
|
||||
$OUTPUT->pix_icon('t/lock', $strprotect) . '</a>';
|
||||
}
|
||||
|
||||
$row = array(
|
||||
$strblockname,
|
||||
$blocklist,
|
||||
$version,
|
||||
$visible,
|
||||
$undeletable,
|
||||
$settings,
|
||||
$uninstall,
|
||||
);
|
||||
$table->add_data($row, $class);
|
||||
}
|
||||
|
||||
$table->print_html();
|
||||
|
||||
if (!empty($incompatible)) {
|
||||
echo $OUTPUT->heading(get_string('incompatibleblocks', 'blockstable', 'admin'));
|
||||
|
||||
$table = new flexible_table('admin-blocks-incompatible');
|
||||
|
||||
$table->define_columns(array('block', 'uninstall'));
|
||||
$table->define_headers(array($strname, $struninstall));
|
||||
$table->define_baseurl($CFG->wwwroot.'/'.$CFG->admin.'/blocks.php');
|
||||
|
||||
$table->set_attribute('class', 'incompatibleblockstable generaltable');
|
||||
|
||||
$table->setup();
|
||||
|
||||
foreach ($incompatible as $block) {
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('block_'.$block->name, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
} else {
|
||||
$uninstall = '';
|
||||
}
|
||||
$table->add_data(array(
|
||||
$block->name,
|
||||
$uninstall,
|
||||
));
|
||||
}
|
||||
$table->print_html();
|
||||
}
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
// Print the table of all blocks.
|
||||
$table = new \core_admin\table\block_management_table();
|
||||
$table->out();
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\admin;
|
||||
|
||||
use admin_setting;
|
||||
use core_plugin_manager;
|
||||
use core_text;
|
||||
|
||||
/**
|
||||
* Admin setting plugin manager.
|
||||
*
|
||||
* @package core_admin
|
||||
* @subpackage admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_setting_plugin_manager extends admin_setting {
|
||||
/** @var core_plugin_manager The plugin manager instance */
|
||||
protected core_plugin_manager $pluginmanager;
|
||||
|
||||
/** @var string The plugintype that this manager covers */
|
||||
protected string $plugintype;
|
||||
|
||||
/** @var string The class of the management table to use */
|
||||
protected string $tableclass;
|
||||
|
||||
public function __construct(
|
||||
string $plugintype,
|
||||
string $tableclass,
|
||||
string $name,
|
||||
string $visiblename,
|
||||
string $description = '',
|
||||
string $defaultsetting = '',
|
||||
) {
|
||||
$this->nosave = true;
|
||||
$this->pluginmanager = core_plugin_manager::instance();
|
||||
$this->plugintype = $plugintype;
|
||||
$this->tableclass = $tableclass;
|
||||
|
||||
parent::__construct($name, $visiblename, $description, $defaultsetting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_setting(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_defaultsetting(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns '', does not write anything
|
||||
*
|
||||
* @return string Always returns ''
|
||||
*/
|
||||
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
public function write_setting($data): string {
|
||||
// Do not write any setting.
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if $query is one of the available editors
|
||||
*
|
||||
* @param string $query The string to search for
|
||||
* @return bool Returns true if found, false if not
|
||||
*/
|
||||
public function is_related($query) {
|
||||
if (parent::is_related($query)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$plugins = $this->pluginmanager->get_installed_plugins($this->plugintype);
|
||||
foreach (array_keys($plugins) as $plugin) {
|
||||
$plugin = "{$this->plugintype}_{$plugin}";
|
||||
if (str_contains($plugin, $query)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$pluginname = get_string('pluginname', $plugin);
|
||||
if (strpos(core_text::strtolower($pluginname), $query) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XHTML to display the control
|
||||
*
|
||||
* @param string $data Unused
|
||||
* @param string $query
|
||||
* @return string
|
||||
*/
|
||||
public function output_html($data, $query = ''): string {
|
||||
$table = new $this->tableclass();
|
||||
if (!($table instanceof \core_admin\table\plugin_management_table)) {
|
||||
throw new \coding_exception("{$this->tableclass} must be an instance of \\core_admin\\table\\plugin_management_table");
|
||||
}
|
||||
return highlight($query, $table->get_content());
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
use block_manager;
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_single_structure;
|
||||
use core_external\external_value;
|
||||
|
||||
/**
|
||||
* Web Service to control the state of a plugin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @category external
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_block_protection extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
|
||||
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block protection state.
|
||||
*
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int $state The target state
|
||||
* @return null
|
||||
*/
|
||||
public static function execute(
|
||||
string $plugin,
|
||||
int $state,
|
||||
): array {
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
]);
|
||||
|
||||
$context = \context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
[, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
|
||||
$displayname = get_string('pluginname', $plugin);
|
||||
|
||||
if ($state) {
|
||||
block_manager::protect_block($pluginname);
|
||||
\core\notification::add(
|
||||
get_string('blockprotected', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
} else {
|
||||
block_manager::unprotect_block($pluginname);
|
||||
\core\notification::add(
|
||||
get_string('blockunprotected', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe the return structure of the external service.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_single_structure;
|
||||
use core_external\external_value;
|
||||
|
||||
/**
|
||||
* Web Service to control the order of a plugin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @category external
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_plugin_order extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
|
||||
'direction' => new external_value(PARAM_INT, 'The direction to move', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin state.
|
||||
*
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int $direction The direction to move the plugin
|
||||
* @return array
|
||||
*/
|
||||
public static function execute(
|
||||
string $plugin,
|
||||
int $direction,
|
||||
): array {
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'direction' => $direction,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'plugin' => $plugin,
|
||||
'direction' => $direction,
|
||||
]);
|
||||
|
||||
$context = \context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
|
||||
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
|
||||
$manager::change_plugin_order($pluginname, $direction);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe the return structure of the external service.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_single_structure;
|
||||
use core_external\external_value;
|
||||
|
||||
/**
|
||||
* Web Service to control the state of a plugin.
|
||||
*
|
||||
* @package core_admin
|
||||
* @category external
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_plugin_state extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'plugin' => new external_value(PARAM_PLUGIN, 'The name of the plugin', VALUE_REQUIRED),
|
||||
'state' => new external_value(PARAM_INT, 'The target state', VALUE_REQUIRED),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the plugin state.
|
||||
*
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int $state The target state
|
||||
* @return null
|
||||
*/
|
||||
public static function execute(
|
||||
string $plugin,
|
||||
int $state,
|
||||
): array {
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
] = self::validate_parameters(self::execute_parameters(), [
|
||||
'plugin' => $plugin,
|
||||
'state' => $state,
|
||||
]);
|
||||
|
||||
$context = \context_system::instance();
|
||||
self::validate_context($context);
|
||||
require_capability('moodle/site:config', $context);
|
||||
|
||||
[$plugintype, $pluginname] = explode('_', \core_component::normalize_componentname($plugin), 2);
|
||||
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
|
||||
$displayname = get_string('pluginname', $plugin);
|
||||
|
||||
if ($manager::enable_plugin($pluginname, $state)) {
|
||||
if (!empty($state)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
} else {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Describe the return structure of the external service.
|
||||
*
|
||||
* @return external_single_structure
|
||||
*/
|
||||
public static function execute_returns(): external_single_structure {
|
||||
return new external_single_structure([]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use core_plugin_manager;
|
||||
use dml_exception;
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Activity Module admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class activity_management_table extends plugin_management_table {
|
||||
|
||||
public function setup() {
|
||||
$this->set_attribute('id', 'modules');
|
||||
$this->set_attribute('class', 'admintable generaltable');
|
||||
parent::setup();
|
||||
}
|
||||
|
||||
protected function get_table_id(): string {
|
||||
return 'module-administration-table';
|
||||
}
|
||||
|
||||
protected function get_plugintype(): string {
|
||||
return 'mod';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/modules.php')
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/modules.php', $params);
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
return array_merge(
|
||||
array_slice($columns, 0, 1, true),
|
||||
['activities' => get_string('activities')],
|
||||
array_slice($columns, 1, null, true),
|
||||
);
|
||||
}
|
||||
|
||||
protected function col_name(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$status = $row->plugininfo->get_status();
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
return html_writer::span(
|
||||
get_string('pluginmissingfromdisk', 'core', $row->plugininfo),
|
||||
'notifyproblem'
|
||||
);
|
||||
}
|
||||
|
||||
return html_writer::span(
|
||||
html_writer::img(
|
||||
$OUTPUT->image_url('monologo', $row->plugininfo->name),
|
||||
'',
|
||||
[
|
||||
'class' => 'icon',
|
||||
],
|
||||
) . get_string('modulename', $row->plugininfo->name)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the number of activities present, with a link to courses containing activity if relevant.
|
||||
*
|
||||
* @param mixed $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_activities(stdClass $row): string {
|
||||
global $DB, $OUTPUT;
|
||||
try {
|
||||
$count = $DB->count_records_select($row->plugininfo->name, "course <> 0");
|
||||
} catch (dml_exception $e) {
|
||||
$count = -1;
|
||||
}
|
||||
|
||||
if ($count > 0) {
|
||||
return $OUTPUT->action_link(
|
||||
new moodle_url('/course/search.php', [
|
||||
'modulelist' => $row->plugininfo->name,
|
||||
]),
|
||||
$count,
|
||||
null,
|
||||
['title' => get_string('showmodulecourse')]
|
||||
);
|
||||
} else if ($count < 0) {
|
||||
return get_string('error');
|
||||
} else {
|
||||
return $count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Tiny admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class block_management_table extends \core_admin\table\plugin_management_table {
|
||||
|
||||
/** @var plugininfo[] A list of blocks which cannot be deleted */
|
||||
protected array $undeletableblocktypes;
|
||||
|
||||
/** @var stdClass[] A list of basic block data */
|
||||
protected array $blockdata;
|
||||
|
||||
public function __construct() {
|
||||
global $DB;
|
||||
parent::__construct();
|
||||
$this->undeletableblocktypes = \block_manager::get_undeletable_block_types();
|
||||
|
||||
$sql = <<<EOF
|
||||
SELECT
|
||||
b.name,
|
||||
b.id,
|
||||
b.name,
|
||||
COUNT(DISTINCT binst.id) as totalcount,
|
||||
COUNT(DISTINCT bcinst.id) as courseviewcount
|
||||
FROM {block} b
|
||||
LEFT JOIN {block_instances} binst ON binst.blockname = b.name
|
||||
LEFT JOIN {block_instances} bcinst ON
|
||||
bcinst.blockname = b.name AND
|
||||
bcinst.pagetypepattern = 'course-view-*'
|
||||
GROUP BY b.id, b.name, b.visible, binst.blockname, bcinst.blockname
|
||||
ORDER BY b.name ASC
|
||||
EOF;
|
||||
|
||||
$this->blockdata = $DB->get_records_sql($sql);
|
||||
}
|
||||
|
||||
protected function get_plugintype(): string {
|
||||
return 'block';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/blocks.php')
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/blocks.php', $params);
|
||||
}
|
||||
|
||||
|
||||
protected function get_table_js_module(): string {
|
||||
return 'core_admin/block_management_table';
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
return array_merge(
|
||||
array_slice($columns, 0, 1, true),
|
||||
['instances' => get_string('blockinstances', 'admin')],
|
||||
array_slice($columns, 1, 2, true),
|
||||
['protect' => get_string('blockprotect', 'admin')],
|
||||
array_slice($columns, 3, null, true),
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_columns_with_help(): array {
|
||||
return [
|
||||
'protect' => new \help_icon('blockprotect', 'admin'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the instances column
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_instances(stdClass $row): string {
|
||||
$blockdata = $this->blockdata[$row->plugininfo->name];
|
||||
if ($blockdata->courseviewcount > 0) {
|
||||
return html_writer::link(
|
||||
new moodle_url('/course/search.php', [
|
||||
'blocklist' => $row->plugininfo->name,
|
||||
'sesskey' => sesskey(),
|
||||
]),
|
||||
$blockdata->totalcount,
|
||||
);
|
||||
}
|
||||
|
||||
return $blockdata->totalcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the protect column.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_protect(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$params = [
|
||||
'sesskey' => sesskey(),
|
||||
];
|
||||
|
||||
$protected = in_array($row->plugininfo->name, $this->undeletableblocktypes);
|
||||
|
||||
$pluginname = $row->plugininfo->displayname;
|
||||
if ($protected) {
|
||||
$params['unprotect'] = $row->plugininfo->name;
|
||||
$icon = $OUTPUT->pix_icon('t/unlock', get_string('blockunprotectblock', 'admin', $pluginname));
|
||||
} else {
|
||||
$params['protect'] = $row->plugininfo->name;
|
||||
$icon = $OUTPUT->pix_icon('t/lock', get_string('blockprotectblock', 'admin', $pluginname));
|
||||
}
|
||||
|
||||
return html_writer::link(
|
||||
$this->get_action_url($params),
|
||||
$icon,
|
||||
[
|
||||
'data-action' => 'toggleprotectstate',
|
||||
'data-plugin' => $row->plugin,
|
||||
'data-target-state' => $protected ? 0 : 1,
|
||||
],
|
||||
);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Tiny admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class editor_management_table extends \core_admin\table\plugin_management_table {
|
||||
protected function get_plugintype(): string {
|
||||
return 'editor';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/settings.php', ['section' => 'manageeditors'])
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/editors.php', $params);
|
||||
}
|
||||
|
||||
protected function order_plugins(array $plugins): array {
|
||||
global $CFG;
|
||||
|
||||
// The Editor list is stored in an ordered string.
|
||||
$activeeditors = explode(',', $CFG->texteditors);
|
||||
|
||||
$sortedplugins = [];
|
||||
foreach ($activeeditors as $editor) {
|
||||
if (isset($plugins[$editor])) {
|
||||
$sortedplugins[$editor] = $plugins[$editor];
|
||||
unset($plugins[$editor]);
|
||||
}
|
||||
}
|
||||
|
||||
$otherplugins = parent::order_plugins($plugins);
|
||||
return array_merge(
|
||||
$sortedplugins,
|
||||
$otherplugins
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Media plugin admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_management_table extends \core_admin\table\plugin_management_table {
|
||||
/** @var array The list of used extensions */
|
||||
protected array $usedextensions = [];
|
||||
|
||||
protected function get_plugintype(): string {
|
||||
return 'media';
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/media.php', $params);
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
return array_merge(
|
||||
array_slice($columns, 0, 1, true),
|
||||
['supports' => get_string('supports', 'core_media')],
|
||||
array_slice($columns, 1, null, true),
|
||||
);
|
||||
}
|
||||
|
||||
protected function col_name(stdClass $row): string {
|
||||
global $OUTPUT, $PAGE;
|
||||
|
||||
$name = $row->plugininfo->name;
|
||||
if ($PAGE->theme->resolve_image_location('icon', 'media_' . $name, false)) {
|
||||
$icon = $OUTPUT->pix_icon('icon', '', "media_{$name}", ['class' => 'icon pluginicon']);
|
||||
} else {
|
||||
$icon = $OUTPUT->pix_icon('spacer', '', 'moodle', ['class' => 'icon pluginicon noicon']);
|
||||
}
|
||||
|
||||
$help = '';
|
||||
if (get_string_manager()->string_exists('pluginname_help', 'media_' . $name)) {
|
||||
$help = ' ' . $OUTPUT->help_icon('pluginname', 'media_' . $name);
|
||||
}
|
||||
|
||||
return $icon . $row->plugininfo->displayname . $help;
|
||||
}
|
||||
|
||||
protected function col_supports(stdClass $row): string {
|
||||
return $row->plugininfo->supports($this->usedextensions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,503 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use context_system;
|
||||
use core_plugin_manager;
|
||||
use core_table\dynamic as dynamic_table;
|
||||
use flexible_table;
|
||||
use html_writer;
|
||||
use moodle_url;
|
||||
use stdClass;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
require_once("{$CFG->libdir}/tablelib.php");
|
||||
|
||||
/**
|
||||
* Plugin Management table.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
abstract class plugin_management_table extends flexible_table implements dynamic_table {
|
||||
|
||||
/** @var \core\plugininfo\base[] The plugin list */
|
||||
protected array $plugins = [];
|
||||
|
||||
/** @var int The number of enabled plugins of this type */
|
||||
protected int $enabledplugincount = 0;
|
||||
|
||||
/** @var core_plugin_manager */
|
||||
protected core_plugin_manager $pluginmanager;
|
||||
|
||||
/** @var string The plugininfo class for this plugintype */
|
||||
protected string $plugininfoclass;
|
||||
|
||||
public function __construct() {
|
||||
global $CFG;
|
||||
|
||||
parent::__construct($this->get_table_id());
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
|
||||
// Fetch the plugininfo class.
|
||||
$this->pluginmanager = core_plugin_manager::instance();
|
||||
$this->plugininfoclass = $this->pluginmanager::resolve_plugininfo_class($this->get_plugintype());
|
||||
|
||||
$this->guess_base_url();
|
||||
|
||||
$this->plugins = $this->get_sorted_plugins();
|
||||
$this->enabledplugincount = count(array_filter($this->plugins, function ($plugin) {
|
||||
return $plugin->is_enabled();
|
||||
}));
|
||||
|
||||
$this->setup_column_configuration();
|
||||
$this->set_filterset(new plugin_management_table_filterset());
|
||||
$this->setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of sorted plugins.
|
||||
*
|
||||
* @return \core\plugininfo\base[]
|
||||
*/
|
||||
protected function get_sorted_plugins(): array {
|
||||
if ($this->plugininfoclass::plugintype_supports_ordering()) {
|
||||
return $this->plugininfoclass::get_sorted_plugins();
|
||||
} else {
|
||||
$plugins = $this->pluginmanager->get_plugins_of_type($this->get_plugintype());
|
||||
return self::sort_plugins($plugins);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the plugins list.
|
||||
*
|
||||
* Note: This only applies to plugins which do not support ordering.
|
||||
*
|
||||
* @param \core\plugininfo\base[] $plugins
|
||||
* @return \core\plugininfo\base[]
|
||||
*/
|
||||
protected function sort_plugins(array $plugins): array {
|
||||
// The asort functions work by reference.
|
||||
\core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the column configuration for this table.
|
||||
*/
|
||||
protected function setup_column_configuration(): void {
|
||||
$columnlist = $this->get_column_list();
|
||||
$this->define_columns(array_keys($columnlist));
|
||||
$this->define_headers(array_values($columnlist));
|
||||
|
||||
$columnswithhelp = $this->get_columns_with_help();
|
||||
$columnhelp = array_map(function (string $column) use ($columnswithhelp): ?\renderable {
|
||||
if (array_key_exists($column, $columnswithhelp)) {
|
||||
return $columnswithhelp[$column];
|
||||
}
|
||||
|
||||
return null;
|
||||
}, array_keys($columnlist));
|
||||
$this->define_help_for_headers($columnhelp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the standard order of the plugins.
|
||||
*
|
||||
* @param array $plugins
|
||||
* @return array
|
||||
*/
|
||||
protected function order_plugins(array $plugins): array {
|
||||
uasort($plugins, function ($a, $b) {
|
||||
if ($a->is_enabled() && !$b->is_enabled()) {
|
||||
return -1;
|
||||
} else if (!$a->is_enabled() && $b->is_enabled()) {
|
||||
return 1;
|
||||
}
|
||||
return strnatcasecmp($a->name, $b->name);
|
||||
});
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the plugintype for this table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function get_plugintype(): string;
|
||||
|
||||
/**
|
||||
* Get the action URL for this table.
|
||||
*
|
||||
* The action URL is used to perform all actions when JS is not available.
|
||||
*
|
||||
* @param array $params
|
||||
* @return moodle_url
|
||||
*/
|
||||
abstract protected function get_action_url(array $params = []): moodle_url;
|
||||
|
||||
/**
|
||||
* Provide a default implementation for guessing the base URL from the action URL.
|
||||
*/
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl($this->get_action_url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web service method used to toggle state.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function get_toggle_service(): ?string {
|
||||
return 'core_admin_set_plugin_state';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the web service method used to order plugins.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
protected function get_sortorder_service(): ?string {
|
||||
return 'core_admin_set_plugin_order';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ID of the table.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_table_id(): string {
|
||||
return 'plugin_management_table-' . $this->get_plugintype();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the column titles
|
||||
* @return string[]
|
||||
*/
|
||||
protected function get_column_list(): array {
|
||||
$columns = [
|
||||
'name' => get_string('name', 'core'),
|
||||
'version' => get_string('version', 'core'),
|
||||
];
|
||||
|
||||
if ($this->supports_disabling()) {
|
||||
$columns['enabled'] = get_string('pluginenabled', 'core_plugin');
|
||||
}
|
||||
|
||||
if ($this->supports_ordering()) {
|
||||
$columns['order'] = get_string('order', 'core');
|
||||
}
|
||||
|
||||
$columns['settings'] = get_string('settings', 'core');
|
||||
$columns['uninstall'] = get_string('uninstallplugin', 'core_admin');
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
protected function get_columns_with_help(): array {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the context for this table.
|
||||
*
|
||||
* @return context_system
|
||||
*/
|
||||
public function get_context(): context_system {
|
||||
return context_system::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the table content.
|
||||
*/
|
||||
public function get_content(): string {
|
||||
ob_start();
|
||||
$this->out();
|
||||
$content = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the table.
|
||||
*/
|
||||
public function out(): void {
|
||||
$plugintype = $this->get_plugintype();
|
||||
foreach ($this->plugins as $plugininfo) {
|
||||
$plugin = "{$plugintype}_{$plugininfo->name}";
|
||||
$rowdata = (object) [
|
||||
'plugin' => $plugin,
|
||||
'plugininfo' => $plugininfo,
|
||||
'name' => $plugininfo->displayname,
|
||||
'version' => $plugininfo->versiondb,
|
||||
];
|
||||
$this->add_data_keyed(
|
||||
$this->format_row($rowdata),
|
||||
$this->get_row_class($rowdata)
|
||||
);
|
||||
}
|
||||
|
||||
$this->finish_output(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This table is not downloadable.
|
||||
* @param bool $downloadable
|
||||
* @return bool
|
||||
*/
|
||||
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
public function is_downloadable($downloadable = null): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the name column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_name(stdClass $row): string {
|
||||
$status = $row->plugininfo->get_status();
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
return html_writer::span(
|
||||
get_string('pluginmissingfromdisk', 'core', $row->plugininfo),
|
||||
'notifyproblem'
|
||||
);
|
||||
}
|
||||
|
||||
if ($row->plugininfo->is_installed_and_upgraded()) {
|
||||
return $row->plugininfo->displayname;
|
||||
}
|
||||
|
||||
return html_writer::span(
|
||||
$row->plugininfo->displayname,
|
||||
'notifyproblem'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the enable/disable column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_enabled(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
$enabled = $row->plugininfo->is_enabled();
|
||||
$params = [
|
||||
'sesskey' => sesskey(),
|
||||
'plugin' => $row->plugininfo->name,
|
||||
'action' => $enabled ? 'disable' : 'enable',
|
||||
];
|
||||
|
||||
if ($enabled) {
|
||||
$icon = $OUTPUT->pix_icon('t/hide', get_string('disableplugin', 'core_admin', $row->plugininfo->displayname));
|
||||
} else {
|
||||
$icon = $OUTPUT->pix_icon('t/show', get_string('enableplugin', 'core_admin', $row->plugininfo->displayname));
|
||||
}
|
||||
|
||||
return html_writer::link(
|
||||
$this->get_action_url($params),
|
||||
$icon,
|
||||
[
|
||||
'data-toggle-method' => $this->get_toggle_service(),
|
||||
'data-action' => 'togglestate',
|
||||
'data-plugin' => $row->plugin,
|
||||
'data-state' => $enabled ? 1 : 0,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
protected function col_order(stdClass $row): string {
|
||||
global $OUTPUT;
|
||||
|
||||
if (!$this->supports_ordering()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$row->plugininfo->is_enabled()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($this->enabledplugincount <= 1) {
|
||||
// There is only one row.
|
||||
return '';
|
||||
}
|
||||
|
||||
$hasup = true;
|
||||
$hasdown = true;
|
||||
|
||||
if (empty($this->currentrow)) {
|
||||
// This is the top row.
|
||||
$hasup = false;
|
||||
}
|
||||
|
||||
if ($this->currentrow === ($this->enabledplugincount - 1)) {
|
||||
// This is the last row.
|
||||
$hasdown = false;
|
||||
}
|
||||
|
||||
if ($this->supports_ordering()) {
|
||||
$dataattributes = [
|
||||
'data-method' => $this->get_sortorder_service(),
|
||||
'data-action' => 'move',
|
||||
'data-plugin' => $row->plugin,
|
||||
];
|
||||
} else {
|
||||
$dataattributes = [];
|
||||
}
|
||||
|
||||
if ($hasup) {
|
||||
$upicon = html_writer::link(
|
||||
$this->get_action_url([
|
||||
'sesskey' => sesskey(),
|
||||
'action' => 'up',
|
||||
'plugin' => $row->plugininfo->name,
|
||||
]),
|
||||
$OUTPUT->pix_icon('t/up', get_string('moveup')),
|
||||
array_merge($dataattributes, ['data-direction' => 'up']),
|
||||
);
|
||||
} else {
|
||||
$upicon = $OUTPUT->spacer();
|
||||
}
|
||||
|
||||
if ($hasdown) {
|
||||
$downicon = html_writer::link(
|
||||
$this->get_action_url([
|
||||
'sesskey' => sesskey(),
|
||||
'action' => 'down',
|
||||
'plugin' => $row->plugininfo->name,
|
||||
]),
|
||||
$OUTPUT->pix_icon('t/down', get_string('movedown')),
|
||||
array_merge($dataattributes, ['data-direction' => 'down']),
|
||||
);
|
||||
} else {
|
||||
$downicon = $OUTPUT->spacer();
|
||||
}
|
||||
|
||||
// For now just add the up/down icons.
|
||||
return html_writer::span($upicon . $downicon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the settings column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_settings(stdClass $row): string {
|
||||
if ($settingsurl = $row->plugininfo->get_settings_url()) {
|
||||
return html_writer::link($settingsurl, get_string('settings'));
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Uninstall column content.
|
||||
*
|
||||
* @param stdClass $row
|
||||
* @return string
|
||||
*/
|
||||
protected function col_uninstall(stdClass $row): string {
|
||||
$status = $row->plugininfo->get_status();
|
||||
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_NEW) {
|
||||
return get_string('status_new', 'core_plugin');
|
||||
}
|
||||
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
$uninstall = get_string('status_missing', 'core_plugin') . '<br/>';
|
||||
} else {
|
||||
$uninstall = '';
|
||||
}
|
||||
|
||||
if ($uninstallurl = $this->pluginmanager->get_uninstall_url($row->plugin)) {
|
||||
$uninstall .= html_writer::link($uninstallurl, get_string('uninstallplugin', 'core_admin'));
|
||||
}
|
||||
|
||||
return $uninstall;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JS module used to manage this table.
|
||||
*
|
||||
* This should be a class which extends 'core_admin/plugin_management_table'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_table_js_module(): string {
|
||||
return 'core_admin/plugin_management_table';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add JS specific to this implementation.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_dynamic_table_html_end(): string {
|
||||
global $PAGE;
|
||||
|
||||
$PAGE->requires->js_call_amd($this->get_table_js_module(), 'init');
|
||||
return parent::get_dynamic_table_html_end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any class to add to the row.
|
||||
*
|
||||
* @param mixed $row
|
||||
* @return string
|
||||
*/
|
||||
protected function get_row_class($row): string {
|
||||
$plugininfo = $row->plugininfo;
|
||||
if ($plugininfo->get_status() === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$plugininfo->is_enabled()) {
|
||||
return 'dimmed_text';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function get_filterset_class(): string {
|
||||
return self::class . '_filterset';
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this plugin type supports the disabling of plugins.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function supports_disabling(): bool {
|
||||
return $this->plugininfoclass::plugintype_supports_disabling();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this table should show ordering fields.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function supports_ordering(): bool {
|
||||
return $this->plugininfoclass::plugintype_supports_ordering();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
/**
|
||||
* This file contains the dynamic interface.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class plugin_management_table_filterset extends \core_table\local\filter\filterset {
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_admin\table;
|
||||
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Tiny admin settings.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_plugin_management_table extends \core_admin\table\plugin_management_table {
|
||||
protected function get_plugintype(): string {
|
||||
return 'tool';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/tools.php')
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_column_list(): array {
|
||||
$columns = parent::get_column_list();
|
||||
|
||||
unset($columns['settings']);
|
||||
|
||||
return $columns;
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/admin/tool.php', $params);
|
||||
}
|
||||
}
|
||||
+55
-49
@@ -1,87 +1,95 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Allows admin to configure editors.
|
||||
* A page to manage editor plugins.
|
||||
*
|
||||
* @package core_admin
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @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.'/tablelib.php');
|
||||
require_once($CFG->libdir . '/adminlib.php');
|
||||
require_once($CFG->libdir . '/tablelib.php');
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$editor = required_param('editor', PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$plugin = required_param('plugin', PARAM_PLUGIN);
|
||||
|
||||
$PAGE->set_url('/admin/editors.php', array('action'=>$action, 'editor'=>$editor));
|
||||
$PAGE->set_url('/admin/editors.php', ['action' => $action, 'editor' => $plugin]);
|
||||
$PAGE->set_context(context_system::instance());
|
||||
|
||||
require_admin();
|
||||
require_sesskey();
|
||||
|
||||
$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=manageeditors";
|
||||
$returnurl = new moodle_url('/admin/settings.php', ['section' => 'manageeditors']);
|
||||
|
||||
// get currently installed and enabled auth plugins
|
||||
$available_editors = editors_get_available();
|
||||
if (!empty($editor) and empty($available_editors[$editor])) {
|
||||
redirect ($returnurl);
|
||||
}
|
||||
|
||||
$active_editors = explode(',', $CFG->texteditors);
|
||||
foreach ($active_editors as $key=>$active) {
|
||||
if (empty($available_editors[$active])) {
|
||||
unset($active_editors[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// process actions
|
||||
|
||||
if (!confirm_sesskey()) {
|
||||
// Get currently installed and enabled auth plugins.
|
||||
$availableeditors = editors_get_available();
|
||||
if (!empty($plugin) && empty($availableeditors[$plugin])) {
|
||||
redirect($returnurl);
|
||||
}
|
||||
|
||||
$return = true;
|
||||
$activeeditors = explode(',', $CFG->texteditors);
|
||||
foreach ($activeeditors as $key => $active) {
|
||||
if (empty($availableeditors[$active])) {
|
||||
unset($activeeditors[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
// Remove from enabled list.
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
|
||||
$class::enable_plugin($editor, false);
|
||||
$class::enable_plugin($plugin, false);
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
// Add to enabled list.
|
||||
if (!in_array($editor, $active_editors)) {
|
||||
if (!in_array($plugin, $activeeditors)) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('editor');
|
||||
$class::enable_plugin($editor, true);
|
||||
$class::enable_plugin($plugin, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'down':
|
||||
$key = array_search($editor, $active_editors);
|
||||
// check auth plugin is valid
|
||||
$key = array_search($plugin, $activeeditors);
|
||||
if ($key !== false) {
|
||||
// move down the list
|
||||
if ($key < (count($active_editors) - 1)) {
|
||||
$fsave = $active_editors[$key];
|
||||
$active_editors[$key] = $active_editors[$key + 1];
|
||||
$active_editors[$key + 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key + 1, $editor);
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
// Move down the list.
|
||||
if ($key < (count($activeeditors) - 1)) {
|
||||
$fsave = $activeeditors[$key];
|
||||
$activeeditors[$key] = $activeeditors[$key + 1];
|
||||
$activeeditors[$key + 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key + 1, $plugin);
|
||||
set_config('texteditors', implode(',', $activeeditors));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
$key = array_search($editor, $active_editors);
|
||||
// check auth is valid
|
||||
$key = array_search($plugin, $activeeditors);
|
||||
if ($key !== false) {
|
||||
// move up the list
|
||||
// Move up the list.
|
||||
if ($key >= 1) {
|
||||
$fsave = $active_editors[$key];
|
||||
$active_editors[$key] = $active_editors[$key - 1];
|
||||
$active_editors[$key - 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key - 1, $editor);
|
||||
set_config('texteditors', implode(',', $active_editors));
|
||||
$fsave = $activeeditors[$key];
|
||||
$activeeditors[$key] = $activeeditors[$key - 1];
|
||||
$activeeditors[$key - 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key - 1, $plugin);
|
||||
set_config('texteditors', implode(',', $activeeditors));
|
||||
core_plugin_manager::reset_caches();
|
||||
}
|
||||
}
|
||||
@@ -91,6 +99,4 @@ switch ($action) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
redirect ($returnurl);
|
||||
}
|
||||
redirect($returnurl);
|
||||
|
||||
+21
-28
@@ -23,14 +23,11 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define('NO_OUTPUT_BUFFERING', true);
|
||||
|
||||
require_once('../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$media = required_param('media', PARAM_PLUGIN);
|
||||
$confirm = optional_param('confirm', 0, PARAM_BOOL);
|
||||
$action = required_param('action', PARAM_ALPHANUMEXT);
|
||||
$plugin = required_param('plugin', PARAM_PLUGIN);
|
||||
|
||||
$PAGE->set_url('/admin/media.php');
|
||||
$PAGE->set_context(context_system::instance());
|
||||
@@ -38,42 +35,38 @@ $PAGE->set_context(context_system::instance());
|
||||
require_admin();
|
||||
require_sesskey();
|
||||
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
|
||||
$sortorder = array_values(\core\plugininfo\media::get_enabled_plugins());
|
||||
|
||||
$return = new moodle_url('/admin/settings.php', array('section' => 'managemediaplayers'));
|
||||
|
||||
if (!array_key_exists($media, $plugins)) {
|
||||
redirect($return);
|
||||
}
|
||||
$return = new moodle_url('/admin/settings.php', [
|
||||
'section' => 'managemediaplayers',
|
||||
]);
|
||||
|
||||
$displayname = get_string('pluginname', "media_{$plugin}");
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('media');
|
||||
$class::enable_plugin($media, false);
|
||||
if ($class::enable_plugin($plugin, false)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('media');
|
||||
$class::enable_plugin($media, true);
|
||||
if ($class::enable_plugin($plugin, true)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $displayname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'up':
|
||||
if (($pos = array_search($media, $sortorder)) > 0) {
|
||||
$tmp = $sortorder[$pos - 1];
|
||||
$sortorder[$pos - 1] = $sortorder[$pos];
|
||||
$sortorder[$pos] = $tmp;
|
||||
\core\plugininfo\media::set_enabled_plugins($sortorder);
|
||||
}
|
||||
$class::change_plugin_order($plugin, $class::MOVE_UP);
|
||||
break;
|
||||
|
||||
case 'down':
|
||||
if ((($pos = array_search($media, $sortorder)) !== false) && ($pos < count($sortorder) - 1)) {
|
||||
$tmp = $sortorder[$pos + 1];
|
||||
$sortorder[$pos + 1] = $sortorder[$pos];
|
||||
$sortorder[$pos] = $tmp;
|
||||
\core\plugininfo\media::set_enabled_plugins($sortorder);
|
||||
}
|
||||
$class::change_plugin_order($plugin, $class::MOVE_DOWN);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+21
-117
@@ -31,133 +31,37 @@ define('MODULE_TABLE', 'module_administration_table');
|
||||
|
||||
admin_externalpage_setup('managemodules');
|
||||
|
||||
$show = optional_param('show', '', PARAM_PLUGIN);
|
||||
$hide = optional_param('hide', '', PARAM_PLUGIN);
|
||||
|
||||
// Print headings.
|
||||
$stractivities = get_string("activities");
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
$strversion = get_string("version");
|
||||
$strhide = get_string("hide");
|
||||
$strshow = get_string("show");
|
||||
$strsettings = get_string("settings");
|
||||
$stractivities = get_string("activities");
|
||||
$stractivitymodule = get_string("activitymodule");
|
||||
$strshowmodulecourse = get_string('showmodulecourse');
|
||||
$plugin = optional_param('plugin', '', PARAM_PLUGIN);
|
||||
$action = optional_param('action', '', PARAM_ALPHA);
|
||||
|
||||
// If data submitted, then process and store.
|
||||
if (!empty($hide) && confirm_sesskey()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
if ($class::enable_plugin($hide, false)) {
|
||||
if (!empty($action) && !empty($plugin) && confirm_sesskey()) {
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
$pluginname = get_string('pluginname', $plugin);
|
||||
|
||||
if ($action === 'disable' && $manager::enable_plugin($plugin, 0)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
redirect(new moodle_url('/admin/modules.php'));
|
||||
}
|
||||
} else if ($action === 'enable' && $manager::enable_plugin($plugin, 1)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'core_admin', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
|
||||
if (!empty($show) && confirm_sesskey()) {
|
||||
$class = \core_plugin_manager::resolve_plugininfo_class('mod');
|
||||
if ($class::enable_plugin($show, true)) {
|
||||
// Settings not required - only pages.
|
||||
admin_get_root(true, false);
|
||||
}
|
||||
|
||||
// Redirect back to the modules page with out any params.
|
||||
redirect(new moodle_url('/admin/modules.php'));
|
||||
}
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($stractivities);
|
||||
|
||||
// Get and sort the existing modules.
|
||||
if (!$modules = $DB->get_records('modules', [], 'name ASC')) {
|
||||
throw new \moodle_exception('moduledoesnotexist', 'error');
|
||||
}
|
||||
|
||||
// Print the table of all modules.
|
||||
// Construct the flexible table ready to display.
|
||||
$table = new flexible_table(MODULE_TABLE);
|
||||
$table->define_columns(['name', 'instances', 'version', 'hideshow', 'uninstall', 'settings']);
|
||||
$table->define_headers([$stractivitymodule, $stractivities, $strversion, "$strhide/$strshow", $strsettings, $struninstall]);
|
||||
$table->define_baseurl($CFG->wwwroot . '/' . $CFG->admin . '/modules.php');
|
||||
$table->set_attribute('id', 'modules');
|
||||
$table->set_attribute('class', 'admintable generaltable');
|
||||
$table->setup();
|
||||
|
||||
$pluginmanager = core_plugin_manager::instance();
|
||||
|
||||
foreach ($modules as $module) {
|
||||
$plugininfo = $pluginmanager->get_plugin_info('mod_' . $module->name);
|
||||
$status = $plugininfo->get_status();
|
||||
|
||||
if ($status === core_plugin_manager::PLUGIN_STATUS_MISSING) {
|
||||
$strmodulename = '<span class="notifyproblem">' . $module->name . ' (' . get_string('missingfromdisk') . ')</span>';
|
||||
$missing = true;
|
||||
} else {
|
||||
$icon = "<img src=\"" . $OUTPUT->image_url('monologo', $module->name) . "\" class=\"icon\" alt=\"\" />";
|
||||
$strmodulename = $icon . ' ' . get_string('modulename', $module->name);
|
||||
$missing = false;
|
||||
}
|
||||
|
||||
$uninstall = '';
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('mod_' . $module->name, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
}
|
||||
|
||||
if (
|
||||
file_exists("$CFG->dirroot/mod/$module->name/settings.php") ||
|
||||
file_exists("$CFG->dirroot/mod/$module->name/settingstree.php")
|
||||
) {
|
||||
$settings = "<a href=\"settings.php?section=modsetting$module->name\">$strsettings</a>";
|
||||
} else {
|
||||
$settings = "";
|
||||
}
|
||||
|
||||
try {
|
||||
$count = $DB->count_records_select($module->name, "course<>0");
|
||||
} catch (dml_exception $e) {
|
||||
$count = -1;
|
||||
}
|
||||
if ($count > 0) {
|
||||
$countlink = $OUTPUT->action_link(
|
||||
new moodle_url('/course/search.php', ['modulelist' => $module->name]),
|
||||
$count,
|
||||
null,
|
||||
['title' => $strshowmodulecourse]
|
||||
);
|
||||
} else if ($count < 0) {
|
||||
$countlink = get_string('error');
|
||||
} else {
|
||||
$countlink = "$count";
|
||||
}
|
||||
|
||||
if ($missing) {
|
||||
$visible = '';
|
||||
$class = '';
|
||||
} else if ($module->visible) {
|
||||
$visible = "<a href=\"modules.php?hide=$module->name&sesskey=" . sesskey() . "\" title=\"$strhide\">" .
|
||||
$OUTPUT->pix_icon('t/hide', $strhide) . '</a>';
|
||||
$class = '';
|
||||
} else {
|
||||
$visible = "<a href=\"modules.php?show=$module->name&sesskey=" . sesskey() . "\" title=\"$strshow\">" .
|
||||
$OUTPUT->pix_icon('t/show', $strshow) . '</a>';
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
if ($module->name == "forum") {
|
||||
$uninstall = "";
|
||||
$visible = "";
|
||||
$class = "";
|
||||
}
|
||||
$version = get_config('mod_' . $module->name, 'version');
|
||||
|
||||
$table->add_data([
|
||||
$strmodulename,
|
||||
$countlink,
|
||||
$version,
|
||||
$visible,
|
||||
$settings,
|
||||
$uninstall,
|
||||
], $class);
|
||||
}
|
||||
|
||||
$table->finish_html();
|
||||
|
||||
echo $OUTPUT->heading(get_string("activities"));
|
||||
$table = new \core_admin\table\activity_management_table();
|
||||
$table->out();
|
||||
echo $OUTPUT->footer();
|
||||
|
||||
@@ -154,7 +154,12 @@ if ($hassiteconfig) {
|
||||
/// Editor plugins
|
||||
$ADMIN->add('modules', new admin_category('editorsettings', new lang_string('editors', 'editor')));
|
||||
$temp = new admin_settingpage('manageeditors', new lang_string('editorsettings', 'editor'));
|
||||
$temp->add(new admin_setting_manageeditors());
|
||||
$temp->add(new \core_admin\admin\admin_setting_plugin_manager(
|
||||
'editor',
|
||||
\core_admin\table\editor_management_table::class,
|
||||
'editorsui',
|
||||
get_string('editorsettings', 'editor'),
|
||||
));
|
||||
$ADMIN->add('editorsettings', $temp);
|
||||
$plugins = core_plugin_manager::instance()->get_plugins_of_type('editor');
|
||||
core_collator::asort_objects_by_property($plugins, 'displayname');
|
||||
@@ -273,7 +278,12 @@ if ($hassiteconfig) {
|
||||
$temp = new admin_settingpage('managemediaplayers', new lang_string('managemediaplayers', 'media'));
|
||||
$temp->add(new admin_setting_heading('mediaformats', get_string('mediaformats', 'core_media'),
|
||||
format_text(get_string('mediaformats_desc', 'core_media'), FORMAT_MARKDOWN)));
|
||||
$temp->add(new admin_setting_managemediaplayers());
|
||||
$temp->add(new \core_admin\admin\admin_setting_plugin_manager(
|
||||
'media',
|
||||
\core_admin\table\media_management_table::class,
|
||||
'managemediaplayers',
|
||||
new lang_string('managemediaplayers', 'core_media'),
|
||||
));
|
||||
$temp->add(new admin_setting_heading('managemediaplayerscommonheading', new lang_string('commonsettings', 'admin'), ''));
|
||||
$temp->add(new admin_setting_configtext('media_default_width',
|
||||
new lang_string('defaultwidth', 'core_media'), new lang_string('defaultwidthdesc', 'core_media'),
|
||||
@@ -723,8 +733,14 @@ if ($hassiteconfig) {
|
||||
/// Add all admin tools
|
||||
if ($hassiteconfig) {
|
||||
$ADMIN->add('modules', new admin_category('tools', new lang_string('tools', 'admin')));
|
||||
$ADMIN->add('tools', new admin_externalpage('managetools', new lang_string('toolsmanage', 'admin'),
|
||||
$CFG->wwwroot . '/' . $CFG->admin . '/tools.php'));
|
||||
$settingspage = new admin_settingpage('toolsmanagement', new lang_string('toolsmanage', 'admin'));
|
||||
$ADMIN->add('tools', $settingspage);
|
||||
$settingspage->add(new \core_admin\admin\admin_setting_plugin_manager(
|
||||
'tool',
|
||||
\core_admin\table\tool_plugin_management_table::class,
|
||||
'managetools',
|
||||
new lang_string('toolsmanage', 'admin')
|
||||
));
|
||||
}
|
||||
|
||||
// Now add various admin tools.
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
@core @core_admin
|
||||
Feature: An administrator can manage Block plugins
|
||||
In order to alter the user experience
|
||||
As an admin
|
||||
I can manage block plugins
|
||||
|
||||
@javascript
|
||||
Scenario: An administrator can control the enabled state of block plugins using JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
When I click on "Disable the Latest badges plugin" "link"
|
||||
Then I should see "The Latest badges plugin has been disabled"
|
||||
And "Disable the Latest badges plugin" "link" should not exist
|
||||
But "Enable the Latest badges plugin" "link" should exist
|
||||
When I click on "Enable the Latest badges plugin" "link"
|
||||
Then I should see "The Latest badges plugin has been enabled"
|
||||
And "Enable the Latest badges plugin" "link" should not exist
|
||||
But "Disable the Latest badges plugin" "link" should exist
|
||||
|
||||
Scenario: An administrator can control the enabled state of block plugins without JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
When I click on "Disable the Latest badges plugin" "link"
|
||||
Then I should see "The Latest badges plugin has been disabled"
|
||||
And "Disable the Latest badges plugin" "link" should not exist
|
||||
But "Enable the Latest badges plugin" "link" should exist
|
||||
When I click on "Enable the Latest badges plugin" "link"
|
||||
Then I should see "The Latest badges plugin has been enabled"
|
||||
And "Enable the Latest badges plugin" "link" should not exist
|
||||
But "Disable the Latest badges plugin" "link" should exist
|
||||
|
||||
@javascript
|
||||
Scenario: An administrator can control the protected state of block plugins using JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
When I click on "Protect instances of the Latest badges block" "link"
|
||||
Then I should see "The Latest badges block is now protected"
|
||||
And "Protect instances of the Latest badges block" "link" should not exist
|
||||
But "Unprotect instances of the Latest badges block" "link" should exist
|
||||
And "Protect instances of the Activities block" "link" should exist
|
||||
When I click on "Unprotect instances of the Latest badges block" "link"
|
||||
Then I should see "The Latest badges block is no longer protected"
|
||||
And "Unprotect instances of the Activities block" "link" should not exist
|
||||
But "Protect instances of the Latest badges block" "link" should exist
|
||||
And "Protect instances of the Activities block" "link" should exist
|
||||
|
||||
Scenario: An administrator can control the protected state of block plugins without JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
When I click on "Protect instances of the Latest badges block" "link"
|
||||
Then I should see "The Latest badges block is now protected"
|
||||
And "Protect instances of the Latest badges block" "link" should not exist
|
||||
But "Unprotect instances of the Latest badges block" "link" should exist
|
||||
And "Protect instances of the Activities block" "link" should exist
|
||||
When I click on "Unprotect instances of the Latest badges block" "link"
|
||||
Then I should see "The Latest badges block is no longer protected"
|
||||
And "Unprotect instances of the Activities block" "link" should not exist
|
||||
But "Protect instances of the Latest badges block" "link" should exist
|
||||
And "Protect instances of the Activities block" "link" should exist
|
||||
@@ -0,0 +1,30 @@
|
||||
@core @core_admin
|
||||
Feature: An administrator can manage Media plugins
|
||||
In order to alter the user experience
|
||||
As an admin
|
||||
I can manage media plugins
|
||||
|
||||
@javascript
|
||||
Scenario: An administrator can control the enabled state of media plugins using JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Media players > Manage media players" in site administration
|
||||
When I click on "Disable the YouTube plugin" "link"
|
||||
Then I should see "The YouTube plugin has been disabled"
|
||||
And "Disable the YouTube plugin" "link" should not exist
|
||||
But "Enable the YouTube plugin" "link" should exist
|
||||
When I click on "Enable the YouTube plugin" "link"
|
||||
Then I should see "The YouTube plugin has been enabled"
|
||||
And "Enable the YouTube plugin" "link" should not exist
|
||||
But "Disable the YouTube plugin" "link" should exist
|
||||
|
||||
Scenario: An administrator can control the enabled state of media plugins without JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Media players > Manage media players" in site administration
|
||||
When I click on "Disable the YouTube plugin" "link"
|
||||
Then I should see "The YouTube plugin has been disabled"
|
||||
And "Disable the YouTube plugin" "link" should not exist
|
||||
But "Enable the YouTube plugin" "link" should exist
|
||||
When I click on "Enable the YouTube plugin" "link"
|
||||
Then I should see "The YouTube plugin has been enabled"
|
||||
And "Enable the YouTube plugin" "link" should not exist
|
||||
But "Disable the YouTube plugin" "link" should exist
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||
|
||||
/**
|
||||
* Unit tests to test block protection changes.
|
||||
*
|
||||
* @package core
|
||||
* @covers \core_admin\external\set_block_protection
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_block_protection_test extends \externallib_advanced_testcase {
|
||||
/**
|
||||
* Test execute method with no login.
|
||||
*/
|
||||
public function test_execute_no_login(): void {
|
||||
$this->expectException(\require_login_exception::class);
|
||||
set_block_protection::execute('block_login', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method with no login.
|
||||
*/
|
||||
public function test_execute_no_capability(): void {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$this->expectException(\required_capability_exception::class);
|
||||
set_block_protection::execute('block_login', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the execute function with a range of parameters.
|
||||
*
|
||||
* @dataProvider execute_provider
|
||||
* @param string $block
|
||||
* @param int $targetstate
|
||||
* @param bool $isundeletable
|
||||
*/
|
||||
public function test_execute(
|
||||
string $block,
|
||||
int $targetstate,
|
||||
bool $isundeletable,
|
||||
): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
set_block_protection::execute($block, $targetstate);
|
||||
|
||||
$undeletable = \block_manager::get_undeletable_block_types();
|
||||
[, $pluginname] = explode('_', $block, 2);
|
||||
|
||||
if ($isundeletable) {
|
||||
$this->assertNotFalse(array_search($pluginname, $undeletable));
|
||||
} else {
|
||||
$this->assertFalse(array_search($pluginname, $undeletable));
|
||||
}
|
||||
$this->assertCount(1, \core\notification::fetch());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_execute.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function execute_provider(): array {
|
||||
return [
|
||||
[
|
||||
'block_login',
|
||||
1,
|
||||
true,
|
||||
],
|
||||
[
|
||||
'block_login',
|
||||
0,
|
||||
false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that an exception is thrown when the block does not exist.
|
||||
*/
|
||||
public function execute_block_does_not_exist(): void {
|
||||
$this->expectException(\dml_missing_record_exception::class);
|
||||
|
||||
set_block_protection::execute('fake_block', 1);
|
||||
$this->assertDebuggingCalledCount(1);
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||
|
||||
/**
|
||||
* Unit tests to configure the plugin order.
|
||||
*
|
||||
* Note: Not all plugins can be ordered, so this test is limited to those which support it.
|
||||
*
|
||||
* @package core
|
||||
* @covers \core_admin\external\set_plugin_state
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_plugin_order_test extends \externallib_advanced_testcase {
|
||||
/**
|
||||
* Text execute method for editor plugins, which support ordering.
|
||||
*
|
||||
* @dataProvider execute_editor_provider
|
||||
* @param string $initialstate The initial state of the plugintype
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int $direction
|
||||
* @param array $neworder
|
||||
* @param string $newstate
|
||||
*/
|
||||
public function test_execute_editors(
|
||||
string $initialstate,
|
||||
string $plugin,
|
||||
int $direction,
|
||||
array $neworder,
|
||||
string $newstate,
|
||||
): void {
|
||||
global $CFG;
|
||||
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$CFG->texteditors = $initialstate;
|
||||
|
||||
set_plugin_order::execute($plugin, $direction);
|
||||
|
||||
$this->assertSame(
|
||||
$neworder,
|
||||
array_keys(\core\plugininfo\editor::get_sorted_plugins()),
|
||||
);
|
||||
$this->assertSame($newstate, $CFG->texteditors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for base tests of the execute method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function execute_editor_provider(): array {
|
||||
return [
|
||||
[
|
||||
'initialstate' => 'textarea,tiny',
|
||||
'pluginname' => 'editor_textarea',
|
||||
1, // DOWN.
|
||||
'expected' => [
|
||||
'tiny',
|
||||
'textarea',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'tiny,textarea',
|
||||
],
|
||||
[
|
||||
'initialstate' => 'textarea,tiny',
|
||||
'pluginname' => 'editor_textarea',
|
||||
-1, // UP.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
[
|
||||
'initialstate' => 'textarea,tiny',
|
||||
'pluginname' => 'editor_tiny',
|
||||
1, // DOWN.
|
||||
// Tiny is already at the bottom of the list of enabled plugins.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
[
|
||||
'initialstate' => 'textarea,tiny',
|
||||
'pluginname' => 'editor_atto',
|
||||
1, // DOWN.
|
||||
// Atto is not enabled. Disabled editors are listed lexically after enabled editors.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Text execute method for plugins which do not support ordering.
|
||||
*
|
||||
* @dataProvider execute_non_orderable_provider
|
||||
* @param string $plugin
|
||||
*/
|
||||
public function test_execute_editors_non_orderable(string $plugin): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
$this->assertIsArray(set_plugin_order::execute($plugin, 1));
|
||||
}
|
||||
|
||||
public function execute_non_orderable_provider(): array {
|
||||
return [
|
||||
// Activities do not support ordering.
|
||||
['mod_assign'],
|
||||
// Nor to blocks.
|
||||
['block_login'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method with no login.
|
||||
*/
|
||||
public function test_execute_no_login(): void {
|
||||
$this->expectException(\require_login_exception::class);
|
||||
set_plugin_order::execute('editor_tiny', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method with no login.
|
||||
*/
|
||||
public function test_execute_no_capability(): void {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$this->expectException(\required_capability_exception::class);
|
||||
set_plugin_order::execute('editor_tiny', 1);
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core_admin\external;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
|
||||
|
||||
/**
|
||||
* Unit tests to configure the enabled/disabled state of a plugin.
|
||||
*
|
||||
* @package core
|
||||
* @covers \core_admin\external\set_plugin_state
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_plugin_state_test extends \externallib_advanced_testcase {
|
||||
/**
|
||||
* Text execute method.
|
||||
*
|
||||
* @dataProvider execute_standard_provider
|
||||
* @param string $plugin The name of the plugin
|
||||
* @param int|null $initialstate The initial state of the plugin
|
||||
* @param int $newstate The target state
|
||||
* @param int $notificationcount The number of notifications expected
|
||||
*/
|
||||
public function test_execute(
|
||||
string $plugin,
|
||||
?int $initialstate,
|
||||
int $newstate,
|
||||
int $notificationcount,
|
||||
): void {
|
||||
$this->resetAfterTest();
|
||||
$this->setAdminUser();
|
||||
|
||||
if ($initialstate !== null) {
|
||||
[$plugintype, $pluginname] = \core_component::normalize_component($plugin);
|
||||
$manager = \core_plugin_manager::resolve_plugininfo_class($plugintype);
|
||||
$manager::enable_plugin($pluginname, $initialstate);
|
||||
\core\notification::fetch();
|
||||
}
|
||||
|
||||
set_plugin_state::execute($plugin, $newstate);
|
||||
$this->assertCount($notificationcount, \core\notification::fetch());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for base tests of the execute method.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function execute_standard_provider(): array {
|
||||
$generatetestsfor = function (string $plugin): array {
|
||||
return [
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'initialstate' => null,
|
||||
'newstate' => 0,
|
||||
'notificationcount' => 1,
|
||||
],
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'initialstate' => 1,
|
||||
'newstate' => 0,
|
||||
'notificationcount' => 1,
|
||||
],
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'initialstate' => 1,
|
||||
'newstate' => 1,
|
||||
'notificationcount' => 0,
|
||||
],
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'initialstate' => 0,
|
||||
'newstate' => 0,
|
||||
'notificationcount' => 0,
|
||||
],
|
||||
[
|
||||
'plugin' => $plugin,
|
||||
'initialstate' => 0,
|
||||
'newstate' => 1,
|
||||
'notificationcount' => 1,
|
||||
],
|
||||
];
|
||||
};
|
||||
|
||||
return array_merge(
|
||||
$generatetestsfor('mod_assign'),
|
||||
$generatetestsfor('editor_tiny'),
|
||||
$generatetestsfor('tiny_h5p'),
|
||||
$generatetestsfor('block_badges'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method with no login.
|
||||
*/
|
||||
public function test_execute_no_login(): void {
|
||||
$this->expectException(\require_login_exception::class);
|
||||
set_plugin_state::execute('mod_assign', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test execute method with no login.
|
||||
*/
|
||||
public function test_execute_no_capability(): void {
|
||||
$this->resetAfterTest();
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
$this->expectException(\required_capability_exception::class);
|
||||
set_plugin_state::execute('mod_assign', 1);
|
||||
}
|
||||
}
|
||||
@@ -14,11 +14,11 @@ Feature: I can apply presets
|
||||
Scenario: Applying Starter Moodle preset changes status and settings
|
||||
# Checking the settings before applying Full Moodle preset (we're only testing one of each type).
|
||||
Given I navigate to "Plugins > Activity modules > Manage activities" in site administration
|
||||
And "Hide" "icon" should exist in the "Chat" "table_row"
|
||||
And "Disable the Chat plugin" "icon" should exist in the "Chat" "table_row"
|
||||
And I navigate to "Plugins > Availability restrictions > Manage restrictions" in site administration
|
||||
And "Hide" "icon" should exist in the "Restriction by grouping" "table_row"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
And "Hide" "icon" should exist in the "Logged in user" "table_row"
|
||||
And "Disable the Logged in user plugin" "icon" should exist in the "Logged in user" "table_row"
|
||||
And I navigate to "Plugins > Course formats > Manage course formats" in site administration
|
||||
And "Disable" "icon" should exist in the "Social format" "table_row"
|
||||
And I navigate to "Plugins > Question behaviours > Manage question behaviours" in site administration
|
||||
@@ -109,11 +109,11 @@ Feature: I can apply presets
|
||||
And the field "Enable badges" matches value "0"
|
||||
And the field "Enable competencies" matches value "0"
|
||||
And I navigate to "Plugins > Activity modules > Manage activities" in site administration
|
||||
And "Hide" "icon" should not exist in the "Chat" "table_row"
|
||||
And "Disable the Chat plugin" "icon" should not exist in the "Chat" "table_row"
|
||||
And I navigate to "Plugins > Availability restrictions > Manage restrictions" in site administration
|
||||
And "Hide" "icon" should not exist in the "Restriction by grouping" "table_row"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
And "Hide" "icon" should not exist in the "Logged in user" "table_row"
|
||||
And "Disable the Logged in user plugin" "icon" should not exist in the "Logged in user" "table_row"
|
||||
And I navigate to "Plugins > Course formats > Manage course formats" in site administration
|
||||
And "Disable" "icon" should not exist in the "Social format" "table_row"
|
||||
And I navigate to "Plugins > Question behaviours > Manage question behaviours" in site administration
|
||||
|
||||
@@ -20,11 +20,11 @@ Feature: I can revert changes after a load
|
||||
And the field "Enable badges" matches value "0"
|
||||
And the field "Enable competencies" matches value "0"
|
||||
And I navigate to "Plugins > Activity modules > Manage activities" in site administration
|
||||
And "Hide" "icon" should not exist in the "Chat" "table_row"
|
||||
And "Disable the Chat plugin" "icon" should not exist in the "Chat" "table_row"
|
||||
And I navigate to "Plugins > Availability restrictions > Manage restrictions" in site administration
|
||||
And "Hide" "icon" should not exist in the "Restriction by grouping" "table_row"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
And "Hide" "icon" should not exist in the "Logged in user" "table_row"
|
||||
And "Disable the Logged in user plugin" "icon" should not exist in the "Logged in user" "table_row"
|
||||
And I navigate to "Plugins > Course formats > Manage course formats" in site administration
|
||||
And "Disable" "icon" should not exist in the "Social format" "table_row"
|
||||
And I navigate to "Plugins > Question behaviours > Manage question behaviours" in site administration
|
||||
@@ -39,11 +39,11 @@ Feature: I can revert changes after a load
|
||||
Then the field "Enable badges" matches value "1"
|
||||
And the field "Enable competencies" matches value "1"
|
||||
And I navigate to "Plugins > Activity modules > Manage activities" in site administration
|
||||
And "Hide" "icon" should exist in the "Chat" "table_row"
|
||||
And "Disable the Chat plugin" "icon" should exist in the "Chat" "table_row"
|
||||
And I navigate to "Plugins > Availability restrictions > Manage restrictions" in site administration
|
||||
And "Hide" "icon" should exist in the "Restriction by grouping" "table_row"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
And "Hide" "icon" should exist in the "Logged in user" "table_row"
|
||||
And "Disable the Logged in user plugin" "icon" should exist in the "Logged in user" "table_row"
|
||||
And I navigate to "Plugins > Course formats > Manage course formats" in site administration
|
||||
And "Disable" "icon" should exist in the "Social format" "table_row"
|
||||
And I navigate to "Plugins > Question behaviours > Manage question behaviours" in site administration
|
||||
|
||||
@@ -23,15 +23,20 @@
|
||||
*/
|
||||
namespace tool_log\plugininfo;
|
||||
|
||||
use core\plugininfo\base, moodle_url, part_of_admin_tree, admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use core\plugininfo\base;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Plugin info class for logging store plugins.
|
||||
*/
|
||||
class logstore extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_enabled() {
|
||||
$enabled = get_config('tool_log', 'enabled_stores');
|
||||
if (!$enabled) {
|
||||
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Provides an overview of installed admin tools
|
||||
*
|
||||
* Displays the list of found admin tools, their version (if found) and
|
||||
* a link to uninstall the admin tool.
|
||||
*
|
||||
* The code is based on admin/localplugins.php by David Mudrak.
|
||||
*
|
||||
* @package admin
|
||||
* @copyright 2011 Petr Skoda {@link http://skodak.org}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->libdir.'/tablelib.php');
|
||||
|
||||
admin_externalpage_setup('managetools');
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading(get_string('tools', 'admin'));
|
||||
|
||||
/// Print the table of all installed tool plugins
|
||||
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
|
||||
$table = new flexible_table('toolplugins_administration_table');
|
||||
$table->define_columns(array('name', 'version', 'uninstall'));
|
||||
$table->define_headers(array(get_string('plugin'), get_string('version'), $struninstall));
|
||||
$table->define_baseurl($PAGE->url);
|
||||
$table->set_attribute('id', 'toolplugins');
|
||||
$table->set_attribute('class', 'admintable generaltable');
|
||||
$table->setup();
|
||||
|
||||
$plugins = array();
|
||||
foreach (core_component::get_plugin_list('tool') as $plugin => $plugindir) {
|
||||
if (get_string_manager()->string_exists('pluginname', 'tool_' . $plugin)) {
|
||||
$strpluginname = get_string('pluginname', 'tool_' . $plugin);
|
||||
} else {
|
||||
$strpluginname = $plugin;
|
||||
}
|
||||
$plugins[$plugin] = $strpluginname;
|
||||
}
|
||||
core_collator::asort($plugins);
|
||||
|
||||
$like = $DB->sql_like('plugin', '?', true, true, false, '|');
|
||||
$params = array('tool|_%');
|
||||
$installed = $DB->get_records_select('config_plugins', "$like AND name = 'version'", $params);
|
||||
$versions = array();
|
||||
foreach ($installed as $config) {
|
||||
$name = preg_replace('/^tool_/', '', $config->plugin);
|
||||
$versions[$name] = $config->value;
|
||||
if (!isset($plugins[$name])) {
|
||||
$plugins[$name] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($plugins as $plugin => $name) {
|
||||
$uninstall = '';
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('tool_'.$plugin, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
}
|
||||
|
||||
if (!isset($versions[$plugin])) {
|
||||
if (file_exists("$CFG->dirroot/$CFG->admin/tool/$plugin/version.php")) {
|
||||
// not installed yet
|
||||
$version = '?';
|
||||
} else {
|
||||
// no version info available
|
||||
$version = '-';
|
||||
}
|
||||
} else {
|
||||
$version = $versions[$plugin];
|
||||
if (file_exists("$CFG->dirroot/$CFG->admin/tool/$plugin")) {
|
||||
$version = $versions[$plugin];
|
||||
} else {
|
||||
// somebody removed plugin without uninstall
|
||||
$name = '<span class="notifyproblem">'.$name.' ('.get_string('missingfromdisk').')</span>';
|
||||
$version = $versions[$plugin];
|
||||
}
|
||||
}
|
||||
|
||||
$table->add_data(array($name, $version, $uninstall));
|
||||
}
|
||||
|
||||
$table->print_html();
|
||||
|
||||
echo $OUTPUT->footer();
|
||||
@@ -1,8 +1,8 @@
|
||||
@block @block_glossary_random @javascript @addablocklink
|
||||
Feature: Add the glossary random block when main feature is enabled
|
||||
In order to add the glossary random block to my course
|
||||
As a teacher
|
||||
It should be added to courses only if the glossary module is enabled.
|
||||
In order to add the glossary random block to my course
|
||||
As a teacher
|
||||
It should be added to courses only if the glossary module is enabled.
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
@@ -17,7 +17,7 @@ Feature: Add the glossary random block when main feature is enabled
|
||||
|
||||
Scenario: The glossary random block cannot be added when glossary module is disabled
|
||||
Given I navigate to "Plugins > Activity modules > Manage activities" in site administration
|
||||
And I click on "Hide" "icon" in the "Glossary" "table_row"
|
||||
And I click on "Disable the Glossary plugin" "icon" in the "Glossary" "table_row"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
When I click on "Add a block" "link"
|
||||
Then I should not see "Random glossary entry"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@block @block_glossary_random @javascript
|
||||
Feature: Add the glossary random block when main feature is disabled
|
||||
In order to add the glossary random block to my course
|
||||
As a teacher
|
||||
It should be added to courses only if the glossary module is enabled.
|
||||
In order to add the glossary random block to my course
|
||||
As a teacher
|
||||
It should be added to courses only if the glossary module is enabled.
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
@@ -14,7 +14,7 @@ Feature: Add the glossary random block when main feature is disabled
|
||||
Given I turn editing mode on
|
||||
And I add the "Random glossary entry" block
|
||||
When I navigate to "Plugins > Activity modules > Manage activities" in site administration
|
||||
And I click on "Hide" "icon" in the "Glossary" "table_row"
|
||||
And I click on "Disable the Glossary plugin" "icon" in the "Glossary" "table_row"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
Then I should see "Random glossary entry"
|
||||
|
||||
@@ -27,7 +27,7 @@ Feature: Add the glossary random block when main feature is disabled
|
||||
And I click on "Cancel" "button" in the "Delete block?" "dialogue"
|
||||
And I should see "Random glossary entry"
|
||||
When I navigate to "Plugins > Activity modules > Manage activities" in site administration
|
||||
And I click on "Hide" "icon" in the "Glossary" "table_row"
|
||||
And I click on "Disable the Glossary plugin" "icon" in the "Glossary" "table_row"
|
||||
And I am on "Course 1" course homepage with editing mode on
|
||||
And I open the "Random glossary entry" blocks action menu
|
||||
And I click on "Delete Random glossary entry block" "link" in the "Random glossary entry" "block"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
@block @block_tag_youtube
|
||||
Feature: Adding and configuring YouTube block
|
||||
In order to have the YouTube block used
|
||||
As a admin
|
||||
I need to add the YouTube block to the tags site page
|
||||
In order to have the YouTube block used
|
||||
As a admin
|
||||
I need to add the YouTube block to the tags site page
|
||||
|
||||
Background:
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Plugins > Blocks > Manage blocks" in site administration
|
||||
And I click on "Show" "icon" in the "YouTube" "table_row"
|
||||
And I click on "Enable the YouTube plugin" "icon" in the "YouTube" "table_row"
|
||||
|
||||
@javascript
|
||||
Scenario: Category options are not available (except default) in the block settings if the YouTube API key is not set.
|
||||
@@ -16,7 +16,7 @@ Feature: Adding and configuring YouTube block
|
||||
And I follow "Dashboard"
|
||||
And I turn editing mode on
|
||||
And the following config values are set as admin:
|
||||
| unaddableblocks | | theme_boost|
|
||||
| unaddableblocks | | theme_boost |
|
||||
# TODO MDL-57120 site "Tags" link not accessible without navigation block.
|
||||
And I add the "Navigation" block if not present
|
||||
And I click on "Site pages" "list_item" in the "Navigation" "block"
|
||||
@@ -38,7 +38,7 @@ Feature: Adding and configuring YouTube block
|
||||
And I follow "Dashboard"
|
||||
And I turn editing mode on
|
||||
And the following config values are set as admin:
|
||||
| unaddableblocks | | theme_boost|
|
||||
| unaddableblocks | | theme_boost |
|
||||
And I add the "Navigation" block if not present
|
||||
And I click on "Site pages" "list_item" in the "Navigation" "block"
|
||||
And I click on "Tags" "link" in the "Navigation" "block"
|
||||
|
||||
+11
-1
@@ -95,10 +95,13 @@ $string['blockediplist'] = 'Blocked IP List';
|
||||
$string['blockinstances'] = 'Instances';
|
||||
$string['blockmultiple'] = 'Multiple';
|
||||
$string['blockprotect'] = 'Protect instances';
|
||||
$string['blockprotectblock'] = 'Protect instances of the {$a} block';
|
||||
$string['blockprotected'] = 'The {$a} block is now protected';
|
||||
$string['blockprotect_help'] = 'If you lock a particular type of block, then no-one will be able to add or delete instances. (You can, of course, unlock again if you need to edit instances.)
|
||||
|
||||
This is intended to protect blocks like the navigation and settings which are very hard to get back if accidentally deleted.';
|
||||
$string['blockunprotect'] = 'Unprotect';
|
||||
$string['blockunprotectblock'] = 'Unprotect instances of the {$a} block';
|
||||
$string['blockunprotected'] = 'The {$a} block is no longer protected';
|
||||
$string['blocksettings'] = 'Manage blocks';
|
||||
$string['bloglevel'] = 'Blog visibility';
|
||||
$string['bookmarkadded'] = 'Bookmark added.';
|
||||
@@ -508,6 +511,7 @@ $string['devicedetectregexexpression'] = 'Regular expression';
|
||||
$string['devicedetectregexvalue'] = 'Return value';
|
||||
$string['devicetype'] = 'Device type';
|
||||
$string['disabled'] = 'Disabled';
|
||||
$string['disableplugin'] = 'Disable the {$a} plugin';
|
||||
$string['disableuserimages'] = 'Disable user profile images';
|
||||
$string['displayerrorswarning'] = 'Enabling the PHP setting <em>display_errors</em> is not recommended on production sites because some error messages may reveal sensitive information about your server.';
|
||||
$string['displayloginfailures'] = 'Display login failures';
|
||||
@@ -582,6 +586,7 @@ $string['enablegravatar_help'] = 'When enabled Moodle will attempt to fetch a us
|
||||
$string['enablemobilewebservice'] = 'Enable web services for mobile devices';
|
||||
$string['enablepdfexportfont'] = 'Enable PDF fonts';
|
||||
$string['enablepdfexportfont_desc'] = 'If your site has courses in different languages which need other fonts in generated PDF files, you can provide the option to set the font in the course settings. You need to specify available fonts in $CFG->pdfexportfont in config.php.';
|
||||
$string['enableplugin'] = 'Enable the {$a} plugin';
|
||||
$string['enablerecordcache'] = 'Enable record cache';
|
||||
$string['enablerssfeeds'] = 'Enable RSS feeds';
|
||||
$string['enablesearchareas'] = 'Enable search areas';
|
||||
@@ -992,6 +997,8 @@ $string['pleaserefreshregistration'] = 'Your site is registered. Registration la
|
||||
$string['pleaserefreshregistrationunknown'] = 'Your site has been registered but the registration date is unknown. Please update your registration using the \'Update registration\' button or ensure that the \'Site registration\' scheduled task is enabled so your registration is automatically updated.';
|
||||
$string['pleaserefreshregistrationnewdata'] = 'Registration information has been changed. Please confirm it using the \'Update registration\' button.';
|
||||
$string['plugin'] = 'Plugin';
|
||||
$string['plugin_disabled'] = 'The {$a} plugin has been disabled';
|
||||
$string['plugin_enabled'] = 'The {$a} plugin has been enabled';
|
||||
$string['plugins'] = 'Plugins';
|
||||
$string['pluginscheck'] = 'Plugin dependencies check';
|
||||
$string['pluginscheckfailed'] = 'Dependencies check failed for {$a->pluginslist}';
|
||||
@@ -1579,3 +1586,6 @@ $string['mediapluginswfnote'] = 'As a default security measure, normal users sho
|
||||
|
||||
// Deprecated since Moodle 4.1.
|
||||
$string['multilangforceold'] = 'Force old multilang syntax: <span> without the class="multilang" and <lang>';
|
||||
|
||||
// Deprecated since Moodle 4.2.
|
||||
$string['blockunprotect'] = 'Unprotect';
|
||||
|
||||
@@ -81,3 +81,4 @@ showlocks_help,core_grades
|
||||
showanalysisicon,core_grades
|
||||
showanalysisicon_desc,core_grades
|
||||
showanalysisicon_help,core_grades
|
||||
blockunprotect,core_admin
|
||||
|
||||
@@ -1663,6 +1663,7 @@ $string['pluginarea'] = 'Area';
|
||||
$string['plugindeletefiles'] = 'All data associated with the plugin \'{$a->name}\' has been deleted from the database. To prevent the plugin re-installing itself, you should now delete this directory from your server: {$a->directory}';
|
||||
$string['plugincheck'] = 'Plugins check';
|
||||
$string['pluginitemid'] = 'Item ID';
|
||||
$string['pluginmissingfromdisk'] = '{$a->name} (Missing from disk)';
|
||||
$string['pluginsetup'] = 'Setting up plugin tables';
|
||||
$string['policyaccept'] = 'I understand and agree';
|
||||
$string['policyagree'] = 'You must agree to this policy to continue using this site. Do you agree?';
|
||||
|
||||
@@ -7239,184 +7239,6 @@ class admin_setting_manageauths extends admin_setting {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Special class for authentication administration.
|
||||
*
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class admin_setting_manageeditors extends admin_setting {
|
||||
/**
|
||||
* Calls parent::__construct with specific arguments
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->nosave = true;
|
||||
parent::__construct('editorsui', get_string('editorsettings', 'editor'), '', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_setting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns true, does nothing
|
||||
*
|
||||
* @return true
|
||||
*/
|
||||
public function get_defaultsetting() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns '', does not write anything
|
||||
*
|
||||
* @return string Always returns ''
|
||||
*/
|
||||
public function write_setting($data) {
|
||||
// do not write any setting
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if $query is one of the available editors
|
||||
*
|
||||
* @param string $query The string to search for
|
||||
* @return bool Returns true if found, false if not
|
||||
*/
|
||||
public function is_related($query) {
|
||||
if (parent::is_related($query)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$editors_available = editors_get_available();
|
||||
foreach ($editors_available as $editor=>$editorstr) {
|
||||
if (strpos($editor, $query) !== false) {
|
||||
return true;
|
||||
}
|
||||
if (strpos(core_text::strtolower($editorstr), $query) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the XHTML to display the control
|
||||
*
|
||||
* @param string $data Unused
|
||||
* @param string $query
|
||||
* @return string
|
||||
*/
|
||||
public function output_html($data, $query='') {
|
||||
global $CFG, $OUTPUT;
|
||||
|
||||
// display strings
|
||||
$txt = get_strings(array('administration', 'settings', 'edit', 'name', 'enable', 'disable',
|
||||
'up', 'down', 'none'));
|
||||
$struninstall = get_string('uninstallplugin', 'core_admin');
|
||||
|
||||
$txt->updown = "$txt->up/$txt->down";
|
||||
|
||||
$editors_available = editors_get_available();
|
||||
$active_editors = explode(',', $CFG->texteditors);
|
||||
|
||||
$active_editors = array_reverse($active_editors);
|
||||
foreach ($active_editors as $key=>$editor) {
|
||||
if (empty($editors_available[$editor])) {
|
||||
unset($active_editors[$key]);
|
||||
} else {
|
||||
$name = $editors_available[$editor];
|
||||
unset($editors_available[$editor]);
|
||||
$editors_available[$editor] = $name;
|
||||
}
|
||||
}
|
||||
if (empty($active_editors)) {
|
||||
//$active_editors = array('textarea');
|
||||
}
|
||||
$editors_available = array_reverse($editors_available, true);
|
||||
$return = $OUTPUT->heading(get_string('acteditorshhdr', 'editor'), 3, 'main', true);
|
||||
$return .= $OUTPUT->box_start('generalbox editorsui');
|
||||
|
||||
$table = new html_table();
|
||||
$table->head = array($txt->name, $txt->enable, $txt->updown, $txt->settings, $struninstall);
|
||||
$table->colclasses = array('leftalign', 'centeralign', 'centeralign', 'centeralign', 'centeralign');
|
||||
$table->id = 'editormanagement';
|
||||
$table->attributes['class'] = 'admintable generaltable';
|
||||
$table->data = array();
|
||||
|
||||
// iterate through auth plugins and add to the display table
|
||||
$updowncount = 1;
|
||||
$editorcount = count($active_editors);
|
||||
$url = "editors.php?sesskey=" . sesskey();
|
||||
foreach ($editors_available as $editor => $name) {
|
||||
// hide/show link
|
||||
$class = '';
|
||||
if (in_array($editor, $active_editors)) {
|
||||
$hideshow = "<a href=\"$url&action=disable&editor=$editor\">";
|
||||
$hideshow .= $OUTPUT->pix_icon('t/hide', get_string('disable')) . '</a>';
|
||||
$enabled = true;
|
||||
$displayname = $name;
|
||||
}
|
||||
else {
|
||||
$hideshow = "<a href=\"$url&action=enable&editor=$editor\">";
|
||||
$hideshow .= $OUTPUT->pix_icon('t/show', get_string('enable')) . '</a>';
|
||||
$enabled = false;
|
||||
$displayname = $name;
|
||||
$class = 'dimmed_text';
|
||||
}
|
||||
|
||||
// up/down link (only if auth is enabled)
|
||||
$updown = '';
|
||||
if ($enabled) {
|
||||
if ($updowncount > 1) {
|
||||
$updown .= "<a href=\"$url&action=up&editor=$editor\">";
|
||||
$updown .= $OUTPUT->pix_icon('t/up', get_string('moveup')) . '</a> ';
|
||||
}
|
||||
else {
|
||||
$updown .= $OUTPUT->spacer() . ' ';
|
||||
}
|
||||
if ($updowncount < $editorcount) {
|
||||
$updown .= "<a href=\"$url&action=down&editor=$editor\">";
|
||||
$updown .= $OUTPUT->pix_icon('t/down', get_string('movedown')) . '</a> ';
|
||||
}
|
||||
else {
|
||||
$updown .= $OUTPUT->spacer() . ' ';
|
||||
}
|
||||
++ $updowncount;
|
||||
}
|
||||
|
||||
// settings link
|
||||
if (file_exists($CFG->dirroot.'/lib/editor/'.$editor.'/settings.php')) {
|
||||
$eurl = new moodle_url('/admin/settings.php', array('section'=>'editorsettings'.$editor));
|
||||
$settings = "<a href='$eurl'>{$txt->settings}</a>";
|
||||
} else {
|
||||
$settings = '';
|
||||
}
|
||||
|
||||
$uninstall = '';
|
||||
if ($uninstallurl = core_plugin_manager::instance()->get_uninstall_url('editor_'.$editor, 'manage')) {
|
||||
$uninstall = html_writer::link($uninstallurl, $struninstall);
|
||||
}
|
||||
|
||||
// Add a row to the table.
|
||||
$row = new html_table_row(array($displayname, $hideshow, $updown, $settings, $uninstall));
|
||||
if ($class) {
|
||||
$row->attributes['class'] = $class;
|
||||
}
|
||||
$table->data[] = $row;
|
||||
}
|
||||
$return .= html_writer::table($table);
|
||||
$return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
|
||||
$return .= $OUTPUT->box_end();
|
||||
return highlight($query, $return);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Special class for antiviruses administration.
|
||||
*
|
||||
|
||||
@@ -23,10 +23,9 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for Antiviruses
|
||||
@@ -36,6 +35,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class antivirus extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -23,14 +23,19 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage, admin_externalpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for authentication plugins
|
||||
*/
|
||||
class auth extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
global $DB;
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ namespace core\plugininfo;
|
||||
|
||||
use admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class for availability plugins.
|
||||
*
|
||||
@@ -35,6 +33,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class availability extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function get_enabled_plugins() {
|
||||
global $DB;
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use core_component, core_plugin_manager, moodle_url, coding_exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use coding_exception;
|
||||
use core_component;
|
||||
use core_plugin_manager;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Base class providing access to the information about a plugin
|
||||
@@ -71,6 +71,21 @@ abstract class base {
|
||||
/** @var array|null array of {@link \core\update\info} for this plugin */
|
||||
protected $availableupdates;
|
||||
|
||||
/** @var int Move a plugin up in the plugin order */
|
||||
public const MOVE_UP = -1;
|
||||
|
||||
/** @var int Move a plugin down in the plugin order */
|
||||
public const MOVE_DOWN = 1;
|
||||
|
||||
/**
|
||||
* Whether this plugintype supports its plugins being disabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
@@ -656,4 +671,39 @@ abstract class base {
|
||||
'return' => $return,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this plugintype supports ordering of plugins using native functionality.
|
||||
*
|
||||
* Please note that plugintypes which pre-date this native functionality may still support ordering
|
||||
* but will not use the built-in functionality.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function plugintype_supports_ordering(): bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
*
|
||||
* @param bool $enabledonly Show all plugins, or only those which are enabled
|
||||
* @return array|null of sorted plugins $pluginname => $pluginname, null means unknown
|
||||
*/
|
||||
public static function get_sorted_plugins(bool $enabledonly = false): ?array {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the order of the plugin relative to other plugins in the plugintype.
|
||||
*
|
||||
* When possible, the change will be stored into the config_log table, to let admins check when/who has modified it.
|
||||
*
|
||||
* @param string $pluginname The plugin name to enable/disable.
|
||||
* @param int $direction The direction to move the plugin. Negative numbers mean up, Positive mean down.
|
||||
* @return bool Whether $pluginname has been updated or not.
|
||||
*/
|
||||
public static function change_plugin_order(string $pluginname, int $direction): bool {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,19 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage, admin_externalpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for page side blocks
|
||||
*/
|
||||
class block extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class for contentbank plugins
|
||||
*
|
||||
@@ -34,6 +32,9 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class contenttype extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if there should be a way to uninstall the plugin via the administration UI.
|
||||
|
||||
@@ -23,10 +23,8 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url;
|
||||
use admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Class for admin tool plugins
|
||||
@@ -37,6 +35,10 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class customfield extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow uninstall
|
||||
* @return bool
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage, admin_externalpage, core_plugin_manager;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use core_plugin_manager;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for dataformats
|
||||
@@ -36,6 +37,10 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class dataformat extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display name
|
||||
*/
|
||||
|
||||
@@ -23,15 +23,19 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for HTML editors
|
||||
*/
|
||||
class editor extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
@@ -133,4 +137,76 @@ class editor extends base {
|
||||
public static function get_manage_url() {
|
||||
return new moodle_url('/admin/settings.php', array('section'=>'manageeditors'));
|
||||
}
|
||||
|
||||
public static function plugintype_supports_ordering(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function get_sorted_plugins(bool $enabledonly = false): ?array {
|
||||
global $CFG;
|
||||
|
||||
$pluginmanager = \core_plugin_manager::instance();
|
||||
$plugins = $pluginmanager->get_plugins_of_type('editor');
|
||||
|
||||
// The Editor list is stored in an ordered string.
|
||||
$activeeditors = explode(',', $CFG->texteditors);
|
||||
|
||||
$sortedplugins = [];
|
||||
foreach ($activeeditors as $editor) {
|
||||
if (isset($plugins[$editor])) {
|
||||
$sortedplugins[$editor] = $plugins[$editor];
|
||||
unset($plugins[$editor]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($enabledonly) {
|
||||
return $sortedplugins;
|
||||
}
|
||||
|
||||
// Sort the rest of the plugins lexically.
|
||||
uasort($plugins, function ($a, $b) {
|
||||
return strnatcasecmp($a->name, $b->name);
|
||||
});
|
||||
|
||||
return array_merge(
|
||||
$sortedplugins,
|
||||
$plugins,
|
||||
);
|
||||
}
|
||||
|
||||
public static function change_plugin_order(string $pluginname, int $direction): bool {
|
||||
$activeeditors = array_keys(self::get_sorted_plugins(true));
|
||||
$key = array_search($pluginname, $activeeditors);
|
||||
|
||||
if ($key === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($direction === self::MOVE_DOWN) {
|
||||
// Move down the list.
|
||||
if ($key < (count($activeeditors) - 1)) {
|
||||
$fsave = $activeeditors[$key];
|
||||
$activeeditors[$key] = $activeeditors[$key + 1];
|
||||
$activeeditors[$key + 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key + 1, $pluginname);
|
||||
set_config('texteditors', implode(',', $activeeditors));
|
||||
\core_plugin_manager::reset_caches();
|
||||
|
||||
return true;
|
||||
}
|
||||
} else if ($direction === self::MOVE_UP) {
|
||||
if ($key >= 1) {
|
||||
$fsave = $activeeditors[$key];
|
||||
$activeeditors[$key] = $activeeditors[$key - 1];
|
||||
$activeeditors[$key - 1] = $fsave;
|
||||
add_to_config_log('editor_position', $key, $key - 1, $pluginname);
|
||||
set_config('texteditors', implode(',', $activeeditors));
|
||||
\core_plugin_manager::reset_caches();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,15 +23,21 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage, admin_externalpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for enrolment plugins
|
||||
*/
|
||||
class enrol extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
*/
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class for document converter plugins
|
||||
*
|
||||
@@ -34,6 +32,10 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class fileconverter extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should there be a way to uninstall the plugin via the administration UI.
|
||||
*
|
||||
|
||||
@@ -23,15 +23,19 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage, admin_externalpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for text filters
|
||||
*/
|
||||
class filter extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function init_display_name() {
|
||||
if (!get_string_manager()->string_exists('filtername', $this->component)) {
|
||||
$this->displayname = '[filtername,' . $this->component . ']';
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class for media plugins
|
||||
*
|
||||
@@ -34,6 +32,10 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class media extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
@@ -202,4 +204,66 @@ class media extends base {
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function plugintype_supports_ordering(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
public static function get_sorted_plugins(bool $enabledonly = false): ?array {
|
||||
$pluginmanager = \core_plugin_manager::instance();
|
||||
|
||||
$plugins = $pluginmanager->get_plugins_of_type('media');
|
||||
$enabledplugins = $pluginmanager->get_enabled_plugins('media');
|
||||
|
||||
// Sort plugins so enabled plugins are displayed first and all others are displayed in the end sorted by rank.
|
||||
\core_collator::asort_objects_by_method($plugins, 'get_rank', \core_collator::SORT_NUMERIC);
|
||||
|
||||
$order = array_values($enabledplugins);
|
||||
if (!$enabledonly) {
|
||||
$order = array_merge($order, array_diff(array_reverse(array_keys($plugins)), $order));
|
||||
}
|
||||
|
||||
$sortedplugins = [];
|
||||
foreach ($order as $name) {
|
||||
$sortedplugins[$name] = $plugins[$name];
|
||||
}
|
||||
|
||||
return $sortedplugins;
|
||||
}
|
||||
|
||||
public static function change_plugin_order(string $pluginname, int $direction): bool {
|
||||
$activeeditors = array_keys(self::get_sorted_plugins(true));
|
||||
$key = array_search($pluginname, $activeeditors);
|
||||
[$media] = explode('_', $pluginname, 2);
|
||||
|
||||
if ($key === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sortorder = array_values(self::get_enabled_plugins());
|
||||
|
||||
if ($direction === self::MOVE_DOWN) {
|
||||
// Move down the list.
|
||||
if ((($pos = array_search($media, $sortorder)) !== false) && ($pos < count($sortorder) - 1)) {
|
||||
$tmp = $sortorder[$pos + 1];
|
||||
$sortorder[$pos + 1] = $sortorder[$pos];
|
||||
$sortorder[$pos] = $tmp;
|
||||
self::set_enabled_plugins($sortorder);
|
||||
|
||||
return true;
|
||||
}
|
||||
} else if ($direction === self::MOVE_UP) {
|
||||
if (($pos = array_search($media, $sortorder)) > 0) {
|
||||
$tmp = $sortorder[$pos - 1];
|
||||
$sortorder[$pos - 1] = $sortorder[$pos];
|
||||
$sortorder[$pos] = $tmp;
|
||||
self::set_enabled_plugins($sortorder);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,19 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for messaging processors
|
||||
*/
|
||||
class message extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -23,14 +23,19 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for activity modules
|
||||
*/
|
||||
class mod extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
namespace core\plugininfo;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Payment gateway subplugin info class.
|
||||
*
|
||||
@@ -33,6 +31,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class paygw extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,14 +23,17 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use core_component, core_plugin_manager, moodle_url, coding_exception;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Class for portfolios
|
||||
*/
|
||||
class portfolio extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
|
||||
namespace core\plugininfo;
|
||||
|
||||
use qbank_columnsortorder\column_manager;
|
||||
|
||||
/**
|
||||
* Base class for qbank plugins.
|
||||
*
|
||||
@@ -37,6 +35,10 @@ use qbank_columnsortorder\column_manager;
|
||||
*/
|
||||
class qbank extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed(): bool {
|
||||
if (in_array($this->name, \core_plugin_manager::standard_plugins_list('qbank'))) {
|
||||
return false;
|
||||
|
||||
@@ -23,14 +23,18 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, core_plugin_manager;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use core_plugin_manager;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Class for question behaviours.
|
||||
*/
|
||||
class qbehaviour extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -23,14 +23,20 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_settingpage, core_plugin_manager;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use core_plugin_manager;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for question types
|
||||
*/
|
||||
class qtype extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use moodle_url, part_of_admin_tree, admin_externalpage;
|
||||
use admin_externalpage;
|
||||
use moodle_url;
|
||||
use part_of_admin_tree;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
require_once($CFG->dirroot . '/repository/lib.php');
|
||||
@@ -42,6 +44,10 @@ class repository extends base {
|
||||
/** @var int Repository state, when it's disabled. */
|
||||
public const REPOSITORY_DISABLED = -1;
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -23,14 +23,18 @@
|
||||
*/
|
||||
namespace core\plugininfo;
|
||||
|
||||
use part_of_admin_tree, admin_settingpage;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
use admin_settingpage;
|
||||
use part_of_admin_tree;
|
||||
|
||||
/**
|
||||
* Class for webservice protocols
|
||||
*/
|
||||
class webservice extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array of enabled plugins $pluginname => $pluginname
|
||||
|
||||
@@ -2953,6 +2953,24 @@ $functions = array(
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
],
|
||||
'core_admin_set_plugin_state' => [
|
||||
'classname' => 'core_admin\external\set_plugin_state',
|
||||
'description' => 'Set the state of a plugin',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
],
|
||||
'core_admin_set_plugin_order' => [
|
||||
'classname' => 'core_admin\external\set_plugin_order',
|
||||
'description' => 'Set the order of a plugin',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
],
|
||||
'core_admin_set_block_protection' => [
|
||||
'classname' => 'core_admin\external\set_block_protection',
|
||||
'description' => 'Set the protection state for a block plugin',
|
||||
'type' => 'write',
|
||||
'ajax' => true,
|
||||
],
|
||||
);
|
||||
|
||||
$services = array(
|
||||
|
||||
@@ -41,17 +41,17 @@ class manager {
|
||||
array $fpoptions = [],
|
||||
?editor $editor = null
|
||||
): array {
|
||||
$disabledplugins = $this->get_disabled_plugins();
|
||||
|
||||
// Get the list of plugins.
|
||||
// Note: Disabled plugins are already removed from this list.
|
||||
$plugins = $this->get_shipped_plugins();
|
||||
|
||||
// Fetch configuration for Moodle plugins.
|
||||
$moodleplugins = \core_component::get_plugin_list_with_class('tiny', 'plugininfo');
|
||||
$enabledplugins = \editor_tiny\plugininfo\tiny::get_enabled_plugins();
|
||||
foreach ($moodleplugins as $plugin => $classname) {
|
||||
if (in_array($plugin, $disabledplugins) || in_array("{$plugin}/plugin", $disabledplugins)) {
|
||||
// Skip getting data for disabled plugins.
|
||||
[, $pluginname] = explode('_', $plugin, 2);
|
||||
if (!in_array($pluginname, $enabledplugins)) {
|
||||
// This plugin has been disabled.
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -75,10 +75,6 @@ class manager {
|
||||
$editor
|
||||
);
|
||||
|
||||
if (!empty($config)) {
|
||||
$plugininfo['config'] = $config;
|
||||
}
|
||||
|
||||
// We suffix the plugin name for Moodle plugins with /plugin to avoid conflicts with Tiny plugins.
|
||||
$plugins["{$plugin}/plugin"] = $plugininfo;
|
||||
}
|
||||
@@ -190,7 +186,7 @@ class manager {
|
||||
$plugins = $this->get_shipped_plugins();
|
||||
$plugins += $this->get_moodle_plugins();
|
||||
|
||||
$disabledplugins = $this->get_disabled_plugins();
|
||||
$disabledplugins = $this->get_disabled_tinymce_plugins();
|
||||
$plugins = array_filter($plugins, function ($plugin) use ($disabledplugins) {
|
||||
return !in_array($plugin, $disabledplugins);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
@@ -216,8 +212,8 @@ class manager {
|
||||
$plugins += $this->get_premium_plugins();
|
||||
}
|
||||
|
||||
$disabledplugins = $this->get_disabled_plugins();
|
||||
return array_filter($plugins, function($plugin) use ($disabledplugins) {
|
||||
$disabledplugins = $this->get_disabled_tinymce_plugins();
|
||||
return array_filter($plugins, function ($plugin) use ($disabledplugins) {
|
||||
return !in_array($plugin, $disabledplugins);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
}
|
||||
@@ -480,11 +476,13 @@ class manager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of the disabled plugins.
|
||||
* Get a list of the built-in TinyMCE plugins which we want to disable.
|
||||
*
|
||||
* These are usually disabled because we have replaced them, or they are not compatible with Moodle in some way.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function get_disabled_plugins(): array {
|
||||
protected function get_disabled_tinymce_plugins(): array {
|
||||
return [
|
||||
// Disable the image and media plugins.
|
||||
// These are not generally compatible with Moodle.
|
||||
|
||||
@@ -27,6 +27,10 @@ use moodle_url;
|
||||
*/
|
||||
class tiny extends \core\plugininfo\base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* These subplugins can be uninstalled.
|
||||
*
|
||||
@@ -94,6 +98,53 @@ class tiny extends \core\plugininfo\base {
|
||||
* @return null|string the settings section name.
|
||||
*/
|
||||
public function get_settings_section_name(): ?string {
|
||||
if (!file_exists($this->full_path('settings.php'))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return "tiny_{$this->name}_settings";
|
||||
}
|
||||
|
||||
public static function get_enabled_plugins(): array {
|
||||
$pluginmanager = \core_plugin_manager::instance();
|
||||
$plugins = $pluginmanager->get_installed_plugins('tiny');
|
||||
|
||||
if (!$plugins) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Filter to return only enabled plugins.
|
||||
$enabled = [];
|
||||
foreach (array_keys($plugins) as $pluginname) {
|
||||
$disabled = get_config("tiny_{$pluginname}", 'disabled');
|
||||
if (empty($disabled)) {
|
||||
$enabled[$pluginname] = $pluginname;
|
||||
}
|
||||
}
|
||||
return $enabled;
|
||||
}
|
||||
|
||||
public static function enable_plugin(string $plugin, int $enabled): bool {
|
||||
$pluginname = "tiny_{$plugin}";
|
||||
|
||||
$oldvalue = !empty(get_config($pluginname, 'disabled'));
|
||||
$disabled = empty($enabled);
|
||||
$haschanged = false;
|
||||
|
||||
// Only set value if there is no config setting or if the value is different from the previous one.
|
||||
if (!$oldvalue && $disabled) {
|
||||
set_config('disabled', $disabled, $pluginname);
|
||||
$haschanged = true;
|
||||
} else if ($oldvalue && !$disabled) {
|
||||
unset_config('disabled', $pluginname);
|
||||
$haschanged = true;
|
||||
}
|
||||
|
||||
if ($haschanged) {
|
||||
add_to_config_log('disabled', $oldvalue, $disabled, $pluginname);
|
||||
\core_plugin_manager::reset_caches();
|
||||
}
|
||||
|
||||
return $haschanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace editor_tiny\table;
|
||||
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Tiny admin settings.
|
||||
*
|
||||
* @package editor_tiny
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class plugin_management_table extends \core_admin\table\plugin_management_table {
|
||||
protected function get_plugintype(): string {
|
||||
return 'tiny';
|
||||
}
|
||||
|
||||
public function guess_base_url(): void {
|
||||
$this->define_baseurl(
|
||||
new moodle_url('/admin/settings.php', ['section' => 'editorsettingstiny'])
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_action_url(array $params = []): moodle_url {
|
||||
return new moodle_url('/lib/editor/tiny/subplugins.php', $params);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,8 @@ $string['settings'] = 'General settings';
|
||||
$string['privacy:reason'] = 'The TinyMCE editor does not store any preferences or user data.';
|
||||
$string['branding'] = 'TinyMCE branding';
|
||||
$string['branding_desc'] = 'Support TinyMCE by displaying the logo in the bottom corner of the text editor. The logo links to the TinyMCE website.';
|
||||
$string['plugin_enabled'] = 'The {$a} plugin has been enabled.';
|
||||
$string['plugin_disabled'] = 'The {$a} plugin has been disabled.';
|
||||
$string['tiny:hash'] = '#';
|
||||
$string['tiny:accessibility'] = 'Accessibility';
|
||||
$string['tiny:action'] = 'Action';
|
||||
|
||||
@@ -27,6 +27,13 @@ defined('MOODLE_INTERNAL') || die;
|
||||
$ADMIN->add('editorsettings', new admin_category('editortiny', $editor->displayname, $editor->is_enabled() === false));
|
||||
|
||||
$settings = new admin_settingpage('editorsettingstiny', new lang_string('settings', 'editor_tiny'));
|
||||
$settings->add(new \core_admin\admin\admin_setting_plugin_manager(
|
||||
'tiny',
|
||||
\editor_tiny\table\plugin_management_table::class,
|
||||
'editor_tiny_settings',
|
||||
get_string('editorsettings', 'editor'),
|
||||
));
|
||||
|
||||
if ($ADMIN->fulltree) {
|
||||
$setting = new admin_setting_configcheckbox(
|
||||
'editor_tiny/branding',
|
||||
@@ -38,15 +45,15 @@ if ($ADMIN->fulltree) {
|
||||
$settings->add($setting);
|
||||
}
|
||||
|
||||
// Note: We add editortiny to the settings page here manually rather than deferring to the plugininfo class.
|
||||
// This ensures that it shows in the category list too.
|
||||
$ADMIN->add('editortiny', $settings);
|
||||
|
||||
foreach (core_plugin_manager::instance()->get_plugins_of_type('tiny') as $plugin) {
|
||||
/** @var \editor_tiny\plugininfo\tiny $plugin */
|
||||
$plugin->load_settings($ADMIN, 'editortiny', $hassiteconfig);
|
||||
}
|
||||
|
||||
// Note: We add editortiny to the settings page here manually rather than deferring to the plugininfo class.
|
||||
// This ensures that it shows in the category list too.
|
||||
$ADMIN->add('editortiny', $settings);
|
||||
|
||||
// Required or the editor plugininfo will add this section twice.
|
||||
unset($settings);
|
||||
$settings = null;
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Tiny subplugin management.
|
||||
*
|
||||
* @package editor_tinymce
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require(__DIR__ . '/../../../config.php');
|
||||
require_once("{$CFG->libdir}/adminlib.php");
|
||||
|
||||
$action = optional_param('action', '', PARAM_ALPHA);
|
||||
$plugin = optional_param('plugin', '', PARAM_PLUGIN);
|
||||
|
||||
$PAGE->set_context(context_system::instance());
|
||||
$PAGE->set_url('/lib/editor/tinymce/subplugins.php');
|
||||
|
||||
require_login();
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
require_sesskey();
|
||||
|
||||
$tinymanager = \core_plugin_manager::resolve_plugininfo_class('tiny');
|
||||
$pluginname = get_string('pluginname', "tiny_{$plugin}");
|
||||
|
||||
switch ($action) {
|
||||
case 'disable':
|
||||
if ($tinymanager::enable_plugin($plugin, 0)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_disabled', 'editor_tiny', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'enable':
|
||||
if ($tinymanager::enable_plugin($plugin, 1)) {
|
||||
\core\notification::add(
|
||||
get_string('plugin_enabled', 'editor_tiny', $pluginname),
|
||||
\core\notification::SUCCESS
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
redirect(new moodle_url('/admin/settings.php', [
|
||||
'section' => 'editorsettingstiny',
|
||||
]));
|
||||
@@ -0,0 +1,30 @@
|
||||
@core @core_admin
|
||||
Feature: An administrator can manage TinyMCE subplugins
|
||||
In order to alter the user experience
|
||||
As an admin
|
||||
I can manage TinyMCE subplugins
|
||||
|
||||
@javascript
|
||||
Scenario: An administrator can control the enabled state of TinyMCE subplugins using JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Text editors > TinyMCE editor > General settings" in site administration
|
||||
When I click on "Disable the Tiny equation editor plugin" "link"
|
||||
Then I should see "The Tiny equation editor plugin has been disabled"
|
||||
And "Disable the Tiny equation editor plugin" "link" should not exist
|
||||
But "Enable the Tiny equation editor plugin" "link" should exist
|
||||
When I click on "Enable the Tiny equation editor plugin" "link"
|
||||
Then I should see "The Tiny equation editor plugin has been enabled"
|
||||
And "Enable the Tiny equation editor plugin" "link" should not exist
|
||||
But "Disable the Tiny equation editor plugin" "link" should exist
|
||||
|
||||
Scenario: An administrator can control the enabled state of TinyMCE subplugins without JavaScript
|
||||
Given I am logged in as "admin"
|
||||
And I navigate to "Plugins > Text editors > TinyMCE editor > General settings" in site administration
|
||||
When I click on "Disable the Tiny equation editor plugin" "link"
|
||||
Then I should see "The Tiny equation editor plugin has been disabled"
|
||||
And "Disable the Tiny equation editor plugin" "link" should not exist
|
||||
But "Enable the Tiny equation editor plugin" "link" should exist
|
||||
When I click on "Enable the Tiny equation editor plugin" "link"
|
||||
Then I should see "The Tiny equation editor plugin has been enabled"
|
||||
And "Enable the Tiny equation editor plugin" "link" should not exist
|
||||
But "Disable the Tiny equation editor plugin" "link" should exist
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace editor_tiny\plugininfo;
|
||||
|
||||
use advanced_testcase;
|
||||
|
||||
/**
|
||||
* Unit tests for the editor_tiny\tiny plugininfo class.
|
||||
*
|
||||
* @package editor_tiny
|
||||
* @covers \editor_tiny\plugininfo\tiny
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tiny_test extends advanced_testcase {
|
||||
/**
|
||||
* Uninstall is allowed of TinyMCE plugins.
|
||||
*
|
||||
* @covers ::is_uninstall_allowed
|
||||
*/
|
||||
public function test_is_uninstall_allowed(): void {
|
||||
$instance = new tiny();
|
||||
$this->assertTrue($instance->is_uninstall_allowed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the manage URL.
|
||||
*
|
||||
* @covers ::get_manage_url
|
||||
*/
|
||||
public function test_get_manage_url(): void {
|
||||
$this->assertInstanceOf(\moodle_url::class, tiny::get_manage_url());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the get_enabled_plugins method.
|
||||
*
|
||||
* @covers ::get_enabled_plugin
|
||||
*/
|
||||
public function test_get_enabled_plugins(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$plugins = tiny::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('recordrtc', $plugins);
|
||||
$this->assertArrayHasKey('media', $plugins);
|
||||
$this->assertArrayHasKey('autosave', $plugins);
|
||||
$this->assertArrayHasKey('h5p', $plugins);
|
||||
|
||||
// Disable a plugin.
|
||||
tiny::enable_plugin('h5p', 0);
|
||||
|
||||
$plugins = tiny::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('recordrtc', $plugins);
|
||||
$this->assertArrayHasKey('media', $plugins);
|
||||
$this->assertArrayHasKey('autosave', $plugins);
|
||||
$this->assertArrayNotHasKey('h5p', $plugins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the base implementation is used for plugins not supporting ordering.
|
||||
*/
|
||||
public function test_sorting_not_supported(): void {
|
||||
$this->assertFalse(tiny::plugintype_supports_ordering());
|
||||
|
||||
$this->assertNull(tiny::get_sorted_plugins());
|
||||
$this->assertNull(tiny::get_sorted_plugins(true));
|
||||
$this->assertNull(tiny::get_sorted_plugins(false));
|
||||
|
||||
$this->assertFalse(tiny::change_plugin_order('tiny_h5p', \core\plugininfo\base::MOVE_UP));
|
||||
$this->assertFalse(tiny::change_plugin_order('tiny_h5p', \core\plugininfo\base::MOVE_DOWN));
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,6 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2022112800; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2023021301; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2022111800;
|
||||
$plugin->component = 'editor_tiny'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ class get extends external_api {
|
||||
throw new \UnexpectedValueException("Table handler class {$tableclass} does not support dynamic updating.");
|
||||
}
|
||||
|
||||
$filtersetclass = "{$tableclass}_filterset";
|
||||
$filtersetclass = $tableclass::get_filterset_class();
|
||||
if (!class_exists($filtersetclass)) {
|
||||
throw new \UnexpectedValueException("The filter specified ({$filtersetclass}) is invalid.");
|
||||
}
|
||||
|
||||
@@ -1953,6 +1953,15 @@ class flexible_table {
|
||||
return $this->filterset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class used as a filterset.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_filterset_class(): string {
|
||||
return static::class . '_filterset';
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to guess the base URL.
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core\plugininfo;
|
||||
|
||||
@@ -272,4 +272,49 @@ class base_test extends \advanced_testcase {
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that plugintype_supports_ordering() returns true.
|
||||
* @covers ::plugintype_supports_ordering
|
||||
*/
|
||||
public function test_plugintype_supports_ordering(): void {
|
||||
$this->assertFalse(base::plugintype_supports_ordering());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the base implementation is used for plugins not supporting ordering.
|
||||
*
|
||||
* @dataProvider plugins_not_supporting_ordering
|
||||
* @param string $plugin
|
||||
* @coversNothing
|
||||
*
|
||||
* Note: This test cannot declare coverage because it covers the various plugin implementations.
|
||||
*/
|
||||
public function test_get_sorted_plugins(
|
||||
string $plugin,
|
||||
): void {
|
||||
[$plugintype, $pluginname] = explode('_', $plugin, 2);
|
||||
$classname = \core_plugin_manager::resolve_plugininfo_class($plugintype);
|
||||
|
||||
$this->assertFalse($classname::plugintype_supports_ordering());
|
||||
|
||||
$this->assertNull($classname::get_sorted_plugins());
|
||||
$this->assertNull($classname::get_sorted_plugins(true));
|
||||
$this->assertNull($classname::get_sorted_plugins(false));
|
||||
|
||||
$this->assertFalse($classname::change_plugin_order($pluginname, base::MOVE_UP));
|
||||
$this->assertFalse($classname::change_plugin_order($pluginname, base::MOVE_DOWN));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for plugins_not_supporting_ordering.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function plugins_not_supporting_ordering(): array {
|
||||
return [
|
||||
['mod_assign'],
|
||||
['block_login'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core\plugininfo;
|
||||
|
||||
use advanced_testcase;
|
||||
|
||||
/**
|
||||
* Unit tests for the mod plugininfo class
|
||||
*
|
||||
* @package core
|
||||
* @covers \core\plugininfo\block
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class block_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the get_enabled_plugins method.
|
||||
*
|
||||
* @covers ::get_enabled_plugins
|
||||
*/
|
||||
public function test_get_enabled_plugins(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// The bigbluebuttonbn plugin is disabled by default.
|
||||
// Check all default formats.
|
||||
$plugins = block::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('badges', $plugins);
|
||||
$this->assertArrayHasKey('timeline', $plugins);
|
||||
$this->assertArrayHasKey('admin_bookmarks', $plugins);
|
||||
|
||||
// Disable a plugin.
|
||||
block::enable_plugin('timeline', 0);
|
||||
|
||||
$plugins = block::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('badges', $plugins);
|
||||
$this->assertArrayNotHasKey('timeline', $plugins);
|
||||
$this->assertArrayHasKey('admin_bookmarks', $plugins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the is_uninstall_allowed method.
|
||||
*
|
||||
* @dataProvider is_uninstall_allowed_provider
|
||||
* @param string $plugin
|
||||
* @param bool $expected
|
||||
*/
|
||||
public function test_is_uninstall_allowed(
|
||||
string $plugin,
|
||||
bool $expected,
|
||||
): void {
|
||||
$pluginmanager = \core_plugin_manager::instance();
|
||||
$plugininfo = $pluginmanager->get_plugin_info("block_{$plugin}");
|
||||
$this->assertEquals($expected, $plugininfo->is_uninstall_allowed());
|
||||
}
|
||||
|
||||
public function is_uninstall_allowed_provider(): array {
|
||||
$plugins = block::get_enabled_plugins();
|
||||
return array_map(function ($plugin) {
|
||||
$expected = true;
|
||||
if ($plugin === 'settings' || $plugin === 'navigation') {
|
||||
$expected = false;
|
||||
}
|
||||
return [
|
||||
'plugin' => $plugin,
|
||||
'expected' => $expected,
|
||||
];
|
||||
}, array_keys($plugins));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core\plugininfo;
|
||||
|
||||
use advanced_testcase;
|
||||
|
||||
/**
|
||||
* Unit tests for the editor plugininfo class
|
||||
*
|
||||
* @package core
|
||||
* @covers \core\plugininfo\editor
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class editor_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test that editor::get_enabled_plugins() returns the correct list of enabled plugins.
|
||||
*/
|
||||
public function test_get_enabled_plugins(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// All plugins are enabled by default.
|
||||
$plugins = editor::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('tiny', $plugins);
|
||||
$this->assertArrayHasKey('textarea', $plugins);
|
||||
|
||||
// Disable tiny.
|
||||
editor::enable_plugin('textarea', 0);
|
||||
|
||||
$plugins = editor::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('tiny', $plugins);
|
||||
$this->assertArrayNotHasKey('textarea', $plugins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that editor::enable_plugin set to disable all plugins will leave the textarea enabled.
|
||||
*/
|
||||
public function test_enable_plugin_all(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// All plugins are enabled by default.
|
||||
$plugins = editor::get_enabled_plugins();
|
||||
foreach ($plugins as $plugin) {
|
||||
editor::enable_plugin($plugin, 0);
|
||||
}
|
||||
|
||||
$plugins = editor::get_enabled_plugins();
|
||||
$this->assertCount(1, $plugins);
|
||||
$this->assertArrayHasKey('textarea', $plugins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that plugintype_supports_ordering() returns true.
|
||||
*/
|
||||
public function test_plugintype_supports_ordering(): void {
|
||||
$this->assertTrue(editor::plugintype_supports_ordering());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that get_sorted_plugins() returns the correct list of plugins.
|
||||
*
|
||||
* @dataProvider get_sorted_plugins_provider
|
||||
* @param string $texteditors The $CFG->texteditors value to use as a base
|
||||
* @param bool $enabledonly
|
||||
* @param array $expected The expected order
|
||||
*/
|
||||
public function test_get_sorted_plugins(
|
||||
string $texteditors,
|
||||
bool $enabledonly,
|
||||
array $expected,
|
||||
): void {
|
||||
global $CFG;
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$CFG->texteditors = $texteditors;
|
||||
$this->assertSame(
|
||||
$expected,
|
||||
array_keys(editor::get_sorted_plugins($enabledonly)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the get_sorted_plugins tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sorted_plugins_provider(): array {
|
||||
return [
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'enabledonly' => true,
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
],
|
||||
],
|
||||
[
|
||||
'texteditors' => 'tiny,textarea',
|
||||
'enabledonly' => true,
|
||||
'expected' => [
|
||||
'tiny',
|
||||
'textarea',
|
||||
],
|
||||
],
|
||||
[
|
||||
'texteditors' => 'tiny',
|
||||
'enabledonly' => true,
|
||||
'expected' => [
|
||||
'tiny',
|
||||
],
|
||||
],
|
||||
'Phantom values are removed from the list' => [
|
||||
'texteditors' => 'fakeeditor',
|
||||
'enabledonly' => true,
|
||||
'expected' => [
|
||||
],
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'enabledonly' => false,
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
|
||||
// Disabled editors are listed alphabetically at the end.
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
],
|
||||
[
|
||||
'texteditors' => 'tiny',
|
||||
'enabledonly' => false,
|
||||
'expected' => [
|
||||
'tiny',
|
||||
|
||||
// Disabled editors are listed alphabetically at the end.
|
||||
'atto',
|
||||
'textarea',
|
||||
'tinymce',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that change_plugin_order() changes the order of the plugins.
|
||||
*
|
||||
* @dataProvider change_plugin_order_provider
|
||||
* @param string $texteditors
|
||||
* @param string $pluginname
|
||||
* @param int $direction
|
||||
* @param array $neworder
|
||||
* @param string $newtexteditors
|
||||
*/
|
||||
public function test_change_plugin_order(
|
||||
string $texteditors,
|
||||
string $pluginname,
|
||||
int $direction,
|
||||
array $neworder,
|
||||
string $newtexteditors,
|
||||
): void {
|
||||
global $CFG;
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$CFG->texteditors = $texteditors;
|
||||
editor::change_plugin_order($pluginname, $direction);
|
||||
|
||||
$this->assertSame(
|
||||
$neworder,
|
||||
array_keys(editor::get_sorted_plugins()),
|
||||
);
|
||||
$this->assertSame($newtexteditors, $CFG->texteditors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider fro the change_plugin_order() tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function change_plugin_order_provider(): array {
|
||||
return [
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'textarea',
|
||||
'direction' => base::MOVE_DOWN,
|
||||
'expected' => [
|
||||
'tiny',
|
||||
'textarea',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'tiny,textarea',
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'tiny',
|
||||
'direction' => base::MOVE_DOWN,
|
||||
// Tiny is already at the bottom of the enabled plugins.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'atto',
|
||||
'direction' => base::MOVE_DOWN,
|
||||
// Atto is not enabled. No change expected.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'tiny',
|
||||
'direction' => base::MOVE_UP,
|
||||
'expected' => [
|
||||
'tiny',
|
||||
'textarea',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'tiny,textarea',
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'tiny',
|
||||
'direction' => base::MOVE_UP,
|
||||
// Tiny is already at the top of the enabled plugins.
|
||||
'expected' => [
|
||||
'tiny',
|
||||
'textarea',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'tiny,textarea',
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'atto',
|
||||
'direction' => base::MOVE_UP,
|
||||
// Atto is not enabled. No change expected.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'tinymce',
|
||||
'direction' => base::MOVE_UP,
|
||||
// TinyMCE is not enabled. No change expected.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
[
|
||||
'texteditors' => 'textarea,tiny',
|
||||
'pluginname' => 'fakeeditor',
|
||||
'direction' => base::MOVE_UP,
|
||||
// The fakeeditor plugin does not exist. No change expected.
|
||||
'expected' => [
|
||||
'textarea',
|
||||
'tiny',
|
||||
'atto',
|
||||
'tinymce',
|
||||
],
|
||||
'newtexteditors' => 'textarea,tiny',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core\plugininfo;
|
||||
|
||||
use advanced_testcase;
|
||||
|
||||
/**
|
||||
* Unit tests for the media plugininfo class.
|
||||
*
|
||||
* @package core
|
||||
* @covers \core\plugininfo\media
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class media_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Test the get_enabled_plugins method.
|
||||
*
|
||||
* @covers ::get_enabled_plugins
|
||||
*/
|
||||
public function test_get_enabled_plugins(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
$plugins = media::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('videojs', $plugins);
|
||||
$this->assertArrayHasKey('youtube', $plugins);
|
||||
|
||||
// Disable a plugin.
|
||||
media::enable_plugin('youtube', 0);
|
||||
|
||||
$plugins = media::get_enabled_plugins();
|
||||
$this->assertArrayNotHasKey('youtube', $plugins);
|
||||
$this->assertArrayHasKey('videojs', $plugins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the is_uninstall_allowed method.
|
||||
*
|
||||
* @dataProvider is_uninstall_allowed_provider
|
||||
* @param string $plugin
|
||||
*/
|
||||
public function test_is_uninstall_allowed(
|
||||
string $plugin,
|
||||
): void {
|
||||
$pluginmanager = \core_plugin_manager::instance();
|
||||
$plugininfo = $pluginmanager->get_plugin_info("media_{$plugin}");
|
||||
$this->assertTrue($plugininfo->is_uninstall_allowed());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for the is_uninstall_allowed tests.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function is_uninstall_allowed_provider(): array {
|
||||
$plugins = media::get_enabled_plugins();
|
||||
return array_map(function ($plugin) {
|
||||
return [
|
||||
'plugin' => $plugin,
|
||||
];
|
||||
}, array_keys($plugins));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that change_plugin_order() changes the order of the plugins.
|
||||
*
|
||||
* @dataProvider change_plugin_order_provider
|
||||
* @param string $initialorder
|
||||
* @param string $pluginname
|
||||
* @param int $direction
|
||||
* @param array $neworder
|
||||
*/
|
||||
public function test_change_plugin_order(
|
||||
array $initialorder,
|
||||
string $pluginname,
|
||||
int $direction,
|
||||
array $neworder,
|
||||
): void {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
media::set_enabled_plugins($initialorder);
|
||||
media::change_plugin_order($pluginname, $direction);
|
||||
|
||||
$this->assertSame(
|
||||
$neworder,
|
||||
array_keys(media::get_sorted_plugins()),
|
||||
);
|
||||
}
|
||||
|
||||
public function change_plugin_order_provider(): array {
|
||||
$pluginmanager = \core_plugin_manager::instance();
|
||||
$allplugins = $pluginmanager->get_plugins_of_type('media');
|
||||
\core_collator::asort_objects_by_method($allplugins, 'get_rank', \core_collator::SORT_NUMERIC);
|
||||
$getorder = function (array $plugins) use ($allplugins) {
|
||||
return array_merge(
|
||||
$plugins,
|
||||
array_diff(array_reverse(array_keys($allplugins)), array_values($plugins)),
|
||||
);
|
||||
};
|
||||
|
||||
return [
|
||||
'Top item down one' => [
|
||||
'initialorder' => [
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
'youtube',
|
||||
],
|
||||
'pluginname' => 'videojs',
|
||||
'direction' => base::MOVE_DOWN,
|
||||
'expected' => $getorder([
|
||||
'html5audio',
|
||||
'videojs',
|
||||
'html5video',
|
||||
'youtube',
|
||||
]),
|
||||
],
|
||||
'Bottom item down one' => [
|
||||
'initialorder' => [
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
'youtube',
|
||||
],
|
||||
'pluginname' => 'youtube',
|
||||
'direction' => base::MOVE_DOWN,
|
||||
'expected' => $getorder([
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
'youtube',
|
||||
]),
|
||||
],
|
||||
'Top item up' => [
|
||||
'initialorder' => [
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
'youtube',
|
||||
],
|
||||
'pluginname' => 'videojs',
|
||||
'direction' => base::MOVE_UP,
|
||||
'expected' => $getorder([
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
'youtube',
|
||||
]),
|
||||
],
|
||||
'Disabled plugin' => [
|
||||
'initialorder' => [
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
],
|
||||
'pluginname' => 'youtube',
|
||||
'direction' => base::MOVE_UP,
|
||||
'expected' => $getorder([
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
]),
|
||||
],
|
||||
'Non-existent plugin' => [
|
||||
'initialorder' => [
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
'youtube',
|
||||
],
|
||||
'pluginname' => 'moodletube',
|
||||
'direction' => base::MOVE_UP,
|
||||
'expected' => $getorder([
|
||||
'videojs',
|
||||
'html5audio',
|
||||
'html5video',
|
||||
'youtube',
|
||||
]),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace core\plugininfo;
|
||||
|
||||
use advanced_testcase;
|
||||
|
||||
/**
|
||||
* Unit tests for the mod plugininfo class
|
||||
*
|
||||
* @package core
|
||||
* @covers \core\plugininfo\mod
|
||||
* @copyright 2023 Andrew Lyons <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class mod_test extends advanced_testcase {
|
||||
public function test_get_enabled_plugins(): void {
|
||||
$this->resetAfterTest();
|
||||
|
||||
// The bigbluebuttonbn plugin is disabled by default.
|
||||
// Check all default formats.
|
||||
$plugins = mod::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('assign', $plugins);
|
||||
$this->assertArrayHasKey('chat', $plugins);
|
||||
$this->assertArrayHasKey('forum', $plugins);
|
||||
$this->assertArrayNotHasKey('bigbluebuttonbn', $plugins);
|
||||
|
||||
// Disable assignment.
|
||||
mod::enable_plugin('assign', 0);
|
||||
|
||||
$plugins = mod::get_enabled_plugins();
|
||||
$this->assertArrayHasKey('chat', $plugins);
|
||||
$this->assertArrayHasKey('forum', $plugins);
|
||||
$this->assertArrayNotHasKey('assign', $plugins);
|
||||
$this->assertArrayNotHasKey('bigbluebuttonbn', $plugins);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace mod_assign\plugininfo;
|
||||
|
||||
use core\plugininfo\base;
|
||||
use core_plugin_manager;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Assign feedback subplugin info class.
|
||||
*
|
||||
@@ -21,14 +27,12 @@
|
||||
* @copyright 2013 Petr Skoda {@link http://skodak.org}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace mod_assign\plugininfo;
|
||||
|
||||
use core\plugininfo\base, core_plugin_manager, moodle_url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
class assignfeedback extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace mod_assign\plugininfo;
|
||||
|
||||
use core\plugininfo\base;
|
||||
use core_plugin_manager;
|
||||
use moodle_url;
|
||||
|
||||
/**
|
||||
* Assign submission subplugin info class.
|
||||
*
|
||||
@@ -21,14 +27,12 @@
|
||||
* @copyright 2013 Petr Skoda {@link http://skodak.org}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace mod_assign\plugininfo;
|
||||
|
||||
use core\plugininfo\base, core_plugin_manager, moodle_url;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
|
||||
class assignsubmission extends base {
|
||||
|
||||
public static function plugintype_supports_disabling(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all enabled plugins, the result may include missing plugins.
|
||||
* @return array|null of enabled plugins $pluginname=>$pluginname, null means unknown
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2023031000.02; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2023031000.03; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '4.2dev (Build: 20230310)'; // Human-friendly version name
|
||||
|
||||
Reference in New Issue
Block a user