From ae5fc380b5c1a511d56f03aa8a06d799f65c6575 Mon Sep 17 00:00:00 2001 From: Sara Arjona Date: Fri, 7 Jun 2024 14:29:12 +0200 Subject: [PATCH] MDL-43938 badges: Merge newbadge.php and edit.php The newbadge.php and edit.php pages have been merged in edit.php to make them easier to maintain because they were quite similar (newbadge.php was only used for creating badges and edit.php for editing badge details and messages). --- .upgradenotes/MDL-43938-2024070407235835.yml | 7 + admin/settings/badges.php | 2 +- badges/classes/badge.php | 142 +++++++++ badges/classes/output/standard_action_bar.php | 15 +- badges/edit.php | 202 +++++++----- badges/newbadge.php | 108 +------ badges/tests/badge_test.php | 298 ++++++++++++++++++ lib/badgeslib.php | 2 +- 8 files changed, 585 insertions(+), 191 deletions(-) create mode 100644 .upgradenotes/MDL-43938-2024070407235835.yml create mode 100644 badges/tests/badge_test.php 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');