This commit is contained in:
Jun Pataleta
2024-07-11 11:21:21 +08:00
32 changed files with 1344 additions and 327 deletions
@@ -0,0 +1,5 @@
issueNumber: MDL-82168
notes:
core_badges:
- message: New webservices enable_badges and disable_badges have been added.
type: improved
-64
View File
@@ -29,9 +29,6 @@ require_once($CFG->libdir . '/badgeslib.php');
$badgeid = required_param('id', PARAM_INT);
$copy = optional_param('copy', 0, PARAM_BOOL);
$activate = optional_param('activate', 0, PARAM_BOOL);
$deactivate = optional_param('lock', 0, PARAM_BOOL);
$confirm = optional_param('confirm', 0, PARAM_BOOL);
$return = optional_param('return', 0, PARAM_LOCALURL);
require_login();
@@ -74,64 +71,3 @@ if ($copy) {
}
redirect(new moodle_url('/badges/overview.php', array('id' => $cloneid)));
}
if ($activate) {
require_capability('moodle/badges:configurecriteria', $context);
$PAGE->url->param('activate', 1);
$status = ($badge->status == BADGE_STATUS_INACTIVE) ? BADGE_STATUS_ACTIVE : BADGE_STATUS_ACTIVE_LOCKED;
if ($confirm == 1) {
require_sesskey();
$badge->set_status($status);
$returnurl->param('msg', 'activatesuccess');
if ($badge->type == BADGE_TYPE_SITE) {
// Review on cron if there are more than 1000 users who can earn a site-level badge.
$sql = 'SELECT COUNT(u.id) as num
FROM {user} u
LEFT JOIN {badge_issued} bi
ON u.id = bi.userid AND bi.badgeid = :badgeid
WHERE bi.badgeid IS NULL AND u.id != :guestid AND u.deleted = 0';
$toearn = $DB->get_record_sql($sql, array('badgeid' => $badge->id, 'guestid' => $CFG->siteguest));
if ($toearn->num < 1000) {
$awards = $badge->review_all_criteria();
$returnurl->param('awards', $awards);
} else {
$returnurl->param('awards', 'cron');
}
} else {
$awards = $badge->review_all_criteria();
$returnurl->param('awards', $awards);
}
redirect($returnurl);
}
$strheading = get_string('reviewbadge', 'badges');
$PAGE->navbar->add($strheading);
$PAGE->set_title($strheading);
$PAGE->set_heading($heading);
echo $OUTPUT->header();
echo $OUTPUT->heading($strheading);
$params = array('id' => $badge->id, 'activate' => 1, 'sesskey' => sesskey(), 'confirm' => 1, 'return' => $return);
$url = new moodle_url('/badges/action.php', $params);
if (!$badge->has_criteria()) {
redirect($returnurl, get_string('error:cannotact', 'badges') . get_string('nocriteria', 'badges'), null, \core\output\notification::NOTIFY_ERROR);
} else {
$message = get_string('reviewconfirm', 'badges', $badge->name);
echo $OUTPUT->confirm($message, $url, $returnurl);
}
echo $OUTPUT->footer();
die;
}
if ($deactivate) {
require_sesskey();
require_capability('moodle/badges:configurecriteria', $context);
$status = ($badge->status == BADGE_STATUS_ACTIVE) ? BADGE_STATUS_INACTIVE : BADGE_STATUS_INACTIVE_LOCKED;
$badge->set_status($status);
redirect($returnurl);
}
+10
View File
@@ -0,0 +1,10 @@
define("core_badges/actions",["exports","core_badges/selectors","core/notification","core/prefetch","core/str","core/ajax","core/pending","core/event_dispatcher","core/toast","core_reportbuilder/local/events","core_reportbuilder/local/selectors"],(function(_exports,_selectors,_notification,_prefetch,_str,_ajax,_pending,_event_dispatcher,_toast,reportEvents,reportSelectors){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 _interopRequireWildcard(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]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
/**
* Various actions on badges - enabling, disabling, etc.
*
* @module core_badges/actions
* @copyright 2024 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_selectors=_interopRequireDefault(_selectors),_notification=_interopRequireDefault(_notification),_ajax=_interopRequireDefault(_ajax),_pending=_interopRequireDefault(_pending),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);_exports.init=()=>{(0,_prefetch.prefetchStrings)("core_badges",["reviewconfirm","activatesuccess","deactivatesuccess","awardoncron","numawardstat"]),(0,_prefetch.prefetchStrings)("core",["confirm","enable"]),registerEventListeners()};const registerEventListeners=()=>{document.addEventListener("click",(event=>{const enableOption=event.target.closest(_selectors.default.actions.enablebadge);if(enableOption){event.preventDefault();const reportElement=event.target.closest(reportSelectors.regions.report),triggerElement=reportElement?enableOption.closest(".dropdown").querySelector(".dropdown-toggle"):null,badgeId=enableOption.dataset.badgeid,badgeName=enableOption.dataset.badgename;_notification.default.saveCancelPromise((0,_str.getString)("confirm","core"),(0,_str.getString)("reviewconfirm","core_badges",badgeName),(0,_str.getString)("enable","core"),{triggerElement:triggerElement}).then((()=>async function(badgeId,badgeName,reportElement){var request={methodname:"core_badges_enable_badges",args:{badgeids:[badgeId]}};const pendingPromise=new _pending.default("core_badges/enable");try{const result=await _ajax.default.call([request])[0];if(reportElement)!function(badgeName,result){var _result$result2;if((null===(_result$result2=result.result)||void 0===_result$result2?void 0:_result$result2.length)>0){var _result$result3;(0,_toast.add)((0,_str.getString)("activatesuccess","core_badges",badgeName),{type:"success"});const awards=null===(_result$result3=result.result)||void 0===_result$result3?void 0:_result$result3.pop().awards;"cron"==awards?(0,_toast.add)((0,_str.getString)("awardoncron","core_badges",{badgename:badgeName})):awards>0&&(0,_toast.add)((0,_str.getString)("numawardstat","core_badges",{badgename:badgeName,awards:awards}))}else result.warnings.length>0&&(0,_toast.add)(result.warnings[0].message,{type:"danger"})}(badgeName,result),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement);else{var _result$result;const awards=null===(_result$result=result.result)||void 0===_result$result?void 0:_result$result.pop().awards;document.location=document.location.pathname+"?id=".concat(badgeId,"&awards=").concat(awards)}}catch(error){_notification.default.exception(error)}pendingPromise.resolve()}(badgeId,badgeName,reportElement))).catch((()=>{}))}const disableOption=event.target.closest(_selectors.default.actions.disablebadge);if(disableOption){event.preventDefault();!async function(badgeId,badgeName,reportElement){var request={methodname:"core_badges_disable_badges",args:{badgeids:[badgeId]}};try{const result=await _ajax.default.call([request])[0];reportElement?(!function(badgeName,result){result.result?(0,_toast.add)((0,_str.getString)("deactivatesuccess","core_badges",badgeName),{type:"success"}):result.warnings.length>0&&(0,_toast.add)(result.warnings[0].message,{type:"danger"})}(badgeName,result),(0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement)):document.location=document.location.pathname+"?id=".concat(badgeId)}catch(error){_notification.default.exception(error)}}(disableOption.dataset.badgeid,disableOption.dataset.badgename,event.target.closest(reportSelectors.regions.report))}}))}}));
//# sourceMappingURL=actions.min.js.map
File diff suppressed because one or more lines are too long
+9 -1
View File
@@ -1,3 +1,11 @@
define("core_badges/selectors",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;var name,value,_default={actions:{deletebackpack:(name="action",value="deletebackpack","[data-".concat(name,'="').concat(value,'"]'))},elements:{clearsearch:".input-group-append .clear-icon",main:"#backpacklist",backpackurl:"[data-backpackurl]"}};return _exports.default=_default,_exports.default}));
define("core_badges/selectors",["exports"],(function(_exports){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0;
/**
* Define all of the selectors we will be using on the backpack interface.
*
* @module core_badges/selectors
* @copyright 2020 Sara Arjona <sara@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
const getDataSelector=(name,value)=>"[data-".concat(name,'="').concat(value,'"]');var _default={actions:{deletebackpack:getDataSelector("action","deletebackpack"),enablebadge:getDataSelector("action","enablebadge"),disablebadge:getDataSelector("action","disablebadge")},elements:{clearsearch:".input-group-append .clear-icon",main:"#backpacklist",backpackurl:"[data-backpackurl]"}};return _exports.default=_default,_exports.default}));
//# sourceMappingURL=selectors.min.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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\n/**\n * Define all of the selectors we will be using on the backpack interface.\n *\n * @module core_badges/selectors\n * @copyright 2020 Sara Arjona <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n *\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n actions: {\n deletebackpack: getDataSelector('action', 'deletebackpack'),\n },\n elements: {\n clearsearch: '.input-group-append .clear-icon',\n main: '#backpacklist',\n backpackurl: '[data-backpackurl]',\n },\n};\n"],"names":["name","value","actions","deletebackpack","elements","clearsearch","main","backpackurl"],"mappings":"mJA+ByBA,KAAMC,eAIhB,CACXC,QAAS,CACLC,gBANiBH,KAMe,SANTC,MAMmB,iCAL9BD,kBAASC,cAOzBG,SAAU,CACNC,YAAa,kCACbC,KAAM,gBACNC,YAAa"}
{"version":3,"file":"selectors.min.js","sources":["../src/selectors.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\n/**\n * Define all of the selectors we will be using on the backpack interface.\n *\n * @module core_badges/selectors\n * @copyright 2020 Sara Arjona <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * A small helper function to build queryable data selectors.\n *\n * @method getDataSelector\n * @param {String} name\n * @param {String} value\n * @return {string}\n */\nconst getDataSelector = (name, value) => {\n return `[data-${name}=\"${value}\"]`;\n};\n\nexport default {\n actions: {\n deletebackpack: getDataSelector('action', 'deletebackpack'),\n enablebadge: getDataSelector('action', 'enablebadge'),\n disablebadge: getDataSelector('action', 'disablebadge'),\n },\n elements: {\n clearsearch: '.input-group-append .clear-icon',\n main: '#backpacklist',\n backpackurl: '[data-backpackurl]',\n },\n};\n"],"names":["getDataSelector","name","value","actions","deletebackpack","enablebadge","disablebadge","elements","clearsearch","main","backpackurl"],"mappings":";;;;;;;;MA+BMA,gBAAkB,CAACC,KAAMC,wBACXD,kBAASC,yBAGd,CACXC,QAAS,CACLC,eAAgBJ,gBAAgB,SAAU,kBAC1CK,YAAaL,gBAAgB,SAAU,eACvCM,aAAcN,gBAAgB,SAAU,iBAE5CO,SAAU,CACNC,YAAa,kCACbC,KAAM,gBACNC,YAAa"}
+194
View File
@@ -0,0 +1,194 @@
// 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/>.
/**
* Various actions on badges - enabling, disabling, etc.
*
* @module core_badges/actions
* @copyright 2024 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import selectors from 'core_badges/selectors';
import Notification from 'core/notification';
import {prefetchStrings} from 'core/prefetch';
import {getString} from 'core/str';
import Ajax from 'core/ajax';
import Pending from 'core/pending';
import {dispatchEvent} from 'core/event_dispatcher';
import {add as addToast} from 'core/toast';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
/**
* Initialize module.
*/
export const init = () => {
prefetchStrings('core_badges', [
'reviewconfirm',
'activatesuccess',
'deactivatesuccess',
'awardoncron',
'numawardstat',
]);
prefetchStrings('core', [
'confirm',
'enable',
]);
registerEventListeners();
};
/**
* Register events for delete preset option in action menu.
*/
const registerEventListeners = () => {
document.addEventListener('click', (event) => {
const enableOption = event.target.closest(selectors.actions.enablebadge);
if (enableOption) {
event.preventDefault();
// Use triggerElement to return focus to the action menu toggle.
const reportElement = event.target.closest(reportSelectors.regions.report);
const triggerElement = reportElement ? enableOption.closest('.dropdown').querySelector('.dropdown-toggle') : null;
const badgeId = enableOption.dataset.badgeid;
const badgeName = enableOption.dataset.badgename;
Notification.saveCancelPromise(
getString('confirm', 'core'),
getString('reviewconfirm', 'core_badges', badgeName),
getString('enable', 'core'),
{triggerElement}
).then(() => {
return enableBadge(badgeId, badgeName, reportElement);
}).catch(() => {
return;
});
}
const disableOption = event.target.closest(selectors.actions.disablebadge);
if (disableOption) {
event.preventDefault();
const badgeId = disableOption.dataset.badgeid;
const badgeName = disableOption.dataset.badgename;
const reportElement = event.target.closest(reportSelectors.regions.report);
disableBadge(badgeId, badgeName, reportElement);
}
});
};
/**
* Enable the badge.
*
* @param {Number} badgeId The id of the badge to enable.
* @param {String} badgeName The name of the badge to enable.
* @param {HTMLElement} reportElement the report element.
*/
async function enableBadge(badgeId, badgeName, reportElement) {
var request = {
methodname: 'core_badges_enable_badges',
args: {
badgeids: [badgeId],
}
};
const pendingPromise = new Pending('core_badges/enable');
try {
const result = await Ajax.call([request])[0];
if (reportElement) {
showEnableResultToast(badgeName, result);
// Report element is present, reload the table.
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
} else {
// Report element is not present, add the parameters to the current page to display the message.
const awards = result.result?.pop().awards;
document.location = document.location.pathname + `?id=${badgeId}&awards=${awards}`;
}
} catch (error) {
Notification.exception(error);
}
pendingPromise.resolve();
}
/**
* Show the result of enabling a badge.
*
* @param {String} badgeName The name of the badge to enable.
* @param {Object} result The result of enabling a badge.
*/
function showEnableResultToast(badgeName, result) {
if (result.result?.length > 0) {
addToast(getString('activatesuccess', 'core_badges', badgeName), {type: 'success'});
const awards = result.result?.pop().awards;
if (awards == 'cron') {
addToast(getString('awardoncron', 'core_badges', {badgename: badgeName}));
} else if (awards > 0) {
addToast(getString('numawardstat', 'core_badges', {badgename: badgeName, awards: awards}));
}
} else if (result.warnings.length > 0) {
addToast(result.warnings[0].message, {type: 'danger'});
}
}
/**
* Disable the badge.
*
* @param {Number} badgeId The id of the badge to disable.
* @param {String} badgeName The name of the badge to enable.
* @param {HTMLElement} reportElement the report element.
*/
async function disableBadge(badgeId, badgeName, reportElement) {
var request = {
methodname: 'core_badges_disable_badges',
args: {
badgeids: [badgeId],
}
};
try {
const result = await Ajax.call([request])[0];
if (reportElement) {
// Report element is present, show the message in a toast and reload the table.
showDisableResultToast(badgeName, result);
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
} else {
// Report element is not present, the page should be reloaded.
document.location = document.location.pathname + `?id=${badgeId}`;
}
} catch (error) {
Notification.exception(error);
}
}
/**
* Show the result of disabling a badge.
*
* @param {String} badgeName The name of the badge to disable.
* @param {Object} result The result of disabling a badge.
*/
function showDisableResultToast(badgeName, result) {
if (result.result) {
addToast(
getString('deactivatesuccess', 'core_badges', badgeName),
{type: 'success'}
);
} else if (result.warnings.length > 0) {
addToast(
result.warnings[0].message,
{type: 'danger'}
);
}
}
+2
View File
@@ -36,6 +36,8 @@ const getDataSelector = (name, value) => {
export default {
actions: {
deletebackpack: getDataSelector('action', 'deletebackpack'),
enablebadge: getDataSelector('action', 'enablebadge'),
disablebadge: getDataSelector('action', 'disablebadge'),
},
elements: {
clearsearch: '.input-group-append .clear-icon',
+126
View File
@@ -0,0 +1,126 @@
<?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_badges\external;
use core_badges\badge;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_multiple_structure;
use core_external\external_value;
use core_external\external_warnings;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/badgeslib.php');
/**
* External service to disable badges.
*
* @package core_badges
* @category external
* @copyright 2024 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 4.5
*/
class disable_badges extends external_api {
/**
* Describes the parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'badgeids' => new external_multiple_structure(
new external_value(PARAM_TEXT, 'The badge identifiers to update', VALUE_REQUIRED),
),
]);
}
/**
* Disable the given badges.
*
* @param array $badgeids List of badge identifiers to disable.
* @return array List of results and warnings.
*/
public static function execute(array $badgeids): array {
global $CFG, $DB;
$warnings = [];
[
'badgeids' => $badgeids,
] = self::validate_parameters(self::execute_parameters(), [
'badgeids' => $badgeids,
]);
// Check if badges are enabled.
if (empty($CFG->enablebadges)) {
throw new moodle_exception('badgesdisabled', 'badges');
}
foreach ($badgeids as $badgeid) {
$badge = new badge($badgeid);
// Check capabilities.
$context = $badge->get_context();
self::validate_context($context);
if (!has_capability('moodle/badges:configurecriteria', $context)) {
$warnings[] = [
'item' => $badgeid,
'warningcode' => 'nopermissions',
'message' => get_string('nopermissions', 'error'),
];
continue;
}
// Check if course badges are enabled.
if (empty($CFG->badges_allowcoursebadges) && ($badge->type == BADGE_TYPE_COURSE)) {
$warnings[] = [
'item' => $badgeid,
'warningcode' => 'coursebadgesdisabled',
'message' => get_string('coursebadgesdisabled', 'badges'),
];
continue;
}
$status = ($badge->status == BADGE_STATUS_ACTIVE) ? BADGE_STATUS_INACTIVE : BADGE_STATUS_INACTIVE_LOCKED;
// Deactivate the badge.
$badge->set_status($status);
}
return [
'result' => empty($warnings),
'warnings' => $warnings,
];
}
/**
* 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([
'result' => new external_value(PARAM_BOOL, 'The processing result'),
'warnings' => new external_warnings(),
]);
}
}
+183
View File
@@ -0,0 +1,183 @@
<?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_badges\external;
use core_badges\badge;
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_multiple_structure;
use core_external\external_value;
use core_external\external_warnings;
use moodle_exception;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->libdir . '/badgeslib.php');
/**
* External service to enable badges.
*
* @package core_badges
* @category external
* @copyright 2024 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 4.5
*/
class enable_badges extends external_api {
/**
* Describes the parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'badgeids' => new external_multiple_structure(
new external_value(PARAM_TEXT, 'The badge identifiers to update', VALUE_REQUIRED),
),
]);
}
/**
* Enable the given badges.
*
* @param array $badgeids List of badge identifiers to enable.
* @return array The number of awarded users for each badge or 'cron' when there are more than 1000 users.
*/
public static function execute(array $badgeids): array {
global $CFG, $DB;
$result = [];
$warnings = [];
[
'badgeids' => $badgeids,
] = self::validate_parameters(self::execute_parameters(), [
'badgeids' => $badgeids,
]);
// Check if badges are enabled.
if (empty($CFG->enablebadges)) {
throw new moodle_exception('badgesdisabled', 'badges');
}
foreach ($badgeids as $badgeid) {
$badge = new badge($badgeid);
// Check capabilities.
$context = $badge->get_context();
self::validate_context($context);
if (!has_capability('moodle/badges:configurecriteria', $context)) {
$warnings[] = [
'item' => $badgeid,
'warningcode' => 'nopermissions',
'message' => get_string('nopermissions', 'error'),
];
continue;
}
// Check if course badges are enabled.
if (empty($CFG->badges_allowcoursebadges) && ($badge->type == BADGE_TYPE_COURSE)) {
$warnings[] = [
'item' => $badgeid,
'warningcode' => 'coursebadgesdisabled',
'message' => get_string('coursebadgesdisabled', 'badges'),
];
continue;
}
// Check if the badge has criteria.
if (!$badge->has_criteria()) {
$warnings[] = [
'item' => $badgeid,
'warningcode' => 'nocriteria',
'message' => get_string('nocriteria', 'badges'),
];
continue;
}
// Activate the badge.
$status = ($badge->status == BADGE_STATUS_INACTIVE) ? BADGE_STATUS_ACTIVE : BADGE_STATUS_ACTIVE_LOCKED;
$badge->set_status($status);
$awards = self::review_criteria($badge);
$result[] = [
'badgeid' => $badgeid,
'awards' => $awards,
];
}
return [
'result' => $result,
'warnings' => $warnings,
];
}
/**
* 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([
'result' => new external_multiple_structure(
new external_single_structure([
'badgeid' => new external_value(PARAM_INT, 'The badge identifier'),
'awards' => new external_value(PARAM_ALPHANUM, 'The processing result'),
]),
),
'warnings' => new external_warnings(),
]);
}
/**
* Review the criteria of the badge.
*
* @param \core_badges\badge $badge The badge to review the criteria.
* @return string The number of awarded users or 'cron' when there are more than 1000 users.
*/
private static function review_criteria(badge $badge): string {
global $CFG, $DB;
if ($badge->type == BADGE_TYPE_SITE) {
// Review on cron if there are more than 1000 users who can earn a site-level badge.
$sql = 'SELECT COUNT(u.id) as num
FROM {user} u
LEFT JOIN {badge_issued} bi
ON u.id = bi.userid AND bi.badgeid = :badgeid
WHERE bi.badgeid IS NULL AND u.id != :guestid AND u.deleted = 0';
$toearn = $DB->get_record_sql(
$sql,
[
'badgeid' => $badge->id,
'guestid' => $CFG->siteguest,
],
);
if ($toearn->num < 1000) {
$awards = $badge->review_all_criteria();
} else {
$awards = 'cron';
}
} else {
$awards = $badge->review_all_criteria();
}
return $awards;
}
}
@@ -158,21 +158,19 @@ class badges extends system_report {
protected function add_actions(): void {
// Activate badge.
$this->add_action((new action(
new moodle_url('/badges/action.php', [
'id' => ':id',
'activate' => true,
'return' => ':return',
]),
new moodle_url('#'),
new pix_icon('t/show', '', 'core'),
[],
[
'data-action' => 'enablebadge',
'data-badgeid' => ':id',
'data-badgename' => ':badgename',
'data-courseid' => ':courseid',
],
false,
new lang_string('activate', 'badges')
))->add_callback(static function(stdclass $row): bool {
$badge = new \core_badges\badge($row->id);
// Populate the return URL.
$row->return = (new moodle_url('/badges/index.php',
['type' => $badge->type, 'id' => (int) $badge->courseid]))->out_as_local_url(false);
$row->badgename = $badge->name;
return has_capability('moodle/badges:configuredetails', $badge->get_context()) &&
$badge->has_criteria() &&
@@ -182,18 +180,19 @@ class badges extends system_report {
// Deactivate badge.
$this->add_action((new action(
new moodle_url('/badges/index.php', [
'lock' => ':id',
'sesskey' => sesskey(),
'type' => ':type',
'id' => ':courseid',
]),
new moodle_url('#'),
new pix_icon('t/hide', '', 'core'),
[],
[
'data-action' => 'disablebadge',
'data-badgeid' => ':id',
'data-badgename' => ':badgename',
'data-courseid' => ':courseid',
],
false,
new lang_string('deactivate', 'badges')
))->add_callback(static function(stdclass $row): bool {
$badge = new \core_badges\badge($row->id);
$row->badgename = $badge->name;
return has_capability('moodle/badges:configuredetails', $badge->get_context()) &&
$badge->has_criteria() &&
$row->status != BADGE_STATUS_INACTIVE && $row->status != BADGE_STATUS_INACTIVE_LOCKED;
+1
View File
@@ -161,5 +161,6 @@ $report = system_report_factory::create(badges::class, $PAGE->context);
$report->set_default_no_results_notice(new lang_string('nobadges', 'badges'));
echo $report->output();
$PAGE->requires->js_call_amd('core_badges/actions', 'init');
echo $OUTPUT->footer();
+2 -2
View File
@@ -74,9 +74,9 @@ echo $output->render_tertiary_navigation($actionbar);
echo $OUTPUT->heading(print_badge_image($badge, $context, 'small') . ' ' . $badge->name);
if ($awards == 'cron') {
echo $OUTPUT->notification(get_string('awardoncron', 'badges'), 'notifysuccess');
echo $OUTPUT->notification(get_string('awardoncron', 'badges', ['badgename' => $badge->name]), 'info');
} else if ((int)$awards > 0) {
echo $OUTPUT->notification(get_string('numawardstat', 'badges', $awards), 'notifysuccess');
echo $OUTPUT->notification(get_string('numawardstat', 'badges', ['badgename' => $badge->name, 'awards' => $awards]), 'info');
}
echo $output->print_badge_status_box($badge);
echo $output->print_badge_overview($badge, $context);
+26 -8
View File
@@ -242,6 +242,7 @@ class core_badges_renderer extends plugin_renderer_base {
if ($badge->has_awards()) {
$url = new moodle_url('/badges/recipients.php', array('id' => $badge->id));
$a = new stdClass();
$a->badgename = $badge->name;
$a->link = $url->out();
$a->count = count($badge->get_awards());
$display .= get_string('numawards', 'badges', $a);
@@ -573,17 +574,34 @@ class core_badges_renderer extends plugin_renderer_base {
$message = $status . $action;
} else {
$this->page->requires->js_call_amd('core_badges/actions', 'init');
$status = get_string('statusmessage_' . $badge->status, 'badges');
if ($badge->is_active()) {
$action = $this->output->single_button(new moodle_url('/badges/action.php',
array('id' => $badge->id, 'lock' => 1, 'sesskey' => sesskey(),
'return' => $this->page->url->out_as_local_url(false))),
get_string('deactivate', 'badges'), 'POST', array('class' => 'activatebadge'));
$action = $this->output->single_button(
new moodle_url('#'),
get_string('deactivate', 'badges'),
'POST',
[
'class' => 'activatebadge',
'data-action' => 'disablebadge',
'data-badgeid' => $badge->id,
'data-badgename' => $badge->name,
'data-courseid' => $badge->courseid,
],
);
} else {
$action = $this->output->single_button(new moodle_url('/badges/action.php',
array('id' => $badge->id, 'activate' => 1, 'sesskey' => sesskey(),
'return' => $this->page->url->out_as_local_url(false))),
get_string('activate', 'badges'), 'POST', array('class' => 'activatebadge'));
$action = $this->output->single_button(
new moodle_url('#'),
get_string('activate', 'badges'),
'POST',
[
'class' => 'activatebadge',
'data-action' => 'enablebadge',
'data-badgeid' => $badge->id,
'data-badgename' => $badge->name,
'data-courseid' => $badge->courseid,
]);
}
$message = $status . $this->output->help_icon('status', 'badges') . $action;
+109 -116
View File
@@ -29,37 +29,23 @@ Feature: Award badges
@javascript
Scenario: Award badge on other badges as criteria
Given I log in as "teacher1"
And I am on "Course 1" course homepage
# Create course badge 1.
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge 1 |
| Description | Course badge 1 description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I set the field "type" to "Manual issue by role"
And I expand all fieldsets
# Set to ANY of the roles awards badge.
And I set the field "Teacher" to "1"
And I set the field "Any of the selected roles awards the badge" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
# Badge #2
And I am on "Course 1" course homepage
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge 2 |
| Description | Course badge 2 description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
# Set "course badge 1" as criteria
Given the following "core_badges > Badges" exist:
| name | course | description | image | status | type |
| Course Badge 1 | C1 | Course badge 1 description | badges/tests/behat/badge.png | active | 2 |
| Course Badge 2 | C1 | Course badge 2 description | badges/tests/behat/badge.png | 0 | 2 |
And the following "core_badges > Criteria" exists:
| badge | Course Badge 1 |
| role | editingteacher |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge 2"
And I select "Criteria" from the "jump" singleselect
# Set "course badge 1" as criteria for Badge 2.
And I set the field "type" to "Awarded badges"
And I set the field "id_badge_badges" to "Course Badge 1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I am on "Course 1" course homepage
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge 1"
@@ -110,13 +96,16 @@ Feature: Award badges
@javascript
Scenario: Award profile badge
Given the following "core_badges > Badge" exists:
| name | Profile Badge |
| description | Test badge description |
| image | badges/tests/behat/badge.png |
| status | 0 |
| type | 1 |
Given I log in as "admin"
And I navigate to "Badges > Add a new badge" in site administration
And I set the following fields to these values:
| Name | Profile Badge |
| Description | Test badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I navigate to "Badges > Manage badges" in site administration
And I follow "Profile Badge"
And I select "Criteria" from the "jump" singleselect
And I set the field "type" to "Profile completion"
And I expand all fieldsets
And I set the field "First name" to "1"
@@ -131,7 +120,7 @@ Feature: Award badges
And I should see "Criterion description"
And I should not see "Criteria for this badge have not been set up yet."
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I open my profile in edit mode
And I expand all fieldsets
And I set the field "Phone" to "123456789"
@@ -142,18 +131,18 @@ Feature: Award badges
@javascript
Scenario: Award site badge
Given I log in as "admin"
And I navigate to "Badges > Add a new badge" in site administration
And I set the following fields to these values:
| Name | Site Badge |
| Description | Site badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I set the field "type" to "Manual issue by role"
And I set the field "Teacher" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
Given the following "core_badges > Badge" exists:
| name | Site Badge |
| description | Site badge description |
| image | badges/tests/behat/badge.png |
| status | active |
| type | 1 |
And the following "core_badges > Criteria" exists:
| badge | Site Badge |
| role | editingteacher |
And I log in as "admin"
And I navigate to "Badges > Manage badges" in site administration
And I follow "Site Badge"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "Teacher 1 (teacher1@example.com)"
@@ -170,19 +159,19 @@ Feature: Award badges
@javascript
Scenario: Award course badge
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge |
| Description | Course badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I set the field "type" to "Manual issue by role"
And I set the field "Teacher" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
Given the following "core_badges > Badge" exists:
| name | Course Badge |
| course | C1 |
| description | Course badge description |
| image | badges/tests/behat/badge.png |
| status | active |
| type | 2 |
And the following "core_badges > Criteria" exists:
| badge | Course Badge |
| role | editingteacher |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "Student 2 (student2@example.com)"
@@ -202,20 +191,22 @@ Feature: Award badges
@javascript
Scenario: Award badge on activity completion
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I change window size to "large"
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge |
| Description | Course badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
Given the following "core_badges > Badge" exists:
| name | Course Badge |
| course | C1 |
| description | Course badge description |
| image | badges/tests/behat/badge.png |
| status | 0 |
| type | 2 |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge"
And I select "Criteria" from the "jump" singleselect
And I set the field "type" to "Activity completion"
And I set the field "Test assignment name" to "1"
And I press "Save"
And I press "Enable access"
When I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I log out
And I log in as "student1"
And I follow "Profile" in the user menu
@@ -236,25 +227,28 @@ Feature: Award badges
| section | 1 |
| completion | 2 |
| completionview | 1 |
And I log in as "teacher1"
And I am on "Course 1" course homepage
Given the following "core_badges > Badge" exists:
| name | Course Badge |
| course | C1 |
| description | Course badge description |
| image | badges/tests/behat/badge.png |
| status | 0 |
| type | 2 |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Course completion" in current page administration
And I set the field "id_overall_aggregation" to "2"
And I click on "Condition: Activity completion" "link"
And I set the field "Assignment - Music history" to "1"
And I press "Save changes"
And I am on "Course 1" course homepage
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge |
| Description | Course badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge"
And I select "Criteria" from the "jump" singleselect
And I set the field "type" to "Course completion"
And I set the field with xpath ".//*[contains(., 'Minimum grade required')]/ancestor::*[contains(concat(' ', @class, ' '), ' fitem ')]//input[1]" to "0"
And I press "Save"
And I press "Enable access"
When I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I log out
And I log in as "student1"
And I follow "Profile" in the user menu
@@ -276,23 +270,19 @@ Feature: Award badges
@javascript
Scenario: All of the selected roles can award badges
Given I log in as "teacher1"
And I am on "Course 1" course homepage
# Create course badge 1.
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge 1 |
| Description | Course badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I set the field "type" to "Manual issue by role"
And I expand all fieldsets
# Set to ANY of the roles awards badge.
And I set the field "Teacher" to "1"
And I set the field "Any of the selected roles awards the badge" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
Given the following "core_badges > Badge" exists:
| name | Course Badge 1 |
| course | C1 |
| description | Course badge description |
| image | badges/tests/behat/badge.png |
| status | active |
| type | 2 |
And the following "core_badges > Criteria" exists:
| badge | Course Badge 1 |
| role | editingteacher |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge 1"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
# Award course badge 1 to student 1.
@@ -304,13 +294,16 @@ Feature: Award badges
And I select "Recipients (1)" from the "jump" singleselect
Then I should see "Recipients (1)"
# Add course badge 2.
And I am on "Course 1" course homepage
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge 2 |
| Description | Course badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
Given the following "core_badges > Badge" exists:
| name | Course Badge 2 |
| course | C1 |
| description | Course badge description |
| image | badges/tests/behat/badge.png |
| status | 0 |
| type | 2 |
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge 2"
And I select "Criteria" from the "jump" singleselect
And I set the field "type" to "Manual issue by role"
And I expand all fieldsets
# Set to ALL of the selected roles award badge.
@@ -318,7 +311,7 @@ Feature: Award badges
And I set the field "All of the selected roles award the badge" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
# Award course badge 2 to student 2.
@@ -347,19 +340,19 @@ Feature: Award badges
@javascript
Scenario: Revoke badge
Given I log in as "teacher1"
And I am on "Course 1" course homepage
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge |
| Description | Course badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I set the field "type" to "Manual issue by role"
And I set the field "Teacher" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
Given the following "core_badges > Badge" exists:
| name | Course Badge |
| course | C1 |
| description | Course badge description |
| image | badges/tests/behat/badge.png |
| status | active |
| type | 2 |
And the following "core_badges > Criteria" exists:
| badge | Course Badge |
| role | editingteacher |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "Student 2 (student2@example.com)"
+13 -13
View File
@@ -13,7 +13,7 @@ Feature: Award badges with separate groups
| student2 | Student | 2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category | groupmode |
| Course 1 | C1 | 0 | 1 |
| Course 1 | C1 | 0 | 1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
@@ -30,16 +30,17 @@ Feature: Award badges with separate groups
| teacher1 | CB |
| student2 | CA |
| teacher2 | CA |
And I am on the "Course 1" "course editing" page logged in as "teacher1"
And I expand all fieldsets
And I set the field "Group mode" to "Separate groups"
And I press "Save and display"
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| Name | Course Badge |
| Description | Course badge description |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And the following "core_badges > Badge" exists:
| name | Course Badge |
| course | C1 |
| description | Course badge description |
| image | badges/tests/behat/badge.png |
| status | 0 |
| type | 2 |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Course Badge"
And I select "Criteria" from the "jump" singleselect
And I set the field "type" to "Manual issue by role"
And I expand all fieldsets
And I set the field "Teacher" to "1"
@@ -48,8 +49,7 @@ Feature: Award badges with separate groups
And I set the field "Any of the selected roles awards the badge" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I log out
And I click on "Enable" "button" in the "Confirm" "dialogue"
@javascript
Scenario: Award course badge as non-editing teacher with only one group
+1 -1
View File
@@ -86,7 +86,7 @@ Feature: Test tertiary navigation as various users
And I navigate to "Badges" in current page administration
And I click on "Manage badges" "button"
And I press "Enable access" action in the "Testing course badge" report row
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I log out
# Now student should see the Badges link.
And I am on the "C1" "Course" page logged in as "student1"
+3 -3
View File
@@ -59,7 +59,7 @@ Feature: Award badges based on activity completion
And I set the field "Quiz - Test quiz name 1" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I should see "Recipients (0)"
# Pass grade for student1. Activity is considered complete because student1 got a passing grade.
And user "student1" has attempted "Test quiz name 1" with responses:
@@ -85,7 +85,7 @@ Feature: Award badges based on activity completion
And I set the field "Quiz - Test quiz name 2" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Pass grade for student1.
And user "student1" has attempted "Test quiz name 2" with responses:
| slot | response |
@@ -119,7 +119,7 @@ Feature: Award badges based on activity completion
And I press "Save"
# Enable badge access once students have completed the activity.
When I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Only student1 should earn the badge because student2 did not pass the quiz.
Then I should see "Recipients (1)"
And I select "Recipients (1)" from the "jump" singleselect
+12 -12
View File
@@ -31,7 +31,7 @@ Feature: Award badges based on cohort
And I set the field "id_cohort_cohorts" to "One Cohort"
And I press "Save"
And I press "Enable access"
When I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
Then I should see "Recipients (1)"
And I log out
And I log in as "user1"
@@ -70,7 +70,7 @@ Feature: Award badges based on cohort
And I set the field "id_agg_1" to "1"
And I press "Save"
When I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
Then I should see "Recipients (1)"
And I log out
And I log in as "user1"
@@ -110,7 +110,7 @@ Feature: Award badges based on cohort
And I set the field "id_cohort_cohorts" to "One Cohort"
And I press "Save"
When I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
Then I should see "Recipients (2)"
And I log out
And I log in as "user1"
@@ -153,7 +153,7 @@ Feature: Award badges based on cohort
And I set the field "Any of the selected roles awards the badge" to "1"
And I press "Save"
When I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "First User (first@example.com)"
@@ -207,7 +207,7 @@ Feature: Award badges based on cohort
And I press "Save"
And I set the field "update" to "Any"
When I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I select "Recipients (1)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "First User (first@example.com)"
@@ -266,7 +266,7 @@ Feature: Award badges based on cohort
And I press "Save"
And I set the field "update" to "Any"
When I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I select "Recipients (1)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "First User (first@example.com)"
@@ -327,7 +327,7 @@ Feature: Award badges based on cohort
And I press "Save"
And I set the field "update" to "All"
When I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "First User (first@example.com)"
@@ -378,7 +378,7 @@ Feature: Award badges based on cohort
And I set the field "id_cohort_cohorts" to "One Cohort"
And I press "Save"
And I press "Enable access"
When I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I should see "Recipients (1)"
And I navigate to "Badges > Manage badges" in site administration
And I press "Edit" action in the "Site Badge 2" report row
@@ -387,7 +387,7 @@ Feature: Award badges based on cohort
And I set the field "id_cohort_cohorts" to "Two Cohort"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
Then I should see "Recipients (2)"
And I log out
And I log in as "user1"
@@ -436,8 +436,8 @@ Feature: Award badges based on cohort
And I set the field "id_cohort_cohorts" to "One Cohort,Two Cohort"
And I set the field "id_agg_1" to "1"
And I press "Save"
And I press "Enable access"
When I press "Continue"
When I press "Enable access"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I should see "Recipients (1)"
And I navigate to "Badges > Manage badges" in site administration
And I press "Edit" action in the "Site Badge 2" report row
@@ -448,7 +448,7 @@ Feature: Award badges based on cohort
And I set the field "id_agg_1" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I should see "Recipients (1)"
And I log out
And I log in as "user1"
@@ -59,7 +59,7 @@ Feature: Award badges based on competency completion
And I wait until the page is ready
# Enable the badge
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Rate the competency in the course
And I am on "Course 1" course homepage
And I navigate to "Competencies" in current page administration
@@ -112,7 +112,7 @@ Feature: Award badges based on competency completion
# Enable the badge
And I wait until the page is ready
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Rate the competency in the course
And I am on "Course 1" course homepage
And I navigate to "Competencies" in current page administration
@@ -167,7 +167,7 @@ Feature: Award badges based on competency completion
# Enable the badge
And I wait until the page is ready
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Rate the competency in the course
And I am on "Course 1" course homepage
And I navigate to "Competencies" in current page administration
+1 -1
View File
@@ -22,7 +22,7 @@ Feature: Award badges based on user profile field
And I set the field "id_field_picture" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I log out
When I log in as "user1"
And I follow "Profile" in the user menu
+5 -5
View File
@@ -77,14 +77,14 @@ Feature: Manage badges
And I press "Save"
And I navigate to "Badges > Manage badges" in site administration
And I press "Enable access" action in the "Badge #1" report row
And I should see "Changes in badge access"
And I press "Continue"
And I should see "Access to the badges was successfully enabled"
And I should see "This will make your badge visible to users and allow them to start earning it."
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I should see "Access to badge 'Badge #1' enabled"
Then the following should exist in the "reportbuilder-table" table:
| Name | Badge status |
| Badge #1 | Available |
And I press "Disable access" action in the "Badge #1" report row
And I should see "Access to the badges was successfully disabled"
And I should see "Access to badge 'Badge #1' disabled"
And the following should exist in the "reportbuilder-table" table:
| Name | Badge status |
| Badge #1 | Not available |
@@ -99,7 +99,7 @@ Feature: Manage badges
And I press "Save"
And I navigate to "Badges > Manage badges" in site administration
And I press "Enable access" action in the "Badge #1" report row
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I press "Award badge" action in the "Badge #1" report row
And I set the field "potentialrecipients[]" to "Admin User (moodle@example.com)"
And I press "Award badge"
@@ -52,7 +52,7 @@ Feature: Manage badges is not shown when there are no existing badges.
And I should not see "Testing course badge"
And I click on "Manage badges" "button"
And I press "Enable access" action in the "Testing course badge" report row
And I click on "Continue" "button"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I should see "Testing course badge"
And I click on "Back" "button"
And "Manage badges" "button" should exist
@@ -92,7 +92,7 @@ Feature: Manage badges is not shown when there are no existing badges.
And I navigate to "Badges" in current page administration
And I click on "Manage badges" "button"
And I press "Enable access" action in the "Testing course badge" report row
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
And I log out
# Now student should see the Badges link.
And I am on the "C1" "Course" page logged in as "student1"
+23 -19
View File
@@ -9,26 +9,26 @@ Feature: Display badges
| username | firstname | lastname | email |
| student1 | Student | 1 | student1@example.com |
# Create system badge and define a criterion.
Given the following "core_badges > Badge" exists:
| name | Testing system badge |
| description | Testing system badge description |
| image | badges/tests/behat/badge.png |
| version | 1.1 |
| status | 0 |
| type | 1 |
| language | ca |
And the following "core_badges > Criteria" exists:
| badge | Testing system badge |
| role | editingteacher |
And I log in as "admin"
And I navigate to "Badges > Add a new badge" in site administration
And I set the following fields to these values:
| Name | Testing system badge |
| Version | 1.1 |
| Language | Catalan |
| Description | Testing system badge description |
| Image author | http://author.example.com |
| Image caption | Test caption image |
And I upload "badges/tests/behat/badge.png" file to "Image" filemanager
And I press "Create badge"
And I set the field "type" to "Manual issue by role"
And I expand all fieldsets
And I set the field "Teacher" to "1"
And I press "Save"
And I navigate to "Badges > Manage badges" in site administration
And I follow "Testing system badge"
And I select "Criteria" from the "jump" singleselect
Scenario: Display badge without expired date
# Enable the badge.
Given I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Award badge to student1.
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
@@ -53,7 +53,7 @@ Feature: Display badges
And I set the field "id_field_firstname" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Award badge to student1.
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
@@ -81,7 +81,7 @@ Feature: Display badges
And I press "Save"
And I set the field "update" to "2"
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Check badge details are displayed.
And I select "Recipients (2)" from the "jump" singleselect
And I press "View issued badge" action in the "Student 1" report row
@@ -101,8 +101,10 @@ Feature: Display badges
When I click on "Relative date" "radio"
And I set the field "expireperiod[number]" to "1"
And I press "Save changes"
And I should see "Changes saved"
And I select "Overview" from the "jump" singleselect
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Award badge to student1.
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
@@ -123,8 +125,10 @@ Feature: Display badges
And I set the field "expireperiod[timeunit]" to "1"
And I set the field "expireperiod[number]" to "1"
And I press "Save changes"
And I should see "Changes saved"
And I select "Overview" from the "jump" singleselect
And I press "Enable access"
And I press "Continue"
And I click on "Enable" "button" in the "Confirm" "dialogue"
# Award badge to student1.
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
+224
View File
@@ -0,0 +1,224 @@
<?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_badges\external;
use core_badges_generator;
use core_badges\badge;
use externallib_advanced_testcase;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->libdir . '/badgeslib.php');
/**
* Tests for external function disable_badges.
*
* @package core_badges
* @copyright 2024 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 4.5
* @covers \core_badges\external\disable_badges
*/
final class disable_badges_test extends externallib_advanced_testcase {
/**
* Test execute method.
*/
public function test_execute(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->assertTrue($data['sitebadge']->is_active());
$this->assertTrue($data['coursebadge']->is_active());
$result = disable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(disable_badges::execute_returns(), $result);
$this->assertTrue($result['result']);
$this->assertEmpty($result['warnings']);
$sitebadge = new badge($data['sitebadge']->id);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertFalse($sitebadge->is_active());
$this->assertFalse($coursebadge->is_active());
}
/**
* Test execute method when badges are disabled.
*/
public function test_execute_badgesdisabled(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Disable course badges.
set_config('enablebadges', 0);
$data = $this->prepare_test_data();
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('badgesdisabled', 'core_badges'));
$result = disable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(disable_badges::execute_returns(), $result);
}
/**
* Test execute method when course badges are disabled.
*/
public function test_execute_coursebadgesdisabled(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Disable course badges.
set_config('badges_allowcoursebadges', 0);
$data = $this->prepare_test_data();
$this->assertTrue($data['sitebadge']->is_active());
$this->assertTrue($data['coursebadge']->is_active());
$result = disable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(disable_badges::execute_returns(), $result);
// Course badge can't be disabled because course badges are disabled.
$this->assertFalse($result['result']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($data['coursebadge']->id, $result['warnings'][0]['item']);
$this->assertEquals('coursebadgesdisabled', $result['warnings'][0]['warningcode']);
$sitebadge = new badge($data['sitebadge']->id);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertFalse($sitebadge->is_active());
$this->assertTrue($coursebadge->is_active());
}
/**
* Test execute method when the user doesn't have the capability to disable badges.
*/
public function test_execute_without_capability(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->setUser($data['teacher']);
$this->assertTrue($data['sitebadge']->is_active());
$this->assertTrue($data['coursebadge']->is_active());
$result = disable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(disable_badges::execute_returns(), $result);
// Teacher doesn't have capability to disable site badges.
$this->assertFalse($result['result']);
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($data['sitebadge']->id, $result['warnings'][0]['item']);
$this->assertEquals('nopermissions', $result['warnings'][0]['warningcode']);
$sitebadge = new badge($data['sitebadge']->id);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertTrue($sitebadge->is_active());
$this->assertFalse($coursebadge->is_active());
}
/**
* Test execute method when the badge is already disabled.
*/
public function test_execute_disabledisabledbadge(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->assertTrue($data['coursebadge']->is_active());
$data['coursebadge']->set_status(BADGE_STATUS_INACTIVE);
$this->assertFalse($data['coursebadge']->is_active());
$result = disable_badges::execute([
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(disable_badges::execute_returns(), $result);
// Disabled badges can be disabled again.
$this->assertTrue($result['result']);
$this->assertEmpty($result['warnings']);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertFalse($coursebadge->is_active());
}
/**
* Prepare the test, creating a few users and badges.
*
* @return array Test data.
*/
private function prepare_test_data(): array {
global $DB;
// Setup test data.
$course = $this->getDataGenerator()->create_course();
// Create users and enrolments.
$student1 = $this->getDataGenerator()->create_and_enrol($course);
$student2 = $this->getDataGenerator()->create_and_enrol($course);
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
$sitebadge = $generator->create_badge([
'name' => 'Site badge',
'description' => 'Site badge',
'status' => BADGE_STATUS_ACTIVE,
]);
$coursebadge = $generator->create_badge([
'name' => 'Course badge',
'description' => 'Course badge',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
'status' => BADGE_STATUS_ACTIVE,
]);
// Create criteria for manually awarding by role.
$managerrole = $DB->get_field('role', 'id', ['shortname' => 'manager']);
$generator->create_criteria(['badgeid' => $sitebadge->id, 'roleid' => $managerrole]);
$generator->create_criteria(['badgeid' => $coursebadge->id, 'roleid' => $managerrole]);
// Issue badges to student1.
$sitebadge->issue($student1->id, true);
$coursebadge->issue($student1->id, true);
return [
'course' => $course,
'student1' => $student1,
'student2' => $student2,
'teacher' => $teacher,
'sitebadge' => $sitebadge,
'coursebadge' => $coursebadge,
];
}
}
+312
View File
@@ -0,0 +1,312 @@
<?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_badges\external;
use core_badges_generator;
use core_badges\badge;
use externallib_advanced_testcase;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->libdir . '/badgeslib.php');
/**
* Tests for external function enable_badges.
*
* @package core_badges
* @copyright 2024 Sara Arjona <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 4.5
* @covers \core_badges\external\enable_badges
*/
final class enable_badges_test extends externallib_advanced_testcase {
/**
* Test execute method.
*/
public function test_execute(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->assertFalse($data['sitebadge']->is_active());
$this->assertFalse($data['coursebadge']->is_active());
$result = enable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
$this->assertEquals($data['sitebadge']->id, $result['result'][0]['badgeid']);
$this->assertEquals($data['coursebadge']->id, $result['result'][1]['badgeid']);
$this->assertEmpty($result['warnings']);
$sitebadge = new badge($data['sitebadge']->id);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertTrue($sitebadge->is_active());
$this->assertTrue($coursebadge->is_active());
}
/**
* Test execute method when badges are disabled.
*/
public function test_execute_badgesdisabled(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Disable course badges.
set_config('enablebadges', 0);
$data = $this->prepare_test_data();
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('badgesdisabled', 'core_badges'));
$result = enable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
}
/**
* Test execute method when course badges are disabled.
*/
public function test_execute_coursebadgesdisabled(): void {
$this->resetAfterTest();
$this->setAdminUser();
// Disable course badges.
set_config('badges_allowcoursebadges', 0);
$data = $this->prepare_test_data();
$this->assertFalse($data['sitebadge']->is_active());
$this->assertFalse($data['coursebadge']->is_active());
$result = enable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
$this->assertEquals($data['sitebadge']->id, $result['result'][0]['badgeid']);
// Course badge can't be enabled because course badges are disabled.
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($data['coursebadge']->id, $result['warnings'][0]['item']);
$this->assertEquals('coursebadgesdisabled', $result['warnings'][0]['warningcode']);
$sitebadge = new badge($data['sitebadge']->id);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertTrue($sitebadge->is_active());
$this->assertFalse($coursebadge->is_active());
}
/**
* Test execute method when badge doesn't have criteria.
*/
public function test_execute_badgewithoutcriteria(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->assertFalse($data['nocriteriabadge']->has_criteria());
$this->assertFalse($data['nocriteriabadge']->is_active());
$result = enable_badges::execute([
$data['nocriteriabadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
$this->assertEmpty($result['result']);
// Badges without criteria can't be enabled.
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($data['nocriteriabadge']->id, $result['warnings'][0]['item']);
$this->assertEquals('nocriteria', $result['warnings'][0]['warningcode']);
$nocriteriabadge = new badge($data['nocriteriabadge']->id);
$this->assertFalse($nocriteriabadge->is_active());
}
/**
* Test execute method when the badge is already enabled.
*/
public function test_execute_enableenabledbadge(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->assertFalse($data['coursebadge']->is_active());
$data['coursebadge']->set_status(BADGE_STATUS_ACTIVE);
$this->assertTrue($data['coursebadge']->is_active());
$result = enable_badges::execute([
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
$this->assertEquals($data['coursebadge']->id, $result['result'][0]['badgeid']);
// Enabled badges can be enabled again.
$this->assertEmpty($result['warnings']);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertTrue($coursebadge->is_active());
}
/**
* Test execute method when badgeid doesn't exist.
*/
public function test_execute_wrongbadgeid(): void {
$this->resetAfterTest();
$this->setAdminUser();
$badgeid = 1234;
$this->expectException(\moodle_exception::class);
$this->expectExceptionMessage(get_string('error:nosuchbadge', 'core_badges', $badgeid));
$result = enable_badges::execute([
$badgeid,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
}
/**
* Test execute method when the user doesn't have the capability to enable badges.
*/
public function test_execute_without_capability(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->setUser($data['teacher']);
$this->assertFalse($data['sitebadge']->is_active());
$this->assertFalse($data['coursebadge']->is_active());
$result = enable_badges::execute([
$data['sitebadge']->id,
$data['coursebadge']->id,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
$this->assertEquals($data['coursebadge']->id, $result['result'][0]['badgeid']);
// Teacher doesn't have capability to enable site badges.
$this->assertNotEmpty($result['warnings']);
$this->assertEquals($data['sitebadge']->id, $result['warnings'][0]['item']);
$this->assertEquals('nopermissions', $result['warnings'][0]['warningcode']);
$sitebadge = new badge($data['sitebadge']->id);
$coursebadge = new badge($data['coursebadge']->id);
$this->assertFalse($sitebadge->is_active());
$this->assertTrue($coursebadge->is_active());
}
/**
* Test execute method when the badge has the same name as another enabled badge.
*/
public function test_execute_duplicatedname(): void {
$this->resetAfterTest();
$this->setAdminUser();
$data = $this->prepare_test_data();
$this->assertFalse($data['coursebadge']->is_active());
$this->assertFalse($data['coursebadge2']->is_active());
$result = enable_badges::execute([
$data['coursebadge']->id,
$data['coursebadge2']->id,
]);
$result = \core_external\external_api::clean_returnvalue(enable_badges::execute_returns(), $result);
// Badge can be enabled because badges with the same name are now allowed.
$this->assertEquals($data['coursebadge']->id, $result['result'][0]['badgeid']);
$this->assertEquals($data['coursebadge2']->id, $result['result'][1]['badgeid']);
$this->assertEmpty($result['warnings']);
$coursebadge = new badge($data['coursebadge']->id);
$coursebadge2 = new badge($data['coursebadge2']->id);
$this->assertTrue($coursebadge->is_active());
$this->assertTrue($coursebadge2->is_active());
}
/**
* Prepare the test, creating a few users and badges.
*
* @return array Test data.
*/
private function prepare_test_data(): array {
global $DB;
// Setup test data.
$course = $this->getDataGenerator()->create_course();
// Create users and enrolments.
$student1 = $this->getDataGenerator()->create_and_enrol($course);
$student2 = $this->getDataGenerator()->create_and_enrol($course);
$teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
/** @var core_badges_generator $generator */
$generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
$sitebadge = $generator->create_badge([
'name' => 'Site badge',
'description' => 'Site badge',
'status' => BADGE_STATUS_INACTIVE,
]);
$coursebadge = $generator->create_badge([
'name' => 'Course badge',
'description' => 'Course badge',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
'status' => BADGE_STATUS_INACTIVE,
]);
$coursebadge2 = $generator->create_badge([
'name' => 'Course badge',
'description' => 'Course badge',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
'status' => BADGE_STATUS_INACTIVE,
]);
$nocriteriabadge = $generator->create_badge([
'name' => 'No criteria badge',
'description' => 'No criteria badge',
'type' => BADGE_TYPE_COURSE,
'courseid' => $course->id,
'status' => BADGE_STATUS_INACTIVE,
]);
// Create criteria for manually awarding by role.
$managerrole = $DB->get_field('role', 'id', ['shortname' => 'manager']);
$generator->create_criteria(['badgeid' => $sitebadge->id, 'roleid' => $managerrole]);
$generator->create_criteria(['badgeid' => $coursebadge->id, 'roleid' => $managerrole]);
$generator->create_criteria(['badgeid' => $coursebadge2->id, 'roleid' => $managerrole]);
// Issue badges to student1.
$sitebadge->issue($student1->id, true);
$coursebadge->issue($student1->id, true);
return [
'course' => $course,
'student1' => $student1,
'student2' => $student2,
'teacher' => $teacher,
'sitebadge' => $sitebadge,
'coursebadge' => $coursebadge,
'coursebadge2' => $coursebadge2,
'nocriteriabadge' => $nocriteriabadge,
];
}
}
@@ -14,37 +14,25 @@ Feature: Enable Block Badges in a course
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
And I log in as "teacher1"
And I am on "Course 1" course homepage
# Issue badge 1 of 2
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| id_name | Badge 1 |
| id_description | Badge 1 |
And I upload "blocks/badges/tests/fixtures/badge.png" file to "Image" filemanager
And I press "Create badge"
And I select "Manual issue by role" from the "Add badge criteria" singleselect
And I set the field "Teacher" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And the following "core_badges > Badges" exist:
| name | course | description | image | status | type |
| Badge 1 | C1 | Badge 1 | badges/tests/behat/badge.png | active | 2 |
| Badge 2 | C1 | Badge 2 | badges/tests/behat/badge.png | active | 2 |
And the following "core_badges > Criterias" exist:
| badge | role |
| Badge 1 | editingteacher |
| Badge 2 | editingteacher |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Badge 1"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "Teacher 1 (teacher1@example.com)"
And I press "Award badge"
# Issue Badge 2 of 2
And I am on "Course 1" course homepage
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| id_name | Badge 2 |
| id_description | Badge 2 |
And I upload "blocks/badges/tests/fixtures/badge.png" file to "Image" filemanager
And I press "Create badge"
And I select "Manual issue by role" from the "Add badge criteria" singleselect
And I set the field "Teacher" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Badge 2"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "Teacher 1 (teacher1@example.com)"
@@ -17,20 +17,19 @@ Feature: Enable Block Badges on the dashboard and view awarded badges
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| badges | System | 1 | my-index | side-post |
And I log in as "teacher1"
And I am on "Course 1" course homepage
# Issue badge 1 of 2
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| id_name | Badge 1 |
| id_description | Badge 1 |
And I upload "blocks/badges/tests/fixtures/badge.png" file to "Image" filemanager
And I press "Create badge"
And I select "Manual issue by role" from the "Add badge criteria" singleselect
And I set the field "Teacher" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And the following "core_badges > Badge" exists:
| name | Badge 1 |
| course | C1 |
| description | Badge 1 |
| image | badges/tests/behat/badge.png |
| status | active |
| type | 2 |
And the following "core_badges > Criteria" exists:
| badge | Badge 1 |
| role | editingteacher |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Badge 1"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "Teacher 1 (teacher1@example.com)"
@@ -17,19 +17,19 @@ Feature: Enable Block Badges on the frontpage and view awarded badges
And the following "blocks" exist:
| blockname | contextlevel | reference | pagetypepattern | defaultregion |
| badges | System | 1 | site-index | side-pre |
And I am on the "Course 1" course page logged in as teacher1
# Issue badge 1 of 2
And I navigate to "Badges > Add a new badge" in current page administration
And I set the following fields to these values:
| id_name | Badge 1 |
| id_description | Badge 1 |
And I upload "blocks/badges/tests/fixtures/badge.png" file to "Image" filemanager
And I press "Create badge"
And I select "Manual issue by role" from the "Add badge criteria" singleselect
And I set the field "Teacher" to "1"
And I press "Save"
And I press "Enable access"
And I press "Continue"
And the following "core_badges > Badge" exists:
| name | Badge 1 |
| course | C1 |
| description | Badge 1 |
| image | badges/tests/behat/badge.png |
| status | active |
| type | 2 |
And the following "core_badges > Criteria" exists:
| badge | Badge 1 |
| role | editingteacher |
And I am on the "Course 1" "course" page logged in as "teacher1"
And I navigate to "Badges > Manage badges" in current page administration
And I follow "Badge 1"
And I select "Recipients (0)" from the "jump" singleselect
And I press "Award badge"
And I set the field "potentialrecipients[]" to "Teacher 1 (teacher1@example.com)"
+7 -7
View File
@@ -26,7 +26,7 @@
$string['actions'] = 'Actions';
$string['activate'] = 'Enable access';
$string['activatesuccess'] = 'Access to the badges was successfully enabled.';
$string['activatesuccess'] = 'Access to badge \'{$a}\' enabled.';
$string['addalignment'] = 'Add external skill or standard';
$string['addbadge'] = 'Add badges';
$string['addbadge_help'] = 'Select all badges that should be added to this badge requirement. Hold CTRL key to select multiple items.';
@@ -78,7 +78,7 @@ $string['attachment_help'] = 'If enabled, an issued badge will be attached to th
$string['award'] = 'Award badge';
$string['awardedto'] = 'Awarded to {$a}';
$string['awardedtoyou'] = 'Issued to me';
$string['awardoncron'] = 'Access to the badges was successfully enabled. Too many users can instantly earn this badge. To ensure site performance, this action will take some time to process.';
$string['awardoncron'] = 'A high number of users are being awarded the badge \'{$a->badgename}\'. It may take some time for all users to receive it.';
$string['awards'] = 'Recipients';
$string['backpackavailability'] = 'External badge verification';
$string['backpackconnectionok'] = 'Backpack connection successfully established';
@@ -272,7 +272,7 @@ $string['dateawarded'] = 'Date issued';
$string['dateearned'] = 'Date: {$a}';
$string['day'] = 'Day(s)';
$string['deactivate'] = 'Disable access';
$string['deactivatesuccess'] = 'Access to the badges was successfully disabled.';
$string['deactivatesuccess'] = 'Access to badge \'{$a}\' disabled.';
$string['defaultissuercontact'] = 'Badge issuer email address';
$string['defaultissuercontact_desc'] = 'An email address associated with the badge issuer. For an Open Badges v2.0 backpack, this is used for authentication when publishing badges to a backpack.';
$string['defaultissuerpassword'] = 'Badge issuer password';
@@ -296,7 +296,6 @@ $string['error:backpackdatainvalid'] = 'The data return from the backpack was in
$string['error:backpackemailnotfound'] = 'The email \'{$a}\' is not associated with a backpack. You need to <a href="http://backpack.openbadges.org">create a backpack</a> for that account or sign in with another email address.';
$string['error:badgeawardnotfound'] = 'Cannot verify this awarded badge. This badge may have been revoked.';
$string['error:badgenotfound'] = 'Badge not found';
$string['error:cannotact'] = 'Cannot activate the badge. ';
$string['error:cannotawardbadge'] = 'Cannot award badge to a user.';
$string['error:cannotrevokebadge'] = 'Cannot revoke badge from a user.';
$string['error:cannotdeletecriterion'] = 'This criterion cannot be deleted. ';
@@ -461,8 +460,8 @@ $string['notifydaily'] = 'Daily';
$string['notifyevery'] = 'Every time';
$string['notifymonthly'] = 'Monthly';
$string['notifyweekly'] = 'Weekly';
$string['numawards'] = 'This badge has been issued to <a href="{$a->link}">{$a->count}</a> user(s).';
$string['numawardstat'] = 'This badge has been issued {$a} user(s).';
$string['numawards'] = 'Users awarded badge \'{$a->badgename}\': <a href="{$a->link}">{$a->count}</a>.';
$string['numawardstat'] = 'Users awarded badge \'{$a->badgename}\': {$a->awards}.';
$string['overallcrit'] = 'of the selected criteria are complete.';
$string['oauth2issuer'] = 'OAuth 2 services';
$string['openbadgesv1'] = 'Open Badges v1.0';
@@ -516,7 +515,6 @@ $string['requiredcohort'] = 'At least one cohort should be added to the cohort c
$string['requiredcompetency'] = 'At least one competency should be added to the competency criterion.';
$string['requiredcourse'] = 'At least one course should be added to the courseset criterion.';
$string['requiredbadge'] = 'At least one badge should be added to the badge criterion.';
$string['reviewbadge'] = 'Changes in badge access';
$string['reviewconfirm'] = '<p>This will make your badge visible to users and allow them to start earning it.</p>
<p>It is possible that some users already meet this badge\'s criteria and will be issued this badge immediately after you enable it.</p>
@@ -598,4 +596,6 @@ $string['backpackemail'] = 'Email address';
$string['backpackemail_help'] = 'The email address associated with your backpack. While you are connected, any badges earned on this site will be associated with this email address.';
// Deprecated since Moodle 4.5.
$string['error:cannotact'] = 'Cannot activate the badge. ';
$string['error:duplicatename'] = 'Badge with such name already exists in the system.';
$string['reviewbadge'] = 'Changes in badge access';
+2
View File
@@ -121,3 +121,5 @@ siteregistrationcontact_help,core_hub
registrationcontactno,core
registrationcontactyes,core
error:duplicatename,core_badges
error:cannotact,core_badges
reviewbadge,core_badges
+12
View File
@@ -119,6 +119,18 @@ $functions = array(
'ajax' => true,
'loginrequired' => true,
),
'core_badges_disable_badges' => [
'classname' => 'core_badges\external\disable_badges',
'description' => 'Disable badges',
'type' => 'write',
'ajax' => true,
],
'core_badges_enable_badges' => [
'classname' => 'core_badges\external\enable_badges',
'description' => 'Enable badges',
'type' => 'write',
'ajax' => true,
],
'core_badges_get_user_badges' => array(
'classname' => 'core_badges_external',
'methodname' => 'get_user_badges',