diff --git a/.upgradenotes/MDL-43938-2024070407235835.yml b/.upgradenotes/MDL-43938-2024070407235835.yml
new file mode 100644
index 00000000000..b9ccf22c748
--- /dev/null
+++ b/.upgradenotes/MDL-43938-2024070407235835.yml
@@ -0,0 +1,7 @@
+issueNumber: MDL-43938
+notes:
+ core_badges:
+ - message: >-
+ The badges/newbadge.php page has been deprecated and merged with
+ badges/edit.php. Please, use badges/edit.php instead.
+ type: deprecated
diff --git a/admin/settings/badges.php b/admin/settings/badges.php
index 997808e9e53..e992f57c3aa 100644
--- a/admin/settings/badges.php
+++ b/admin/settings/badges.php
@@ -87,7 +87,7 @@ if (($hassiteconfig || has_any_capability(array(
$ADMIN->add('badges',
new admin_externalpage('newbadge',
new lang_string('newbadge', 'badges'),
- new moodle_url('/badges/newbadge.php', array('type' => BADGE_TYPE_SITE)),
+ new moodle_url('/badges/edit.php', ['action' => 'new']),
array('moodle/badges:createbadge'), empty($CFG->enablebadges)
)
);
diff --git a/badges/classes/badge.php b/badges/classes/badge.php
index be27fe6d177..77765558233 100644
--- a/badges/classes/badge.php
+++ b/badges/classes/badge.php
@@ -991,4 +991,146 @@ class badge {
public function get_badge_tags(): array {
return array_values(\core_tag_tag::get_item_tags_array('core_badges', 'badge', $this->id));
}
+
+ /**
+ * Create a badge, to store it in the database.
+ *
+ * @param stdClass $data Data to create a badge.
+ * @param int|null $courseid The course where the badge will be added.
+ * @return badge The badge object created.
+ */
+ public static function create_badge(stdClass $data, ?int $courseid = null): badge {
+ global $DB, $USER, $CFG;
+
+ $now = time();
+
+ $fordb = new stdClass();
+ $fordb->id = null;
+ $fordb->courseid = $courseid;
+ $fordb->type = $courseid ? BADGE_TYPE_COURSE : BADGE_TYPE_SITE;
+ $fordb->name = $data->name;
+ $fordb->version = $data->version;
+ $fordb->language = $data->language;
+ $fordb->description = $data->description;
+ $fordb->imageauthorname = $data->imageauthorname;
+ $fordb->imageauthoremail = $data->imageauthoremail;
+ $fordb->imageauthorurl = $data->imageauthorurl;
+ $fordb->imagecaption = $data->imagecaption;
+ $fordb->timecreated = $now;
+ $fordb->timemodified = $now;
+ $fordb->usercreated = $USER->id;
+ $fordb->usermodified = $USER->id;
+
+ if (badges_open_badges_backpack_api() == OPEN_BADGES_V1) {
+ $fordb->issuername = $data->issuername;
+ $fordb->issuerurl = $data->issuerurl;
+ $fordb->issuercontact = $data->issuercontact;
+ } else {
+ $url = parse_url($CFG->wwwroot);
+ $fordb->issuerurl = $url['scheme'] . '://' . $url['host'];
+ $fordb->issuername = $CFG->badges_defaultissuername;
+ $fordb->issuercontact = $CFG->badges_defaultissuercontact;
+ }
+
+ if (!property_exists($data, 'expiry')) {
+ $data->expiry = 0;
+ }
+ $fordb->expiredate = ($data->expiry == 1) ? $data->expiredate : null;
+ $fordb->expireperiod = ($data->expiry == 2) ? $data->expireperiod : null;
+ $fordb->messagesubject = get_string('messagesubject', 'badges');
+ $fordb->message = get_string('messagebody', 'badges',
+ html_writer::link($CFG->wwwroot . '/badges/mybadges.php', get_string('managebadges', 'badges')));
+ $fordb->attachment = 1;
+ $fordb->notification = BADGE_MESSAGE_NEVER;
+ $fordb->status = BADGE_STATUS_INACTIVE;
+
+ $badgeid = $DB->insert_record('badge', $fordb, true);
+
+ if ($courseid) {
+ $course = get_course($courseid);
+ $context = context_course::instance($course->id);
+ } else {
+ $context = context_system::instance();
+ }
+
+ // Trigger event, badge created.
+ $eventparams = [
+ 'objectid' => $badgeid,
+ 'context' => $context,
+ ];
+ $event = \core\event\badge_created::create($eventparams);
+ $event->trigger();
+
+ $badge = new badge($badgeid);
+ if (property_exists($data, 'tags')) {
+ \core_tag_tag::set_item_tags('core_badges', 'badge', $badgeid, $context, $data->tags);
+ }
+
+ return $badge;
+ }
+
+ /**
+ * Update badge data.
+ *
+ * @param stdClass $data Data to update a badge.
+ * @return bool A status for update a badge.
+ */
+ public function update(stdClass $data): bool {
+ global $USER;
+
+ $this->name = $data->name;
+ $this->version = trim($data->version);
+ $this->language = $data->language;
+ $this->description = $data->description;
+ $this->imageauthorname = $data->imageauthorname;
+ $this->imageauthoremail = $data->imageauthoremail;
+ $this->imageauthorurl = $data->imageauthorurl;
+ $this->imagecaption = $data->imagecaption;
+ $this->usermodified = $USER->id;
+ if (badges_open_badges_backpack_api() == OPEN_BADGES_V1) {
+ $this->issuername = $data->issuername;
+ $this->issuerurl = $data->issuerurl;
+ $this->issuercontact = $data->issuercontact;
+ }
+ $this->expiredate = ($data->expiry == 1) ? $data->expiredate : null;
+ $this->expireperiod = ($data->expiry == 2) ? $data->expireperiod : null;
+
+ // Need to unset message_editor options to avoid errors on form edit.
+ unset($this->messageformat);
+ unset($this->message_editor);
+
+ if (!$this->save()) {
+ return false;
+ }
+
+ \core_tag_tag::set_item_tags('core_badges', 'badge', $this->id, $this->get_context(), $data->tags);
+
+ return true;
+ }
+
+ /**
+ * Update the message of badge.
+ *
+ * @param stdClass $data Data to update a badge message.
+ * @return bool A status for update a badge message.
+ */
+ public function update_message(stdClass $data): bool {
+ // Calculate next message cron if form data is different from original badge data.
+ if ($data->notification != $this->notification) {
+ if ($data->notification > BADGE_MESSAGE_ALWAYS) {
+ $this->nextcron = badges_calculate_message_schedule($data->notification);
+ } else {
+ $this->nextcron = null;
+ }
+ }
+
+ $this->message = clean_text($data->message_editor['text'], FORMAT_HTML);
+ $this->messagesubject = $data->messagesubject;
+ $this->notification = $data->notification;
+ $this->attachment = $data->attachment;
+
+ unset($this->messageformat);
+ unset($this->message_editor);
+ return $this->save();
+ }
}
diff --git a/badges/classes/output/standard_action_bar.php b/badges/classes/output/standard_action_bar.php
index 01609e2a992..619eb7719bd 100644
--- a/badges/classes/output/standard_action_bar.php
+++ b/badges/classes/output/standard_action_bar.php
@@ -88,8 +88,19 @@ class standard_action_bar extends base_action_bar {
}
if ($this->showaddbadge && has_capability('moodle/badges:createbadge', $this->page->context)) {
- $buttons[] = new single_button(new moodle_url('/badges/newbadge.php', $params),
- get_string('newbadge', 'core_badges'), 'post', single_button::BUTTON_PRIMARY);
+ $editparams = ['action' => 'new'];
+ if (array_key_exists('id', $params)) {
+ $editparams['courseid'] = $params['id'];
+ }
+ $buttons[] = new single_button(
+ new moodle_url(
+ '/badges/edit.php',
+ $editparams,
+ ),
+ get_string('newbadge', 'core_badges'),
+ 'post',
+ single_button::BUTTON_PRIMARY,
+ );
}
foreach ($buttons as $key => $button) {
diff --git a/badges/edit.php b/badges/edit.php
index 86f6c9f910c..a65fdd9b128 100644
--- a/badges/edit.php
+++ b/badges/edit.php
@@ -15,10 +15,9 @@
// along with Moodle. If not, see .
/**
- * Editing badge details, criteria, messages
+ * Editing badge details, criteria, messages.
*
- * @package core
- * @subpackage badges
+ * @package core_badges
* @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Yuliya Bozhko
@@ -28,7 +27,14 @@ require_once(__DIR__ . '/../config.php');
require_once($CFG->libdir . '/badgeslib.php');
require_once($CFG->libdir . '/filelib.php');
-$badgeid = required_param('id', PARAM_INT);
+// Used only for creating new badge.
+$courseid = optional_param('courseid', 0, PARAM_INT);
+if ($courseid === 0 ) {
+ $courseid = null;
+}
+
+// Used for editing existing badge.
+$badgeid = optional_param('id', null, PARAM_INT);
$action = optional_param('action', 'badge', PARAM_TEXT);
require_login();
@@ -37,24 +43,54 @@ if (empty($CFG->enablebadges)) {
throw new \moodle_exception('badgesdisabled', 'badges');
}
-$badge = new badge($badgeid);
-$context = $badge->get_context();
-$navurl = new moodle_url('/badges/index.php', array('type' => $badge->type));
+if (!empty($badgeid)) {
+ // Existing badge.
+ $badge = new badge($badgeid);
-if ($action == 'message') {
- require_capability('moodle/badges:configuremessages', $context);
+ if ($badge->courseid) {
+ $course = get_course($badge->courseid);
+ }
+ $params = ['id' => $badgeid, 'action' => $action];
+ $badgename = $badge->name;
+
+ // Check capabilities.
+ $context = $badge->get_context();
+ if ($action == 'message') {
+ require_capability('moodle/badges:configuremessages', $context);
+ } else {
+ require_capability('moodle/badges:configuredetails', $context);
+ }
} else {
- require_capability('moodle/badges:configuredetails', $context);
+ // New badge.
+ if ($courseid) {
+ $course = get_course($courseid);
+ $context = context_course::instance($course->id);
+ } else {
+ $context = context_system::instance();
+ }
+
+ $badge = new stdClass();
+ $badge->id = null;
+ $badge->type = $courseid ? BADGE_TYPE_COURSE : BADGE_TYPE_SITE;
+ $badge->courseid = $courseid;
+
+ $params = ['courseid' => $courseid];
+ $badgename = get_string('create', 'badges');
+
+ // Check capabilities.
+ require_capability('moodle/badges:createbadge', $context);
}
+// Check if course badges are enabled.
+if (empty($CFG->badges_allowcoursebadges) && ($badge->type == BADGE_TYPE_COURSE)) {
+ throw new \moodle_exception('coursebadgesdisabled', 'badges');
+}
+
+$navurl = new moodle_url('/badges/index.php', ['type' => $badge->type]);
if ($badge->type == BADGE_TYPE_COURSE) {
- if (empty($CFG->badges_allowcoursebadges)) {
- throw new \moodle_exception('coursebadgesdisabled', 'badges');
- }
require_login($badge->courseid);
- $course = get_course($badge->courseid);
$heading = format_string($course->fullname, true, ['context' => $context]);
- $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid));
+ $navurl = new moodle_url('/badges/index.php', ['type' => $badge->type, 'id' => $badge->courseid]);
$PAGE->set_pagelayout('incourse');
navigation_node::override_active_url($navurl);
} else {
@@ -63,106 +99,104 @@ if ($badge->type == BADGE_TYPE_COURSE) {
navigation_node::override_active_url($navurl, true);
}
-$currenturl = new moodle_url('/badges/edit.php', array('id' => $badge->id, 'action' => $action));
+$currenturl = new moodle_url('/badges/edit.php', $params);
$PAGE->set_context($context);
$PAGE->set_url($currenturl);
$PAGE->set_heading($heading);
-$PAGE->set_title($badge->name);
+$PAGE->set_title($badgename);
$PAGE->add_body_class('limitedwidth');
-$PAGE->navbar->add($badge->name);
+$PAGE->navbar->add($badgename);
+/** @var \core_badges_renderer $output*/
$output = $PAGE->get_renderer('core', 'badges');
$statusmsg = '';
$errormsg = '';
-$badge->message = clean_text($badge->message, FORMAT_HTML);
-$editoroptions = array(
+$editoroptions = [];
+if ($badge->id && $action == 'message') {
+ $badge->message = clean_text($badge->message, FORMAT_HTML);
+ $editoroptions = [
'subdirs' => 0,
'maxbytes' => 0,
'maxfiles' => 0,
'changeformat' => 0,
'context' => $context,
'noclean' => false,
- 'trusttext' => false
- );
-$badge = file_prepare_standard_editor($badge, 'message', $editoroptions, $context);
+ 'trusttext' => false,
+ ];
+ $badge = file_prepare_standard_editor($badge, 'message', $editoroptions, $context);
+}
-$formclass = '\core_badges\form' . '\\' . $action;
-$form = new $formclass($currenturl, array('badge' => $badge, 'action' => $action, 'editoroptions' => $editoroptions));
+$formclass = '\core_badges\form' . '\\' . ($action == 'new' ? 'badge' : $action);
+$params = [
+ 'action' => $action,
+];
+if ($badge->id) {
+ $params['badge'] = $badge;
+ $params['editoroptions'] = $editoroptions;
+} else {
+ $params['courseid'] = $courseid;
+}
+$form = new $formclass($currenturl, $params);
if ($form->is_cancelled()) {
- redirect(new moodle_url('/badges/overview.php', array('id' => $badgeid)));
+ redirect(new moodle_url('/badges/overview.php', ['id' => $badgeid]));
} else if ($form->is_submitted() && $form->is_validated() && ($data = $form->get_data())) {
- if ($action == 'badge') {
- $badge->name = $data->name;
- $badge->version = trim($data->version);
- $badge->language = $data->language;
- $badge->description = $data->description;
- $badge->imageauthorname = $data->imageauthorname;
- $badge->imageauthoremail = $data->imageauthoremail;
- $badge->imageauthorurl = $data->imageauthorurl;
- $badge->imagecaption = $data->imagecaption;
- $badge->usermodified = $USER->id;
- if (badges_open_badges_backpack_api() == OPEN_BADGES_V1) {
- $badge->issuername = $data->issuername;
- $badge->issuerurl = $data->issuerurl;
- $badge->issuercontact = $data->issuercontact;
- }
- $badge->expiredate = ($data->expiry == 1) ? $data->expiredate : null;
- $badge->expireperiod = ($data->expiry == 2) ? $data->expireperiod : null;
-
- // Need to unset message_editor options to avoid errors on form edit.
- unset($badge->messageformat);
- unset($badge->message_editor);
-
- if ($badge->save()) {
- core_tag_tag::set_item_tags('core_badges', 'badge', $badge->id, $context, $data->tags);
+ switch ($action) {
+ case 'new':
+ // Create new badge.
+ $badge = badge::create_badge($data, $courseid);
+ $badgeid = $badge->id;
badges_process_badge_image($badge, $form->save_temp_file('image'));
- $form->set_data($badge);
- $statusmsg = get_string('changessaved');
- } else {
- $errormsg = get_string('error:save', 'badges');
- }
- } else if ($action == 'message') {
- // Calculate next message cron if form data is different from original badge data.
- if ($data->notification != $badge->notification) {
- if ($data->notification > BADGE_MESSAGE_ALWAYS) {
- $badge->nextcron = badges_calculate_message_schedule($data->notification);
- } else {
- $badge->nextcron = null;
+
+ // If a user can configure badge criteria, they will be redirected to the criteria page.
+ if (has_capability('moodle/badges:configurecriteria', $context)) {
+ redirect(new moodle_url('/badges/criteria.php', ['id' => $badgeid]));
}
- }
+ redirect(new moodle_url('/badges/overview.php', ['id' => $badgeid]));
+ break;
- $badge->message = clean_text($data->message_editor['text'], FORMAT_HTML);
- $badge->messagesubject = $data->messagesubject;
- $badge->notification = $data->notification;
- $badge->attachment = $data->attachment;
+ case 'badge':
+ // Edit existing badge.
+ if ($badge->update($data)) {
+ badges_process_badge_image($badge, $form->save_temp_file('image'));
+ $form->set_data($badge);
+ $statusmsg = get_string('changessaved');
+ } else {
+ $errormsg = get_string('error:save', 'badges');
+ }
+ break;
- unset($badge->messageformat);
- unset($badge->message_editor);
- if ($badge->save()) {
- $statusmsg = get_string('changessaved');
- } else {
- $errormsg = get_string('error:save', 'badges');
- }
+ case 'message':
+ // Update badge message.
+ if ($badge->update_message($data)) {
+ $statusmsg = get_string('changessaved');
+ } else {
+ $errormsg = get_string('error:save', 'badges');
+ }
+ break;
}
}
-echo $OUTPUT->header();
-$actionbar = new \core_badges\output\manage_badge_action_bar($badge, $PAGE);
-echo $output->render_tertiary_navigation($actionbar);
+echo $output->header();
-echo $OUTPUT->heading(print_badge_image($badge, $context, 'small') . ' ' . $badge->name);
+if ($badge->id) {
+ $actionbar = new \core_badges\output\manage_badge_action_bar($badge, $PAGE);
+ echo $output->render_tertiary_navigation($actionbar);
+ echo $output->heading(print_badge_image($badge, $context, 'small') . ' ' . $badge->name);
-if ($errormsg !== '') {
- echo $OUTPUT->notification($errormsg);
+ if ($errormsg !== '') {
+ echo $output->notification($errormsg);
-} else if ($statusmsg !== '') {
- echo $OUTPUT->notification($statusmsg, 'notifysuccess');
+ } else if ($statusmsg !== '') {
+ echo $output->notification($statusmsg, 'notifysuccess');
+ }
+ echo $output->print_badge_status_box($badge);
+} else {
+ echo $output->heading($badgename);
}
-echo $output->print_badge_status_box($badge);
$form->display();
-echo $OUTPUT->footer();
+echo $output->footer();
diff --git a/badges/newbadge.php b/badges/newbadge.php
index fe60d03e045..0658ebf4fa8 100644
--- a/badges/newbadge.php
+++ b/badges/newbadge.php
@@ -17,117 +17,19 @@
/**
* First step page for creating a new badge
*
- * @package core
- * @subpackage badges
+ * @package core_badges
* @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Yuliya Bozhko
+ * @deprecated since 4.5. Use badges/edit.php instead.
+ * @todo MDL-82383 This file will be deleted in Moodle 6.0.
*/
require_once(__DIR__ . '/../config.php');
-require_once($CFG->libdir . '/badgeslib.php');
-$type = required_param('type', PARAM_INT);
$courseid = optional_param('id', 0, PARAM_INT);
require_login();
-if (empty($CFG->enablebadges)) {
- throw new \moodle_exception('badgesdisabled', 'badges');
-}
-
-if (empty($CFG->badges_allowcoursebadges) && ($type == BADGE_TYPE_COURSE)) {
- throw new \moodle_exception('coursebadgesdisabled', 'badges');
-}
-
-$title = get_string('create', 'badges');
-$PAGE->add_body_class('limitedwidth');
-
-if (($type == BADGE_TYPE_COURSE) && ($course = $DB->get_record('course', array('id' => $courseid)))) {
- require_login($course);
- $coursecontext = context_course::instance($course->id);
- $PAGE->set_context($coursecontext);
- $PAGE->set_pagelayout('incourse');
- $PAGE->set_url('/badges/newbadge.php', array('type' => $type, 'id' => $course->id));
- $heading = format_string($course->fullname, true, array('context' => $coursecontext)) . ": " . $title;
- $PAGE->set_heading($heading);
- $PAGE->set_title($heading);
-} else {
- $PAGE->set_context(context_system::instance());
- $PAGE->set_pagelayout('admin');
- $PAGE->set_url('/badges/newbadge.php', array('type' => $type));
- $PAGE->set_heading($title);
- $PAGE->set_title($title);
-}
-
-require_capability('moodle/badges:createbadge', $PAGE->context);
-
-$fordb = new stdClass();
-$fordb->id = null;
-
-$form = new \core_badges\form\badge($PAGE->url, array('action' => 'new'));
-
-if ($form->is_cancelled()) {
- redirect(new moodle_url('/badges/index.php', array('type' => $type, 'id' => $courseid)));
-} else if ($data = $form->get_data()) {
- // Creating new badge here.
- $now = time();
-
- $fordb->name = $data->name;
- $fordb->version = $data->version;
- $fordb->language = $data->language;
- $fordb->description = $data->description;
- $fordb->imageauthorname = $data->imageauthorname;
- $fordb->imageauthoremail = $data->imageauthoremail;
- $fordb->imageauthorurl = $data->imageauthorurl;
- $fordb->imagecaption = $data->imagecaption;
- $fordb->timecreated = $now;
- $fordb->timemodified = $now;
- $fordb->usercreated = $USER->id;
- $fordb->usermodified = $USER->id;
-
- if (badges_open_badges_backpack_api() == OPEN_BADGES_V1) {
- $fordb->issuername = $data->issuername;
- $fordb->issuerurl = $data->issuerurl;
- $fordb->issuercontact = $data->issuercontact;
- } else {
- $url = parse_url($CFG->wwwroot);
- $fordb->issuerurl = $url['scheme'] . '://' . $url['host'];
- $fordb->issuername = $CFG->badges_defaultissuername;
- $fordb->issuercontact = $CFG->badges_defaultissuercontact;
- }
-
- $fordb->expiredate = ($data->expiry == 1) ? $data->expiredate : null;
- $fordb->expireperiod = ($data->expiry == 2) ? $data->expireperiod : null;
- $fordb->type = $type;
- $fordb->courseid = ($type == BADGE_TYPE_COURSE) ? $courseid : null;
- $fordb->messagesubject = get_string('messagesubject', 'badges');
- $fordb->message = get_string('messagebody', 'badges',
- html_writer::link($CFG->wwwroot . '/badges/mybadges.php', get_string('managebadges', 'badges')));
- $fordb->attachment = 1;
- $fordb->notification = BADGE_MESSAGE_NEVER;
- $fordb->status = BADGE_STATUS_INACTIVE;
-
- $newid = $DB->insert_record('badge', $fordb, true);
-
- // Trigger event, badge created.
- $eventparams = array('objectid' => $newid, 'context' => $PAGE->context);
- $event = \core\event\badge_created::create($eventparams);
- $event->trigger();
-
- $newbadge = new badge($newid);
- core_tag_tag::set_item_tags('core_badges', 'badge', $newid, $PAGE->context, $data->tags);
- badges_process_badge_image($newbadge, $form->save_temp_file('image'));
- // If a user can configure badge criteria, they will be redirected to the criteria page.
- if (has_capability('moodle/badges:configurecriteria', $PAGE->context)) {
- redirect(new moodle_url('/badges/criteria.php', array('id' => $newid)));
- }
- redirect(new moodle_url('/badges/overview.php', array('id' => $newid)));
-}
-
-echo $OUTPUT->header();
-echo $OUTPUT->box('', 'notifyproblem hide', 'check_connection');
-
-$form->display();
-
-echo $OUTPUT->footer();
+$newpageurl = new moodle_url('/badges/edit.php', ['courseid' => $courseid, 'action' => 'new']);
+redirect($newpageurl, get_string('newbadgedeprecated', 'core_badges'));
diff --git a/badges/tests/badge_test.php b/badges/tests/badge_test.php
new file mode 100644
index 00000000000..b98d6b53e68
--- /dev/null
+++ b/badges/tests/badge_test.php
@@ -0,0 +1,298 @@
+.
+
+declare(strict_types=1);
+
+namespace core_badges;
+
+use core_badges_generator;
+
+defined('MOODLE_INTERNAL') || die();
+
+global $CFG;
+require_once("{$CFG->libdir}/badgeslib.php");
+
+/**
+ * Unit tests for badge class.
+ *
+ * @package core_badges
+ * @covers \core_badges\badge
+ * @copyright 2024 Sara Arjona
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+final class badge_test extends \advanced_testcase {
+
+ /**
+ * Test create_badge.
+ *
+ * @dataProvider badges_provider
+ * @param bool $iscourse Whether the badge is a course badge or not.
+ * @param array $data Badge data. It will override the default data.
+ */
+ public function test_create_badge(bool $iscourse = false, array $data = []): void {
+ global $DB;
+
+ $this->resetAfterTest();
+
+ $courseid = null;
+ if ($iscourse) {
+ $course = $this->getDataGenerator()->create_course();
+ $courseid = (int) $course->id;
+ }
+
+ $user1 = $this->getDataGenerator()->create_user();
+ $this->setUser($user1);
+
+ // Check no badges exist.
+ $this->assertEquals(0, $DB->count_records('badge'));
+
+ $data = (object) array_merge($this->get_badge(), $data);
+
+ // Trigger and capture events.
+ $sink = $this->redirectEvents();
+
+ $badge = badge::create_badge($data, $courseid);
+ // Check the badge was created with the correct data.
+ $this->assertEquals(1, $DB->count_records('badge'));
+ $this->assertNotEmpty($badge->id);
+ if ($iscourse) {
+ $this->assertEquals(BADGE_TYPE_COURSE, $badge->type);
+ $this->assertEquals($course->id, $badge->courseid);
+ } else {
+ $this->assertEquals(BADGE_TYPE_SITE, $badge->type);
+ $this->assertNull($badge->courseid);
+ }
+ // Badges are always inactive by default, regardless the given status.
+ $this->assertEquals(BADGE_STATUS_INACTIVE, $badge->status);
+
+ if (property_exists($data, 'tags')) {
+ $this->assertEquals($data->tags, $badge->get_badge_tags());
+ }
+
+ // Check that the event was triggered.
+ $events = $sink->get_events();
+ $event = reset($events);
+
+ // Check that the event data is valid.
+ $this->assertInstanceOf('\core\event\badge_created', $event);
+ $this->assertEquals($badge->usercreated, $event->userid);
+ $this->assertEquals($badge->id, $event->objectid);
+ $this->assertDebuggingNotCalled();
+ $sink->close();
+ }
+
+ /**
+ * Test update() in badge class.
+ *
+ * @dataProvider badges_provider
+ * @param bool $iscourse Whether the badge is a course badge or not.
+ * @param array $data Badge data to update the badge with. It will override the default data.
+ */
+ public function test_udpate_badge(bool $iscourse = false, array $data = []): void {
+ global $USER, $DB;
+
+ $this->resetAfterTest();
+
+ $record = [];
+ if ($iscourse) {
+ $course = $this->getDataGenerator()->create_course();
+ $record['type'] = BADGE_TYPE_COURSE;
+ $record['courseid'] = $course->id;
+ }
+
+ /** @var core_badges_generator $generator */
+ $generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
+
+ $user1 = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $this->setUser($user1);
+
+ /** @var badge $badge */
+ $badge = $generator->create_badge($record);
+ $data = (object) array_merge($this->get_badge(), $data);
+
+ // Check the badge has been created.
+ $this->assertEquals(1, $DB->count_records('badge'));
+ $this->assertNotEquals($data->name, $badge->name);
+ $this->assertEmpty($badge->get_badge_tags());
+
+ // Trigger and capture events.
+ $sink = $this->redirectEvents();
+
+ $this->setUser($user2);
+ $this->assertTrue($badge->update($data));
+ // Check the badge was updated with the correct data.
+ $this->assertEquals(1, $DB->count_records('badge'));
+ $this->assertNotEmpty($badge->id);
+ $this->assertEquals($data->name, $badge->name);
+ if ($iscourse) {
+ $this->assertEquals(BADGE_TYPE_COURSE, $badge->type);
+ $this->assertEquals($course->id, $badge->courseid);
+ } else {
+ $this->assertEquals(BADGE_TYPE_SITE, $badge->type);
+ $this->assertNull($badge->courseid);
+ }
+ $this->assertEquals(BADGE_STATUS_ACTIVE, $badge->status);
+ $this->assertEquals($USER->id, $badge->usermodified);
+
+ if (property_exists($data, 'tags')) {
+ $this->assertEquals($data->tags, $badge->get_badge_tags());
+ }
+
+ // Check that the event was triggered.
+ $events = $sink->get_events();
+ $event = reset($events);
+
+ // Check that the event data is valid.
+ $this->assertInstanceOf('\core\event\badge_updated', $event);
+ $this->assertEquals($badge->usermodified, $event->userid);
+ $this->assertEquals($badge->id, $event->objectid);
+ $this->assertDebuggingNotCalled();
+ $sink->close();
+ }
+
+ /**
+ * Test update_message() in badge class.
+ *
+ * @dataProvider badges_provider
+ * @param bool $iscourse Whether the badge is a course badge or not.
+ * @param array $data Badge data to update the badge with. It will override the default data.
+ */
+ public function test_udpate_message_badge(bool $iscourse = false, array $data = []): void {
+ global $USER, $DB;
+
+ $this->resetAfterTest();
+
+ $record = [];
+ if ($iscourse) {
+ $course = $this->getDataGenerator()->create_course();
+ $record['type'] = BADGE_TYPE_COURSE;
+ $record['courseid'] = $course->id;
+ }
+
+ /** @var core_badges_generator $generator */
+ $generator = $this->getDataGenerator()->get_plugin_generator('core_badges');
+
+ $user1 = $this->getDataGenerator()->create_user();
+ $user2 = $this->getDataGenerator()->create_user();
+ $this->setUser($user1);
+
+ /** @var badge $badge */
+ $badge = $generator->create_badge($record);
+ $data = (object) array_merge($this->get_badge(), $data);
+
+ // Check the badge has been created.
+ $this->assertEquals(1, $DB->count_records('badge'));
+ $this->assertNotEquals($data->name, $badge->name);
+ $this->assertNotEquals($data->messagesubject, $badge->messagesubject);
+ $this->assertNotEquals($data->message_editor['text'], $badge->message);
+ $this->assertEmpty($badge->get_badge_tags());
+
+ // Trigger and capture events.
+ $sink = $this->redirectEvents();
+
+ $this->setUser($user2);
+ $this->assertTrue($badge->update_message($data));
+ // Check the badge was updated with the correct data.
+ $this->assertEquals(1, $DB->count_records('badge'));
+ $this->assertNotEmpty($badge->id);
+ $this->assertNotEquals($data->name, $badge->name);
+ $this->assertEquals($data->messagesubject, $badge->messagesubject);
+ $this->assertEquals($data->message_editor['text'], $badge->message);
+ if ($iscourse) {
+ $this->assertEquals(BADGE_TYPE_COURSE, $badge->type);
+ $this->assertEquals($course->id, $badge->courseid);
+ } else {
+ $this->assertEquals(BADGE_TYPE_SITE, $badge->type);
+ $this->assertNull($badge->courseid);
+ }
+ $this->assertEquals(BADGE_STATUS_ACTIVE, $badge->status);
+ $this->assertEquals($user1->id, $badge->usermodified);
+
+ // Check that the event was triggered.
+ $events = $sink->get_events();
+ $event = reset($events);
+
+ // Check that the event data is valid.
+ $this->assertInstanceOf('\core\event\badge_updated', $event);
+ $this->assertEquals($USER->id, $event->userid);
+ $this->assertEquals($badge->id, $event->objectid);
+ $this->assertDebuggingNotCalled();
+ $sink->close();
+ }
+
+ /**
+ * Data provider for badge tests.
+ *
+ * @return array
+ */
+ public static function badges_provider(): array {
+ return [
+ 'Site badge' => [
+ ],
+ 'Site badge with tags' => [
+ 'iscourse' => false,
+ 'data' => [
+ 'tags' => ['tag1', 'tag2'],
+ ],
+ ],
+ 'Course badge' => [
+ 'iscourse' => true,
+ ],
+ ];
+ }
+
+ /**
+ * Get default badge data for testing purpose.
+ *
+ * @return array Badge data.
+ */
+ private function get_badge(): array {
+ global $USER;
+
+ return [
+ 'name' => 'My test badge',
+ 'description' => 'Testing badge description',
+ 'timecreated' => time(),
+ 'timemodified' => time(),
+ 'usercreated' => $USER->id,
+ 'usermodified' => $USER->id,
+ 'issuername' => 'Test issuer',
+ 'issuerurl' => 'http://issuer-url.domain.co.nz',
+ 'issuercontact' => 'issuer@example.com',
+ 'expiry' => 0,
+ 'expiredate' => null,
+ 'expireperiod' => null,
+ 'type' => BADGE_TYPE_SITE,
+ 'courseid' => null,
+ 'messagesubject' => 'The new test message subject',
+ 'messageformat' => '1',
+ 'message_editor' => [
+ 'text' => 'The new test message body',
+ ],
+ 'attachment' => 1,
+ 'notification' => 0,
+ 'status' => BADGE_STATUS_ACTIVE_LOCKED,
+ 'version' => OPEN_BADGES_V2,
+ 'language' => 'en',
+ 'imageauthorname' => 'Image author',
+ 'imageauthoremail' => 'author@example.com',
+ 'imageauthorurl' => 'http://image.example.com/',
+ 'imagecaption' => 'Image caption',
+ 'tags' => [],
+ ];
+ }
+}
diff --git a/lib/badgeslib.php b/lib/badgeslib.php
index 357aad0d363..6030c3aa2a0 100644
--- a/lib/badgeslib.php
+++ b/lib/badgeslib.php
@@ -517,7 +517,7 @@ function badges_add_course_navigation(navigation_node $coursenode, stdClass $cou
navigation_node::TYPE_SETTING, null, 'coursebadges');
if (has_capability('moodle/badges:createbadge', $coursecontext)) {
- $url = new moodle_url('/badges/newbadge.php', array('type' => BADGE_TYPE_COURSE, 'id' => $course->id));
+ $url = new moodle_url('/badges/edit.php', ['action' => 'new', 'courseid' => $course->id]);
$coursenode->get('coursebadges')->add(get_string('newbadge', 'badges'), $url,
navigation_node::TYPE_SETTING, null, 'newbadge');