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');