From f4fb827ed13582daf64cb13a065daa3260871225 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Tue, 15 Mar 2016 11:58:36 +0100 Subject: [PATCH] MDL-53462 core_badges: New WS core_badges_get_user_badges --- badges/classes/external.php | 192 +++++++++++++++++++++++++++++++++ badges/tests/external_test.php | 151 ++++++++++++++++++++++++++ lib/db/services.php | 14 ++- version.php | 2 +- 4 files changed, 356 insertions(+), 3 deletions(-) create mode 100644 badges/classes/external.php create mode 100644 badges/tests/external_test.php diff --git a/badges/classes/external.php b/badges/classes/external.php new file mode 100644 index 00000000000..2a982645533 --- /dev/null +++ b/badges/classes/external.php @@ -0,0 +1,192 @@ +. + +/** + * Badges external API + * + * @package core_badges + * @category external + * @copyright 2016 Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.1 + */ + +defined('MOODLE_INTERNAL') || die; + +require_once($CFG->libdir . '/externallib.php'); +require_once($CFG->libdir . '/badgeslib.php'); + +/** + * Badges external functions + * + * @package core_badges + * @category external + * @copyright 2016 Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.1 + */ +class core_badges_external extends external_api { + + /** + * Describes the parameters for get_user_badges. + * + * @return external_external_function_parameters + * @since Moodle 3.1 + */ + public static function get_user_badges_parameters() { + return new external_function_parameters ( + array( + 'userid' => new external_value(PARAM_INT, 'Badges only for this user id, empty for current user', VALUE_DEFAULT, 0), + 'courseid' => new external_value(PARAM_INT, 'Filter badges by course id, empty all the courses', VALUE_DEFAULT, 0), + 'page' => new external_value(PARAM_INT, 'The page of records to return.', VALUE_DEFAULT, 0), + 'perpage' => new external_value(PARAM_INT, 'The number of records to return per page', VALUE_DEFAULT, 0), + 'search' => new external_value(PARAM_RAW, 'A simple string to search for', VALUE_DEFAULT, ''), + 'onlypublic' => new external_value(PARAM_BOOL, 'Whether to return only public badges', VALUE_DEFAULT, false), + ) + ); + } + + /** + * Returns the list of badges awarded to a user. + * + * @param int $userid user id + * @param int $courseid course id + * @param int $page page of records to return + * @param int $perpage number of records to return per page + * @param string $search a simple string to search for + * @param bool $onlypublic whether to return only public badges + * @return array array containing warnings and the awarded badges + * @since Moodle 3.1 + * @throws moodle_exception + */ + public static function get_user_badges($userid = 0, $courseid = 0, $page = 0, $perpage = 0, $search = '', $onlypublic = false) { + global $CFG, $USER; + + $warnings = array(); + + $params = array( + 'userid' => $userid, + 'courseid' => $courseid, + 'page' => $page, + 'perpage' => $perpage, + 'search' => $search, + 'onlypublic' => $onlypublic, + ); + $params = self::validate_parameters(self::get_user_badges_parameters(), $params); + + if (empty($CFG->enablebadges)) { + throw new moodle_exception('badgesdisabled', 'badges'); + } + + if (empty($CFG->badges_allowcoursebadges) && $params['courseid'] != 0) { + throw new moodle_exception('coursebadgesdisabled', 'badges'); + } + + // Default value for userid. + if (empty($params['userid'])) { + $params['userid'] = $USER->id; + } + + // Validate the user. + $user = core_user::get_user($params['userid'], '*', MUST_EXIST); + core_user::require_active_user($user); + + $usercontext = context_user::instance($user->id); + self::validate_context($usercontext); + + if ($USER->id != $user->id) { + require_capability('moodle/badges:viewotherbadges', $usercontext); + // We are looking other user's badges, we must retrieve only public badges. + $params['onlypublic'] = true; + } + + $userbadges = badges_get_user_badges($user->id, $params['courseid'], $params['page'], $params['perpage'], $params['search'], + $params['onlypublic']); + + $result = array(); + $result['badges'] = array(); + $result['warnings'] = $warnings; + + foreach ($userbadges as $badge) { + $context = ($badge->type == BADGE_TYPE_SITE) ? context_system::instance() : context_course::instance($badge->courseid); + $badge->badgeurl = moodle_url::make_webservice_pluginfile_url($context->id, 'badges', 'badgeimage', $badge->id, '/', + 'f1')->out(false); + // Return all the information if we are requesting our own badges. + // Or, if we have permissions for configuring badges in the badge context. + if ($USER->id == $user->id or has_capability('moodle/badges:configuredetails', $context)) { + $result['badges'][] = (array) $badge; + } else { + $result['badges'][] = array( + 'name' => $badge->name, + 'description' => $badge->description, + 'badgeurl' => $badge->badgeurl, + 'issuername' => $badge->issuername, + 'issuerurl' => $badge->issuerurl, + 'issuercontact' => $badge->issuercontact, + 'uniquehash' => $badge->uniquehash, + 'dateissued' => $badge->dateissued, + 'dateexpire' => $badge->dateexpire, + ); + } + } + + return $result; + } + + /** + * Describes the get_user_badges return value. + * + * @return external_single_structure + * @since Moodle 3.1 + */ + public static function get_user_badges_returns() { + return new external_single_structure( + array( + 'badges' => new external_multiple_structure( + new external_single_structure( + array( + 'id' => new external_value(PARAM_INT, 'Badge id.', VALUE_OPTIONAL), + 'name' => new external_value(PARAM_FILE, 'Badge name.'), + 'description' => new external_value(PARAM_NOTAGS, 'Badge description.'), + 'badgeurl' => new external_value(PARAM_URL, 'Badge URL.'), + 'timecreated' => new external_value(PARAM_INT, 'Time created.', VALUE_OPTIONAL), + 'timemodified' => new external_value(PARAM_INT, 'Time modified.', VALUE_OPTIONAL), + 'usercreated' => new external_value(PARAM_INT, 'User created.', VALUE_OPTIONAL), + 'usermodified' => new external_value(PARAM_INT, 'User modified.', VALUE_OPTIONAL), + 'issuername' => new external_value(PARAM_NOTAGS, 'Issuer name.'), + 'issuerurl' => new external_value(PARAM_URL, 'Issuer URL.'), + 'issuercontact' => new external_value(PARAM_RAW, 'Issuer contact.'), + 'expiredate' => new external_value(PARAM_INT, 'Expire date.', VALUE_OPTIONAL), + 'expireperiod' => new external_value(PARAM_INT, 'Expire period.', VALUE_OPTIONAL), + 'type' => new external_value(PARAM_INT, 'Type.', VALUE_OPTIONAL), + 'courseid' => new external_value(PARAM_INT, 'Course id.', VALUE_OPTIONAL), + 'message' => new external_value(PARAM_RAW, 'Message.', VALUE_OPTIONAL), + 'messagesubject' => new external_value(PARAM_TEXT, 'Message subject.', VALUE_OPTIONAL), + 'attachment' => new external_value(PARAM_INT, 'Attachment.', VALUE_OPTIONAL), + 'status' => new external_value(PARAM_INT, 'Status.', VALUE_OPTIONAL), + 'issuedid' => new external_value(PARAM_INT, 'Issued id.', VALUE_OPTIONAL), + 'uniquehash' => new external_value(PARAM_ALPHANUM, 'Unique hash.'), + 'dateissued' => new external_value(PARAM_INT, 'Date issued.'), + 'dateexpire' => new external_value(PARAM_INT, 'Date expire.'), + 'visible' => new external_value(PARAM_INT, 'Visible.', VALUE_OPTIONAL), + ) + ) + ), + 'warnings' => new external_warnings(), + ) + ); + } +} diff --git a/badges/tests/external_test.php b/badges/tests/external_test.php new file mode 100644 index 00000000000..77db1a40c6e --- /dev/null +++ b/badges/tests/external_test.php @@ -0,0 +1,151 @@ +. + +/** + * Badges external functions tests. + * + * @package core_badges + * @category external + * @copyright 2016 Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.1 + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; + +require_once($CFG->dirroot . '/webservice/tests/helpers.php'); +require_once($CFG->libdir . '/badgeslib.php'); + +/** + * Badges external functions tests + * + * @package core_badges + * @category external + * @copyright 2016 Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 3.1 + */ +class core_badges_external_testcase extends externallib_advanced_testcase { + + /** + * Set up for every test + */ + public function setUp() { + global $DB; + $this->resetAfterTest(); + $this->setAdminUser(); + + // Setup test data. + $this->course = $this->getDataGenerator()->create_course(); + + // Create users. + $this->student = self::getDataGenerator()->create_user(); + $this->teacher = self::getDataGenerator()->create_user(); + + // Users enrolments. + $this->studentrole = $DB->get_record('role', array('shortname' => 'student')); + $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); + $this->getDataGenerator()->enrol_user($this->student->id, $this->course->id, $this->studentrole->id, 'manual'); + $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course->id, $this->teacherrole->id, 'manual'); + + // Mock up a site badge. + $now = time(); + $badge = new stdClass(); + $badge->id = null; + $badge->name = "Test badge site"; + $badge->description = "Testing badges site"; + $badge->timecreated = $now - 12; + $badge->timemodified = $now - 12; + $badge->usercreated = $this->teacher->id; + $badge->usermodified = $this->teacher->id; + $badge->issuername = "Test issuer"; + $badge->issuerurl = "http://issuer-url.domain.co.nz"; + $badge->issuercontact = "issuer@example.com"; + $badge->expiredate = null; + $badge->expireperiod = null; + $badge->type = BADGE_TYPE_SITE; + $badge->courseid = null; + $badge->messagesubject = "Test message subject for badge"; + $badge->message = "Test message body for badge"; + $badge->attachment = 1; + $badge->notification = 0; + $badge->status = BADGE_STATUS_ACTIVE; + + $badgeid = $DB->insert_record('badge', $badge, true); + $badge = new badge($badgeid); + $badge->issue($this->student->id, true); + + // Hack the database to adjust the time each badge was issued. + $DB->set_field('badge_issued', 'dateissued', $now - 11, array('userid' => $this->student->id, 'badgeid' => $badgeid)); + + // Now a course badge. + $badge->id = null; + $badge->name = "Test badge course"; + $badge->description = "Testing badges course"; + $badge->type = BADGE_TYPE_COURSE; + $badge->courseid = $this->course->id; + + $badgeid = $DB->insert_record('badge', $badge, true); + $badge = new badge($badgeid); + $badge->issue($this->student->id, true); + + // Hack the database to adjust the time each badge was issued. + $DB->set_field('badge_issued', 'dateissued', $now - 11, array('userid' => $this->student->id, 'badgeid' => $badgeid)); + } + + /** + * Test get user badges. + * These is a basic test since the badges_get_my_user_badges used by the external function already has unit tests. + */ + public function test_get_my_user_badges() { + + $this->setUser($this->student); + + $result = core_badges_external::get_user_badges(); + $result = external_api::clean_returnvalue(core_badges_external::get_user_badges_returns(), $result); + $this->assertCount(2, $result['badges']); + + // Pagination and filtering. + $result = core_badges_external::get_user_badges(0, $this->course->id, 0, 1, '', true); + $result = external_api::clean_returnvalue(core_badges_external::get_user_badges_returns(), $result); + $this->assertCount(1, $result['badges']); + $this->assertEquals($this->course->id, $result['badges'][0]['courseid']); + } + + /** + * Test get user badges. + */ + public function test_get_other_user_badges() { + + $this->setUser($this->teacher); + + $result = core_badges_external::get_user_badges($this->student->id); + $result = external_api::clean_returnvalue(core_badges_external::get_user_badges_returns(), $result); + + $this->assertCount(2, $result['badges']); + + // Check that we don't have permissions for view the complete information for site badges. + foreach ($result['badges'] as $badge) { + if (isset($badge['type']) and $badge['type'] == BADGE_TYPE_COURSE) { + $this->assertTrue(isset($badge['message'])); + } else { + $this->assertFalse(isset($badge['message'])); + } + } + } +} diff --git a/lib/db/services.php b/lib/db/services.php index fcba61030e9..e08f0e1ef19 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -1195,6 +1195,15 @@ $functions = array( 'capabilities' => 'moodle/question:flag', ), + // Badges functions. + 'core_badges_get_user_badges' => array( + 'classname' => 'core_badges_external', + 'methodname' => 'get_user_badges', + 'description' => 'Returns the list of badges awarded to a user.', + 'type' => 'read', + 'capabilities' => 'moodle/badges:viewotherbadges' + ), + ); $services = array( @@ -1261,8 +1270,9 @@ $services = array( 'core_rating_get_item_ratings', 'core_user_get_users_by_field', 'core_user_add_user_private_files', - 'core_question_update_flag' - ), + 'core_question_update_flag', + 'core_badges_get_user_badges', + ), 'enabled' => 0, 'restrictedusers' => 0, 'shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE, diff --git a/version.php b/version.php index 8db8d21c47c..912229bf8e7 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2016032400.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2016032400.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes.