diff --git a/badges/classes/external.php b/badges/classes/external.php index 19a764d2610..15437d09c2f 100644 --- a/badges/classes/external.php +++ b/badges/classes/external.php @@ -124,9 +124,10 @@ class core_badges_external extends external_api { foreach ($userbadges as $badge) { $context = ($badge->type == BADGE_TYPE_SITE) ? context_system::instance() : context_course::instance($badge->courseid); + $canconfiguredetails = has_capability('moodle/badges:configuredetails', $context); // If the user is viewing another user's badge and doesn't have the right capability return only part of the data. - if ($USER->id != $user->id and !has_capability('moodle/badges:configuredetails', $context)) { + if ($USER->id != $user->id and !$canconfiguredetails) { $badge = (object) array( 'id' => $badge->id, 'name' => $badge->name, @@ -146,7 +147,40 @@ class core_badges_external extends external_api { ); } - $exporter = new user_badge_exporter($badge, array('context' => $context)); + // Create a badge instance to be able to get the endorsement and other info. + $badgeinstance = new badge($badge->id); + $endorsement = $badgeinstance->get_endorsement(); + $competencies = $badgeinstance->get_alignment(); + $relatedbadges = $badgeinstance->get_related_badges(); + + if (!$canconfiguredetails) { + // Return only the properties visible by the user. + + if (!empty($competencies)) { + foreach ($competencies as $competency) { + unset($competency->targetdescription); + unset($competency->targetframework); + unset($competency->targetcode); + } + } + + if (!empty($relatedbadges)) { + foreach ($relatedbadges as $relatedbadge) { + unset($relatedbadge->version); + unset($relatedbadge->language); + unset($relatedbadge->type); + } + } + } + + $related = array( + 'context' => $context, + 'endorsement' => $endorsement ? $endorsement : null, + 'competencies' => $competencies, + 'relatedbadges' => $relatedbadges, + ); + + $exporter = new user_badge_exporter($badge, $related); $result['badges'][] = $exporter->export($PAGE->get_renderer('core')); } diff --git a/badges/classes/external/competency_exporter.php b/badges/classes/external/competency_exporter.php new file mode 100644 index 00000000000..3eca46a2027 --- /dev/null +++ b/badges/classes/external/competency_exporter.php @@ -0,0 +1,94 @@ +. + +/** + * Contains competency class for displaying a badge competency. + * + * @package core_badges + * @copyright 2018 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_badges\external; + +defined('MOODLE_INTERNAL') || die(); + +use core\external\exporter; + +/** + * Class for displaying a badge competency. + * + * @package core_badges + * @copyright 2018 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class competency_exporter extends exporter { + + /** + * Return the list of properties. + * + * @return array + */ + protected static function define_properties() { + return [ + 'id' => [ + 'type' => PARAM_INT, + 'description' => 'Competency id', + ], + 'badgeid' => [ + 'type' => PARAM_INT, + 'description' => 'Badge id', + ], + 'targetname' => [ + 'type' => PARAM_TEXT, + 'description' => 'Target name', + ], + 'targeturl' => [ + 'type' => PARAM_URL, + 'description' => 'Target URL', + ], + 'targetdescription' => [ + 'type' => PARAM_TEXT, + 'description' => 'Target description', + 'null' => NULL_ALLOWED, + 'optional' => true, + ], + 'targetframework' => [ + 'type' => PARAM_TEXT, + 'description' => 'Target framework', + 'null' => NULL_ALLOWED, + 'optional' => true, + ], + 'targetcode' => [ + 'type' => PARAM_TEXT, + 'description' => 'Target code', + 'null' => NULL_ALLOWED, + 'optional' => true, + ] + ]; + } + + /** + * Returns a list of objects that are related. + * + * @return array + */ + protected static function define_related() { + return array( + 'context' => 'context', + ); + } +} diff --git a/badges/classes/external/endorsement_exporter.php b/badges/classes/external/endorsement_exporter.php new file mode 100644 index 00000000000..80e4ddeb670 --- /dev/null +++ b/badges/classes/external/endorsement_exporter.php @@ -0,0 +1,95 @@ +. + +/** + * Contains endorsement class for displaying a badge endorsement. + * + * @package core_badges + * @copyright 2018 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_badges\external; + +defined('MOODLE_INTERNAL') || die(); + +use core\external\exporter; + +/** + * Class for displaying a badge endorsement. + * + * @package core_badges + * @copyright 2018 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class endorsement_exporter extends exporter { + + /** + * Return the list of properties. + * + * @return array + */ + protected static function define_properties() { + return [ + 'id' => [ + 'type' => PARAM_INT, + 'description' => 'Endorsement id', + ], + 'badgeid' => [ + 'type' => PARAM_INT, + 'description' => 'Badge id', + ], + 'issuername' => [ + 'type' => PARAM_TEXT, + 'description' => 'Endorsement issuer name', + ], + 'issuerurl' => [ + 'type' => PARAM_URL, + 'description' => 'Endorsement issuer URL', + ], + 'issueremail' => [ + 'type' => PARAM_RAW, + 'description' => 'Endorsement issuer email', + ], + 'claimid' => [ + 'type' => PARAM_URL, + 'description' => 'Claim URL', + 'null' => NULL_ALLOWED, + ], + 'claimcomment' => [ + 'type' => PARAM_NOTAGS, + 'description' => 'Claim comment', + 'null' => NULL_ALLOWED, + ], + 'dateissued' => [ + 'type' => PARAM_INT, + 'description' => 'Date issued', + 'default' => 0, + ] + ]; + } + + /** + * Returns a list of objects that are related. + * + * @return array + */ + protected static function define_related() { + return array( + 'context' => 'context', + ); + } +} diff --git a/badges/classes/external/related_info_exporter.php b/badges/classes/external/related_info_exporter.php new file mode 100644 index 00000000000..83bee1e7c56 --- /dev/null +++ b/badges/classes/external/related_info_exporter.php @@ -0,0 +1,85 @@ +. + +/** + * Contains related class for displaying information of a related badge. + * + * @package core_badges + * @copyright 2018 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_badges\external; + +defined('MOODLE_INTERNAL') || die(); + +use core\external\exporter; + +/** + * Class for displaying information of a related badge. + * + * @package core_badges + * @copyright 2018 Dani Palou + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class related_info_exporter extends exporter { + + /** + * Return the list of properties. + * + * @return array + */ + protected static function define_properties() { + return [ + 'id' => [ + 'type' => PARAM_INT, + 'description' => 'Badge id', + ], + 'name' => [ + 'type' => PARAM_TEXT, + 'description' => 'Badge name', + ], + 'version' => [ + 'type' => PARAM_TEXT, + 'description' => 'Version', + 'optional' => true, + 'null' => NULL_ALLOWED, + ], + 'language' => [ + 'type' => PARAM_NOTAGS, + 'description' => 'Language', + 'optional' => true, + 'null' => NULL_ALLOWED, + ], + 'type' => [ + 'type' => PARAM_INT, + 'description' => 'Type', + 'optional' => true, + ], + ]; + } + + /** + * Returns a list of objects that are related. + * + * @return array + */ + protected static function define_related() { + return array( + 'context' => 'context', + ); + } +} diff --git a/badges/classes/external/user_badge_exporter.php b/badges/classes/external/user_badge_exporter.php index 0e284fb4a5d..0cc7269da3e 100644 --- a/badges/classes/external/user_badge_exporter.php +++ b/badges/classes/external/user_badge_exporter.php @@ -29,6 +29,9 @@ defined('MOODLE_INTERNAL') || die(); use core\external\exporter; use renderer_base; use moodle_url; +use core_badges\external\endorsement_exporter; +use core_badges\external\competency_exporter; +use core_badges\external\related_info_exporter; /** * Class for displaying a badge issued to a user. @@ -229,7 +232,10 @@ class user_badge_exporter extends exporter { */ protected static function define_related() { return array( - 'context' => 'context' + 'context' => 'context', + 'endorsement' => 'stdClass?', + 'competencies' => 'stdClass[]', + 'relatedbadges' => 'stdClass[]', ); } @@ -244,6 +250,21 @@ class user_badge_exporter extends exporter { 'type' => PARAM_URL, 'description' => 'Badge URL', ], + 'endorsement' => [ + 'type' => endorsement_exporter::read_properties_definition(), + 'description' => 'Badge endorsement', + 'optional' => true, + ], + 'competencies' => [ + 'type' => competency_exporter::read_properties_definition(), + 'description' => 'Badge competencies (alignment)', + 'multiple' => true, + ], + 'relatedbadges' => [ + 'type' => related_info_exporter::read_properties_definition(), + 'description' => 'Related badges', + 'multiple' => true, + ] ]; } @@ -255,12 +276,36 @@ class user_badge_exporter extends exporter { */ protected function get_other_values(renderer_base $output) { $context = $this->related['context']; + $endorsement = $this->related['endorsement']; + $competencies = $this->related['competencies']; + $relatedbadges = $this->related['relatedbadges']; $values = array( 'badgeurl' => moodle_url::make_webservice_pluginfile_url($context->id, 'badges', 'badgeimage', $this->data->id, '/', - 'f1')->out(false), + 'f1')->out(false), + 'competencies' => array(), + 'relatedbadges' => array(), ); + if ($endorsement) { + $endorsementexporter = new endorsement_exporter($endorsement, array('context' => $context)); + $values['endorsement'] = $endorsementexporter->export($output); + } + + if (!empty($competencies)) { + foreach ($competencies as $competency) { + $competencyexporter = new competency_exporter($competency, array('context' => $context)); + $values['competencies'][] = $competencyexporter->export($output); + } + } + + if (!empty($relatedbadges)) { + foreach ($relatedbadges as $badge) { + $relatedexporter = new related_info_exporter($badge, array('context' => $context)); + $values['relatedbadges'][] = $relatedexporter->export($output); + } + } + return $values; } } diff --git a/badges/tests/external_test.php b/badges/tests/external_test.php index 1176b9fa6c9..6cf9ad53584 100644 --- a/badges/tests/external_test.php +++ b/badges/tests/external_test.php @@ -99,6 +99,34 @@ class core_badges_external_testcase extends externallib_advanced_testcase { // 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)); + // Add an endorsement for the badge. + $endorsement = new stdClass(); + $endorsement->badgeid = $badgeid; + $endorsement->issuername = 'Issuer name'; + $endorsement->issuerurl = 'http://endorsement-issuer-url.domain.co.nz'; + $endorsement->issueremail = 'endorsementissuer@example.com'; + $endorsement->claimid = 'http://claim-url.domain.co.nz'; + $endorsement->claimcomment = 'Claim comment'; + $endorsement->dateissued = $now; + $badge->save_endorsement($endorsement); + + // Add 2 competencies. + $competency = new stdClass(); + $competency->badgeid = $badgeid; + $competency->targetname = 'Competency 1'; + $competency->targeturl = 'http://c1-target-url.domain.co.nz'; + $competency->targetdescription = 'C1 target description'; + $competency->targetframework = 'C1 framework'; + $competency->targetcode = 'C1 code'; + $badge->save_alignment($competency); + + $competency->targetname = 'Competency 2'; + $competency->targeturl = 'http://c2-target-url.domain.co.nz'; + $competency->targetdescription = 'C2 target description'; + $competency->targetframework = 'C2 framework'; + $competency->targetcode = 'C2 code'; + $badge->save_alignment($competency); + // Now a course badge. $badge->id = null; $badge->name = "Test badge course"; @@ -106,12 +134,15 @@ class core_badges_external_testcase extends externallib_advanced_testcase { $badge->type = BADGE_TYPE_COURSE; $badge->courseid = $this->course->id; - $badgeid = $DB->insert_record('badge', $badge, true); - $badge = new badge($badgeid); + $coursebadgeid = $DB->insert_record('badge', $badge, true); + $badge = new badge($coursebadgeid); $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)); + $DB->set_field('badge_issued', 'dateissued', $now - 11, array('userid' => $this->student->id, 'badgeid' => $coursebadgeid)); + + // Make the site badge a related badge. + $badge->add_related_badges(array($badgeid)); } /** @@ -130,6 +161,40 @@ class core_badges_external_testcase extends externallib_advanced_testcase { $badge->badgeurl = moodle_url::make_webservice_pluginfile_url($context->id, 'badges', 'badgeimage', $badge->id, '/', 'f1')->out(false); + // Get the endorsement, competencies and related badges. + $badgeinstance = new badge($badge->id); + $endorsement = $badgeinstance->get_endorsement(); + $competencies = $badgeinstance->get_alignment(); + $relatedbadges = $badgeinstance->get_related_badges(); + $badge->competencies = array(); + $badge->relatedbadges = array(); + + if ($endorsement) { + $badge->endorsement = (array) $endorsement; + } + + if (!empty($competencies)) { + foreach ($competencies as $competency) { + // Students cannot see some fields of the competencies. + unset($competency->targetdescription); + unset($competency->targetframework); + unset($competency->targetcode); + + $badge->competencies[] = (array) $competency; + } + } + + if (!empty($relatedbadges)) { + foreach ($relatedbadges as $relatedbadge) { + // Students cannot see some fields of the related badges. + unset($relatedbadge->version); + unset($relatedbadge->language); + unset($relatedbadge->type); + + $badge->relatedbadges[] = (array) $relatedbadge; + } + } + $expectedbadges[] = (array) $badge; } @@ -160,6 +225,15 @@ class core_badges_external_testcase extends externallib_advanced_testcase { foreach ($result['badges'] as $badge) { if (isset($badge['type']) and $badge['type'] == BADGE_TYPE_COURSE) { $this->assertTrue(isset($badge['message'])); + + // Check that we have permissions to see all the data in competencies and related badges. + foreach ($badge['competencies'] as $competency) { + $this->assertTrue(isset($competency['targetdescription'])); + } + + foreach ($badge['relatedbadges'] as $relatedbadge) { + $this->assertTrue(isset($relatedbadge['type'])); + } } else { $this->assertFalse(isset($badge['message'])); } diff --git a/badges/upgrade.txt b/badges/upgrade.txt index 8dd1f87f7c8..8b2039407c3 100644 --- a/badges/upgrade.txt +++ b/badges/upgrade.txt @@ -1,6 +1,10 @@ This files describes API changes in /badges/*, information provided here is intended especially for developers. +=== 3.6 === + +* The WebService core_badges_get_user_badges now returns more information for each badge: notification, nextcron, email, version, language, imageauthorname, imageauthoremail, imageauthorurl, imagecaption, endorsement, competencies and relatedbadges. + === 2.7 === * get_completed_criteria_sql() - This method was added to award_criteria class and must be overriden