From b2f66d477bb212a0786371e8cf1c0d545ddfbb7f Mon Sep 17 00:00:00 2001 From: Sara Arjona Date: Fri, 28 Jun 2024 12:58:35 +0200 Subject: [PATCH] MDL-70983 badges: Remove OBv1.0 support The only backpack implementing OBv1.0 was Mozilla Backpack. It closed in 2019 and their badges were moved to https://backpack.openbadges.org/ by Badgr. However, as Badgr is supporting OBv2.0 too, it makes no sense keep OBv1.0 implementation in Moodle: it has caused some issues and over-complicates current code. --- .upgradenotes/MDL-70983-2024062810515930.yml | 7 + badges/classes/assertion.php | 42 +- badges/classes/backpack_api.php | 512 ++++++------------ badges/classes/backpack_api_mapping.php | 34 +- badges/classes/badge.php | 39 +- .../classes/external/collection_exporter.php | 19 +- badges/classes/external/issuer_exporter.php | 18 +- badges/classes/form/collections.php | 32 +- badges/classes/form/external_backpack.php | 13 +- badges/issuer_json.php | 8 +- badges/tests/badgeslib_test.php | 38 +- badges/tests/behat/backpack.feature | 6 +- lib/badgeslib.php | 10 +- 13 files changed, 239 insertions(+), 539 deletions(-) create mode 100644 .upgradenotes/MDL-70983-2024062810515930.yml diff --git a/.upgradenotes/MDL-70983-2024062810515930.yml b/.upgradenotes/MDL-70983-2024062810515930.yml new file mode 100644 index 0000000000000..df52839ac011b --- /dev/null +++ b/.upgradenotes/MDL-70983-2024062810515930.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-70983 +notes: + core_badges: + - message: Final removal of BADGE_BACKPACKAPIURL and BADGE_BACKPACKWEBURL. + type: removed + - message: OPEN_BADGES_V1 is deprecated and should not be used anymore. + type: deprecated diff --git a/badges/classes/assertion.php b/badges/classes/assertion.php index 9a54c1300c930..4021c9d1e91b5 100644 --- a/badges/classes/assertion.php +++ b/badges/classes/assertion.php @@ -14,22 +14,13 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Badge assertion library. - * - * @package core - * @subpackage 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 - */ - defined('MOODLE_INTERNAL') || die(); /** - * Open Badges Assertions specification 1.0 {@link https://github.com/mozilla/openbadges-backpack/wiki/Assertions} + * Open Badges Assertions specification 2.0 + * {@link https://www.imsglobal.org/sites/default/files/Badges/OBv2p0Final/index.html#Assertion} * - * Badge asserion is defined by three parts: + * Badge assertion is defined by three parts: * - Badge Assertion (information regarding a specific badge that was awarded to a badge earner) * - Badge Class (general information about a badge and what it is intended to represent) * - Issuer Class (general information of an issuing organisation) @@ -40,6 +31,10 @@ /** * Class that represents badge assertion. * + * @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 */ class core_badges_assertion { /** @var object Issued badge information from database */ @@ -205,7 +200,7 @@ public function get_badge_class($issued = true) { $badgeurl = new moodle_url('/badges/badgeclass.php', $params); $class['criteria'] = $badgeurl->out(false); // Currently badge URL. if ($issued) { - $params = ['id' => $this->get_badge_id(), 'obversion' => $this->_obversion]; + $params = ['id' => $this->get_badge_id()]; $issuerurl = new moodle_url('/badges/issuer_json.php', $params); $class['issuer'] = $issuerurl->out(false); } @@ -227,24 +222,9 @@ public function get_badge_class($issued = true) { * @return array Issuer information. */ public function get_issuer() { - global $CFG; - $issuer = array(); - if ($this->_data) { - // Required. - if ($this->_obversion == OPEN_BADGES_V1) { - $issuer['name'] = $this->_data->issuername; - $issuer['url'] = $this->_data->issuerurl; - // Optional. - if (!empty($this->_data->issuercontact)) { - $issuer['email'] = $this->_data->issuercontact; - } else { - $issuer['email'] = $CFG->badges_defaultissuercontact; - } - } else { - $badge = new badge($this->get_badge_id()); - $issuer = $badge->get_badge_issuer(); - } - } + $badge = new badge($this->get_badge_id()); + $issuer = $badge->get_badge_issuer(); + $this->embed_data_badge_version2($issuer, OPEN_BADGES_V2_TYPE_ISSUER); return $issuer; } diff --git a/badges/classes/backpack_api.php b/badges/classes/backpack_api.php index 08e5ba3399792..1b6901235c1e4 100644 --- a/badges/classes/backpack_api.php +++ b/badges/classes/backpack_api.php @@ -14,14 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Communicate with backpacks. - * - * @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 - */ - namespace core_badges; defined('MOODLE_INTERNAL') || die(); @@ -30,11 +22,8 @@ use cache; use coding_exception; -use core_badges\external\assertion_exporter; -use core_badges\external\collection_exporter; use core_badges\external\issuer_exporter; use core_badges\external\badgeclass_exporter; -use curl; use stdClass; use context_system; @@ -47,7 +36,8 @@ /** * Class for communicating with backpacks. * - * @package core_badges + * @package core_badges + * @author Yuliya Bozhko * @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 */ @@ -71,7 +61,7 @@ class backpack_api { /** @var integer The id of the backpack we are talking to. */ private $backpackid; - /** @var \backpack_api_mapping[] List of apis for the user or site using api version 1 or 2. */ + /** @var \core_badges\backpack_api_mapping[] List of apis for the user or site using api version 2. */ private $mappings = []; /** @@ -108,199 +98,137 @@ public function __construct($sitebackpack, $userbackpack = false) { * Define the mappings supported by this usage and api version. */ private function define_mappings() { - if ($this->backpackapiversion == OPEN_BADGES_V2) { - if ($this->isuserbackpack) { - $mapping = []; - $mapping[] = [ - 'collections', // Action. - '[URL]/backpack/collections', // URL - [], // Post params. - '', // Request exporter. - 'core_badges\external\collection_exporter', // Response exporter. - true, // Multiple. - 'get', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - $mapping[] = [ - 'user', // Action. - '[SCHEME]://[HOST]/o/token', // URL - ['username' => '[EMAIL]', 'password' => '[PASSWORD]'], // Post params. - '', // Request exporter. - 'oauth_token_response', // Response exporter. - false, // Multiple. - 'post', // Method. - false, // JSON Encoded. - false, // Auth required. - ]; - $mapping[] = [ - 'assertion', // Action. - // Badgr.io does not return the public information about a badge - // if the issuer is associated with another user. We need to pass - // the expand parameters which are not in any specification to get - // additional information about the assertion in a single request. - '[URL]/backpack/assertions/[PARAM2]?expand=badgeclass&expand=issuer', - [], // Post params. - '', // Request exporter. - 'core_badges\external\assertion_exporter', // Response exporter. - false, // Multiple. - 'get', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - $mapping[] = [ - 'importbadge', // Action. - // Badgr.io does not return the public information about a badge - // if the issuer is associated with another user. We need to pass - // the expand parameters which are not in any specification to get - // additional information about the assertion in a single request. - '[URL]/backpack/import', - ['url' => '[PARAM]'], // Post params. - '', // Request exporter. - 'core_badges\external\assertion_exporter', // Response exporter. - false, // Multiple. - 'post', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - $mapping[] = [ - 'badges', // Action. - '[URL]/backpack/collections/[PARAM1]', // URL - [], // Post params. - '', // Request exporter. - 'core_badges\external\collection_exporter', // Response exporter. - true, // Multiple. - 'get', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - foreach ($mapping as $map) { - $map[] = true; // User api function. - $map[] = OPEN_BADGES_V2; // V2 function. - $this->mappings[] = new backpack_api_mapping(...$map); - } - } else { - $mapping = []; - $mapping[] = [ - 'user', // Action. - '[SCHEME]://[HOST]/o/token', // URL - ['username' => '[EMAIL]', 'password' => '[PASSWORD]'], // Post params. - '', // Request exporter. - 'oauth_token_response', // Response exporter. - false, // Multiple. - 'post', // Method. - false, // JSON Encoded. - false // Auth required. - ]; - $mapping[] = [ - 'issuers', // Action. - '[URL]/issuers', // URL - '[PARAM]', // Post params. - 'core_badges\external\issuer_exporter', // Request exporter. - 'core_badges\external\issuer_exporter', // Response exporter. - false, // Multiple. - 'post', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - $mapping[] = [ - 'badgeclasses', // Action. - '[URL]/issuers/[PARAM2]/badgeclasses', // URL - '[PARAM]', // Post params. - 'core_badges\external\badgeclass_exporter', // Request exporter. - 'core_badges\external\badgeclass_exporter', // Response exporter. - false, // Multiple. - 'post', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - $mapping[] = [ - 'assertions', // Action. - '[URL]/badgeclasses/[PARAM2]/assertions', // URL - '[PARAM]', // Post params. - 'core_badges\external\assertion_exporter', // Request exporter. - 'core_badges\external\assertion_exporter', // Response exporter. - false, // Multiple. - 'post', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - $mapping[] = [ - 'updateassertion', // Action. - '[URL]/assertions/[PARAM2]?expand=badgeclass&expand=issuer', - '[PARAM]', // Post params. - 'core_badges\external\assertion_exporter', // Request exporter. - 'core_badges\external\assertion_exporter', // Response exporter. - false, // Multiple. - 'put', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - foreach ($mapping as $map) { - $map[] = false; // Site api function. - $map[] = OPEN_BADGES_V2; // V2 function. - $this->mappings[] = new backpack_api_mapping(...$map); - } + if ($this->isuserbackpack) { + $mapping = []; + $mapping[] = [ + 'collections', // Action. + '[URL]/backpack/collections', // URL. + [], // Post params. + '', // Request exporter. + 'core_badges\external\collection_exporter', // Response exporter. + true, // Multiple. + 'get', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + $mapping[] = [ + 'user', // Action. + '[SCHEME]://[HOST]/o/token', // URL. + ['username' => '[EMAIL]', 'password' => '[PASSWORD]'], // Post params. + '', // Request exporter. + 'oauth_token_response', // Response exporter. + false, // Multiple. + 'post', // Method. + false, // JSON Encoded. + false, // Auth required. + ]; + $mapping[] = [ + 'assertion', // Action. + // Badgr.io does not return the public information about a badge + // if the issuer is associated with another user. We need to pass + // the expand parameters which are not in any specification to get + // additional information about the assertion in a single request. + '[URL]/backpack/assertions/[PARAM2]?expand=badgeclass&expand=issuer', + [], // Post params. + '', // Request exporter. + 'core_badges\external\assertion_exporter', // Response exporter. + false, // Multiple. + 'get', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + $mapping[] = [ + 'importbadge', // Action. + // Badgr.io does not return the public information about a badge + // if the issuer is associated with another user. We need to pass + // the expand parameters which are not in any specification to get + // additional information about the assertion in a single request. + '[URL]/backpack/import', + ['url' => '[PARAM]'], // Post params. + '', // Request exporter. + 'core_badges\external\assertion_exporter', // Response exporter. + false, // Multiple. + 'post', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + $mapping[] = [ + 'badges', // Action. + '[URL]/backpack/collections/[PARAM1]', // URL. + [], // Post params. + '', // Request exporter. + 'core_badges\external\collection_exporter', // Response exporter. + true, // Multiple. + 'get', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + foreach ($mapping as $map) { + $map[] = true; // User api function. + $map[] = OPEN_BADGES_V2; // V2 function. + $this->mappings[] = new backpack_api_mapping(...$map); } } else { - if ($this->isuserbackpack) { - $mapping = []; - $mapping[] = [ - 'user', // Action. - '[URL]/displayer/convert/email', // URL - ['email' => '[EMAIL]'], // Post params. - '', // Request exporter. - 'convert_email_response', // Response exporter. - false, // Multiple. - 'post', // Method. - false, // JSON Encoded. - false // Auth required. - ]; - $mapping[] = [ - 'groups', // Action. - '[URL]/displayer/[PARAM1]/groups.json', // URL - [], // Post params. - '', // Request exporter. - '', // Response exporter. - false, // Multiple. - 'get', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - $mapping[] = [ - 'badges', // Action. - '[URL]/displayer/[PARAM2]/group/[PARAM1].json', // URL - [], // Post params. - '', // Request exporter. - '', // Response exporter. - false, // Multiple. - 'get', // Method. - true, // JSON Encoded. - true // Auth required. - ]; - foreach ($mapping as $map) { - $map[] = true; // User api function. - $map[] = OPEN_BADGES_V1; // V1 function. - $this->mappings[] = new backpack_api_mapping(...$map); - } - } else { - $mapping = []; - $mapping[] = [ - 'user', // Action. - '[URL]/displayer/convert/email', // URL - ['email' => '[EMAIL]'], // Post params. - '', // Request exporter. - 'convert_email_response', // Response exporter. - false, // Multiple. - 'post', // Method. - false, // JSON Encoded. - false // Auth required. - ]; - foreach ($mapping as $map) { - $map[] = false; // Site api function. - $map[] = OPEN_BADGES_V1; // V1 function. - $this->mappings[] = new backpack_api_mapping(...$map); - } + $mapping = []; + $mapping[] = [ + 'user', // Action. + '[SCHEME]://[HOST]/o/token', // URL. + ['username' => '[EMAIL]', 'password' => '[PASSWORD]'], // Post params. + '', // Request exporter. + 'oauth_token_response', // Response exporter. + false, // Multiple. + 'post', // Method. + false, // JSON Encoded. + false, // Auth required. + ]; + $mapping[] = [ + 'issuers', // Action. + '[URL]/issuers', // URL. + '[PARAM]', // Post params. + 'core_badges\external\issuer_exporter', // Request exporter. + 'core_badges\external\issuer_exporter', // Response exporter. + false, // Multiple. + 'post', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + $mapping[] = [ + 'badgeclasses', // Action. + '[URL]/issuers/[PARAM2]/badgeclasses', // URL. + '[PARAM]', // Post params. + 'core_badges\external\badgeclass_exporter', // Request exporter. + 'core_badges\external\badgeclass_exporter', // Response exporter. + false, // Multiple. + 'post', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + $mapping[] = [ + 'assertions', // Action. + '[URL]/badgeclasses/[PARAM2]/assertions', // URL. + '[PARAM]', // Post params. + 'core_badges\external\assertion_exporter', // Request exporter. + 'core_badges\external\assertion_exporter', // Response exporter. + false, // Multiple. + 'post', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + $mapping[] = [ + 'updateassertion', // Action. + '[URL]/assertions/[PARAM2]?expand=badgeclass&expand=issuer', + '[PARAM]', // Post params. + 'core_badges\external\assertion_exporter', // Request exporter. + 'core_badges\external\assertion_exporter', // Response exporter. + false, // Multiple. + 'put', // Method. + true, // JSON Encoded. + true, // Auth required. + ]; + foreach ($mapping as $map) { + $map[] = false; // Site api function. + $map[] = OPEN_BADGES_V2; // V2 function. + $this->mappings[] = new backpack_api_mapping(...$map); } } } @@ -315,20 +243,6 @@ private function define_mappings() { * @return mixed */ private function curl_request($action, $collection = null, $entityid = null, $postdata = null) { - global $CFG, $SESSION; - - $curl = new curl(); - $authrequired = false; - if ($this->backpackapiversion == OPEN_BADGES_V1) { - $useridkey = $this->get_token_key(BADGE_USER_ID_TOKEN); - if (isset($SESSION->$useridkey)) { - if ($collection == null) { - $collection = $SESSION->$useridkey; - } else { - $entityid = $SESSION->$useridkey; - } - } - } foreach ($this->mappings as $mapping) { if ($mapping->is_match($action)) { return $mapping->request( @@ -380,25 +294,6 @@ private function get_token_key($type) { return $prefix; } - /** - * Normalise the return from a missing user request. - * - * @param string $status - * @return mixed - */ - private function check_status($status) { - // V1 ONLY. - switch($status) { - case "missing": - $response = array( - 'status' => $status, - 'message' => get_string('error:nosuchuser', 'badges') - ); - return $response; - } - return false; - } - /** * Make an api request to get an assertion * @@ -406,11 +301,6 @@ private function check_status($status) { * @return mixed */ public function get_assertion($entityid) { - // V2 Only. - if ($this->backpackapiversion == OPEN_BADGES_V1) { - throw new coding_exception('Not supported in this backpack API'); - } - return $this->curl_request('assertion', null, $entityid); } @@ -422,11 +312,6 @@ public function get_assertion($entityid) { * @return mixed */ public function put_badgeclass_assertion($entityid, $data) { - // V2 Only. - if ($this->backpackapiversion == OPEN_BADGES_V1) { - throw new coding_exception('Not supported in this backpack API'); - } - return $this->curl_request('assertions', null, $entityid, $data); } @@ -438,11 +323,6 @@ public function put_badgeclass_assertion($entityid, $data) { * @return mixed */ public function update_assertion(string $entityid, array $data) { - // V2 Only. - if ($this->backpackapiversion == OPEN_BADGES_V1) { - throw new coding_exception('Not supported in this backpack API'); - } - return $this->curl_request('updateassertion', null, $entityid, $data); } @@ -454,11 +334,6 @@ public function update_assertion(string $entityid, array $data) { * @throws coding_exception */ public function import_badge_assertion(string $data) { - // V2 Only. - if ($this->backpackapiversion == OPEN_BADGES_V1) { - throw new coding_exception('Not supported in this backpack API'); - } - return $this->curl_request('importbadge', null, null, $data); } @@ -482,12 +357,8 @@ public function set_backpack_collections($backpackid, $collections) { foreach ($collections as $collection) { $obj = new stdClass(); $obj->backpackid = $backpackid; - if ($this->backpackapiversion == OPEN_BADGES_V1) { - $obj->collectionid = (int) $collection; - } else { - $obj->entityid = $collection; - $obj->collectionid = -1; - } + $obj->entityid = $collection; + $obj->collectionid = -1; if (!$DB->record_exists('badge_external', (array) $obj)) { $DB->insert_record('badge_external', $obj); } @@ -504,11 +375,6 @@ public function set_backpack_collections($backpackid, $collections) { * @return mixed */ public function put_badgeclass($entityid, $data) { - // V2 Only. - if ($this->backpackapiversion == OPEN_BADGES_V1) { - throw new coding_exception('Not supported in this backpack API'); - } - return $this->curl_request('badgeclasses', null, $entityid, $data); } @@ -519,11 +385,6 @@ public function put_badgeclass($entityid, $data) { * @return mixed */ public function put_issuer($data) { - // V2 Only. - if ($this->backpackapiversion == OPEN_BADGES_V1) { - throw new coding_exception('Not supported in this backpack API'); - } - return $this->curl_request('issuers', null, null, $data); } @@ -586,17 +447,8 @@ public function authenticate() { * @return stdClass[] The collections. */ public function get_collections() { - global $PAGE; - if ($this->authenticate()) { - if ($this->backpackapiversion == OPEN_BADGES_V1) { - $result = $this->curl_request('groups'); - if (isset($result->groups)) { - $result = $result->groups; - } - } else { - $result = $this->curl_request('collections'); - } + $result = $this->curl_request('collections'); if ($result) { return $result; } @@ -608,16 +460,12 @@ public function get_collections() { * Get one collection by id. * * @param integer $collectionid - * @return stdClass The collection. + * @return array The collection. */ public function get_collection_record($collectionid) { global $DB; - if ($this->backpackapiversion == OPEN_BADGES_V1) { - return $DB->get_fieldset_select('badge_external', 'collectionid', 'backpackid = :bid', array('bid' => $collectionid)); - } else { - return $DB->get_fieldset_select('badge_external', 'entityid', 'backpackid = :bid', array('bid' => $collectionid)); - } + return $DB->get_fieldset_select('badge_external', 'entityid', 'backpackid = :bid', ['bid' => $collectionid]); } /** @@ -652,11 +500,7 @@ public function disconnect_backpack($userid, $backpackid) { * @return string The collection id. */ public function get_collection_id_from_response($data) { - if ($this->backpackapiversion == OPEN_BADGES_V1) { - return $data->groupId; - } else { - return $data->entityId; - } + return $data->entityId; } /** @@ -679,52 +523,46 @@ public function get_badges($collection, $expanded = false) { global $PAGE; if ($this->authenticate()) { - if ($this->backpackapiversion == OPEN_BADGES_V1) { - if (empty($collection->collectionid)) { - return []; - } - $result = $this->curl_request('badges', $collection->collectionid); - return $result->badges; - } else { - if (empty($collection->entityid)) { - return []; - } - // Now we can make requests. - $badges = $this->curl_request('badges', $collection->entityid); - if (count($badges) == 0) { - return []; - } - $badges = $badges[0]; - if ($expanded) { - $publicassertions = []; - $context = context_system::instance(); - $output = $PAGE->get_renderer('core', 'badges'); - foreach ($badges->assertions as $assertion) { - $remoteassertion = $this->get_assertion($assertion); - // Remote badge was fetched nested in the assertion. - $remotebadge = $remoteassertion->badgeclass; - if (!$remotebadge) { - continue; - } - $apidata = badgeclass_exporter::map_external_data($remotebadge, $this->backpackapiversion); - $exporterinstance = new badgeclass_exporter($apidata, ['context' => $context]); - $remotebadge = $exporterinstance->export($output); - - $remoteissuer = $remotebadge->issuer; - $apidata = issuer_exporter::map_external_data($remoteissuer, $this->backpackapiversion); - $exporterinstance = new issuer_exporter($apidata, ['context' => $context]); - $remoteissuer = $exporterinstance->export($output); - - $badgeclone = clone $remotebadge; - $badgeclone->issuer = $remoteissuer; - $remoteassertion->badge = $badgeclone; - $remotebadge->assertion = $remoteassertion; - $publicassertions[] = $remotebadge; + if (empty($collection->entityid)) { + return []; + } + // Now we can make requests. + $badges = $this->curl_request('badges', $collection->entityid); + if (count($badges) == 0) { + return []; + } + $badges = $badges[0]; + if ($expanded) { + $publicassertions = []; + $context = context_system::instance(); + $output = $PAGE->get_renderer('core', 'badges'); + foreach ($badges->assertions as $assertion) { + $remoteassertion = $this->get_assertion($assertion); + // Remote badge was fetched nested in the assertion. + $remotebadge = $remoteassertion->badgeclass; + if (!$remotebadge) { + continue; } - $badges = $publicassertions; + $apidata = badgeclass_exporter::map_external_data($remotebadge, $this->backpackapiversion); + $exporterinstance = new badgeclass_exporter($apidata, ['context' => $context]); + $remotebadge = $exporterinstance->export($output); + + $remoteissuer = $remotebadge->issuer; + $apidata = issuer_exporter::map_external_data($remoteissuer, $this->backpackapiversion); + $exporterinstance = new issuer_exporter($apidata, ['context' => $context]); + $remoteissuer = $exporterinstance->export($output); + + $badgeclone = clone $remotebadge; + $badgeclone->issuer = $remoteissuer; + $remoteassertion->badge = $badgeclone; + $remotebadge->assertion = $remoteassertion; + $publicassertions[] = $remotebadge; } - return $badges; + $badges = $publicassertions; } + return $badges; } + + return []; } } diff --git a/badges/classes/backpack_api_mapping.php b/badges/classes/backpack_api_mapping.php index 36ec0bc2e2865..10802a93cafb3 100644 --- a/badges/classes/backpack_api_mapping.php +++ b/badges/classes/backpack_api_mapping.php @@ -31,10 +31,6 @@ require_once($CFG->libdir . '/filelib.php'); use context_system; -use core_badges\external\assertion_exporter; -use core_badges\external\collection_exporter; -use core_badges\external\issuer_exporter; -use core_badges\external\badgeclass_exporter; use curl; /** @@ -82,7 +78,7 @@ class backpack_api_mapping { /** @var mixed List of parameters for this method. */ protected $postparams; - /** @var int OpenBadges version 1 or 2. */ + /** @var int OpenBadges version. */ protected $backpackapiversion; /** @@ -98,7 +94,7 @@ class backpack_api_mapping { * @param boolean $json json decode the response. * @param boolean $authrequired Authentication is required for this request. * @param boolean $isuserbackpack user backpack or a site backpack. - * @param integer $backpackapiversion OpenBadges version 1 or 2. + * @param integer $backpackapiversion OpenBadges version. */ public function __construct($action, $url, $postparams, $requestexporter, $responseexporter, $multiple, $method, $json, $authrequired, $isuserbackpack, $backpackapiversion) { @@ -233,32 +229,6 @@ private function get_post_params($email, $password, $param) { return $request; } - /** - * Read the response from a V1 user request and save the userID. - * - * @param string $response The request response. - * @param integer $backpackid The backpack id. - * @return mixed - */ - private function convert_email_response($response, $backpackid) { - global $SESSION; - - if (isset($response->status) && $response->status == 'okay') { - - // Remember the tokens. - $useridkey = $this->get_token_key(BADGE_USER_ID_TOKEN); - $backpackidkey = $this->get_token_key(BADGE_BACKPACK_ID_TOKEN); - - $SESSION->$useridkey = $response->userId; - $SESSION->$backpackidkey = $backpackid; - return $response->userId; - } - if (!empty($response->error)) { - self::set_authentication_error($response->error); - } - return false; - } - /** * Get the user id from a previous user request. * diff --git a/badges/classes/badge.php b/badges/classes/badge.php index ecf48de8ff77e..6ecc87fee30a5 100644 --- a/badges/classes/badge.php +++ b/badges/classes/badge.php @@ -14,16 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Badge assertion library. - * - * @package core - * @subpackage 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 - */ - namespace core_badges; defined('MOODLE_INTERNAL') || die(); @@ -44,8 +34,10 @@ /** * Class that represents badge. * + * @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 */ class badge { /** @var int Badge id */ @@ -954,25 +946,14 @@ public function markdown_badge_criteria() { * @return array Issuer informations of the badge. */ public function get_badge_issuer(?int $obversion = null) { - global $DB; - - $issuer = []; - if ($obversion == OPEN_BADGES_V1) { - $data = $DB->get_record('badge', ['id' => $this->id]); - $issuer['name'] = $data->issuername; - $issuer['url'] = $data->issuerurl; - $issuer['email'] = $data->issuercontact; - } else { - $issuer['name'] = $this->issuername; - $issuer['url'] = $this->issuerurl; - $issuer['email'] = $this->issuercontact; - $issuer['@context'] = OPEN_BADGES_V2_CONTEXT; - $issueridurl = new moodle_url('/badges/issuer_json.php', array('id' => $this->id)); - $issuer['id'] = $issueridurl->out(false); - $issuer['type'] = OPEN_BADGES_V2_TYPE_ISSUER; - } - - return $issuer; + return [ + 'name' => $this->issuername, + 'url' => $this->issuerurl, + 'email' => $this->issuercontact, + '@context' => OPEN_BADGES_V2_CONTEXT, + 'id' => (new moodle_url('/badges/issuer_json.php', ['id' => $this->id]))->out(false), + 'type' => OPEN_BADGES_V2_TYPE_ISSUER, + ]; } /** diff --git a/badges/classes/external/collection_exporter.php b/badges/classes/external/collection_exporter.php index ac79f98ee4cfd..866dc59d40f9c 100644 --- a/badges/classes/external/collection_exporter.php +++ b/badges/classes/external/collection_exporter.php @@ -14,14 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Contains class for displaying a collection. - * - * @package core_badges - * @copyright 2019 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - namespace core_badges\external; defined('MOODLE_INTERNAL') || die(); @@ -30,7 +22,7 @@ use stdClass; /** - * Class for displaying a badge competency. + * Class for displaying a badge collection. * * @package core_badges * @copyright 2019 Damyon Wiese @@ -46,15 +38,6 @@ class collection_exporter extends exporter { * @return stdClass */ public static function map_external_data($data, $apiversion) { - if ($apiversion == OPEN_BADGES_V1) { - $result = new stdClass(); - $result->entityType = 'BackpackCollection'; - $result->entityId = $data->groupId; - $result->name = $data->name; - $result->description = $data->description; - $result->assertions = []; - return $result; - } return $data; } diff --git a/badges/classes/external/issuer_exporter.php b/badges/classes/external/issuer_exporter.php index d741031e58e04..3529d33e15fcf 100644 --- a/badges/classes/external/issuer_exporter.php +++ b/badges/classes/external/issuer_exporter.php @@ -14,14 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Contains class for displaying a issuer. - * - * @package core_badges - * @copyright 2019 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - namespace core_badges\external; defined('MOODLE_INTERNAL') || die(); @@ -38,17 +30,13 @@ class issuer_exporter extends exporter { /** - * Either map version 1 data to version 2 or return it untouched. + * Map data depending on the version. * - * @param stdClass $data The remote data. + * @param \stdClass $data The remote data. * @param string $apiversion The backpack version used to communicate remotely. - * @return stdClass + * @return \stdClass */ public static function map_external_data($data, $apiversion) { - if ($apiversion == OPEN_BADGES_V1) { - $result = new \stdClass(); - return $result; - } $mapped = new \stdClass(); if (isset($data->entityType)) { $mapped->type = $data->entityType; diff --git a/badges/classes/form/collections.php b/badges/classes/form/collections.php index d9f08368f4576..74a08325e4e95 100644 --- a/badges/classes/form/collections.php +++ b/badges/classes/form/collections.php @@ -14,16 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Form class for mybackpack.php - * - * @package core - * @subpackage 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 - */ - namespace core_badges\form; defined('MOODLE_INTERNAL') || die(); @@ -37,8 +27,10 @@ /** * Form to select backpack collections. * + * @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 */ class collections extends moodleform { @@ -79,22 +71,12 @@ public function definition() { foreach ($groups as $group) { $count = 0; // Handle attributes based on backpack's supported version. - if ($sitebackpack->apiversion == OPEN_BADGES_V2) { - // OpenBadges v2 data attributes. - if (empty($group->published)) { - // Only public collections. - continue; - } - - // Get the number of badges associated with this collection from the assertions array returned. - $count = count($group->assertions); - } else { - // OpenBadges v1 data attributes. - $group->entityId = $group->groupId; - - // Get the number of badges associated with this collection. In that case, the number is returned directly. - $count = $group->badges; + if (empty($group->published)) { + // Only public collections. + continue; } + // Get the number of badges associated with this collection from the assertions array returned. + $count = count($group->assertions); if (!$hasgroups) { $mform->addElement('static', 'selectgroup', '', get_string('selectgroup_start', 'badges')); diff --git a/badges/classes/form/external_backpack.php b/badges/classes/form/external_backpack.php index af099e14bec09..57da76ba4c288 100644 --- a/badges/classes/form/external_backpack.php +++ b/badges/classes/form/external_backpack.php @@ -14,15 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * External backpack form - * - * @package core_badges - * @copyright 2019 Damyon Wiese - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - namespace core_badges\form; + defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir.'/formslib.php'); @@ -93,8 +86,8 @@ public function definition() { $mform->hideIf('backpackemail', 'includeauthdetails'); $mform->hideIf('backpackemail', 'apiversion', 'in', [OPEN_BADGES_V2P1]); $mform->hideIf('password', 'includeauthdetails'); - $mform->hideIf('password', 'apiversion', 'in', [OPEN_BADGES_V1, OPEN_BADGES_V2P1]); - $mform->hideIf('backpackapiurl', 'apiversion', 'in', [OPEN_BADGES_V1, OPEN_BADGES_V2P1]); + $mform->hideIf('password', 'apiversion', 'in', [OPEN_BADGES_V2P1]); + $mform->hideIf('backpackapiurl', 'apiversion', 'in', [OPEN_BADGES_V2P1]); // Disable short forms. $mform->setDisableShortforms(); diff --git a/badges/issuer_json.php b/badges/issuer_json.php index 87fe6bd417e7c..366df384f14fb 100644 --- a/badges/issuer_json.php +++ b/badges/issuer_json.php @@ -17,8 +17,7 @@ /** * Serve Issuer JSON for related badge or default Issuer if no badge is defined. * - * @package core - * @subpackage badges + * @package core_badges * @copyright 2020 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -28,10 +27,7 @@ require_once(__DIR__ . '/../config.php'); require_once($CFG->libdir . '/badgeslib.php'); - $id = optional_param('id', null, PARAM_INT); -// OB specification version. If it's not defined, the site will be used as default. -$obversion = optional_param('obversion', badges_open_badges_backpack_api(), PARAM_INT); if (empty($id)) { // Get the default issuer for this site. @@ -40,7 +36,7 @@ // Get the issuer for this badge. $badge = new badge($id); if ($badge->status != BADGE_STATUS_INACTIVE) { - $json = $badge->get_badge_issuer($obversion); + $json = $badge->get_badge_issuer(); } else { // The badge doen't exist or not accessible for the users. header("HTTP/1.0 410 Gone"); diff --git a/badges/tests/badgeslib_test.php b/badges/tests/badgeslib_test.php index 834c026fa5c67..1b14b5a961f8b 100644 --- a/badges/tests/badgeslib_test.php +++ b/badges/tests/badgeslib_test.php @@ -14,16 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Unit tests for badges - * - * @package core - * @subpackage badges - * @copyright 2013 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 - */ - defined('MOODLE_INTERNAL') || die(); global $CFG; @@ -33,6 +23,14 @@ use core_badges\helper; use core\task\manager; +/** + * Unit tests for badges + * + * @package core_badges + * @copyright 2013 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 + */ class badgeslib_test extends advanced_testcase { protected $badgeid; protected $course; @@ -907,10 +905,10 @@ public function test_badges_assertion(): void { $badge = new badge($this->coursebadge); $this->assertFalse($badge->is_issued($this->user->id)); - $criteria_overall = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id)); - $criteria_overall->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ANY)); - $criteria_overall1 = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_PROFILE, 'badgeid' => $badge->id)); - $criteria_overall1->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ALL, 'field_address' => 'address')); + $criteriaoverall = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id]); + $criteriaoverall->save(['agg' => BADGE_CRITERIA_AGGREGATION_ANY]); + $criteriaoverall1 = award_criteria::build(['criteriatype' => BADGE_CRITERIA_TYPE_PROFILE, 'badgeid' => $badge->id]); + $criteriaoverall1->save(['agg' => BADGE_CRITERIA_AGGREGATION_ALL, 'field_address' => 'address']); $this->user->address = 'Test address'; $sink = $this->redirectEmails(); @@ -922,17 +920,7 @@ public function test_badges_assertion(): void { $awards = $badge->get_awards(); $this->assertCount(1, $awards); - // Get assertion. - $award = reset($awards); - $assertion = new core_badges_assertion($award->uniquehash, OPEN_BADGES_V1); - $testassertion = $this->assertion; - - // Make sure JSON strings have the same structure. - $this->assertStringMatchesFormat($testassertion->badge, json_encode($assertion->get_badge_assertion())); - $this->assertStringMatchesFormat($testassertion->class, json_encode($assertion->get_badge_class())); - $this->assertStringMatchesFormat($testassertion->issuer, json_encode($assertion->get_issuer())); - - // Test Openbadge specification version 2. + // Test Openbadge specification version 2.0. // Get assertion version 2. $award = reset($awards); $assertion2 = new core_badges_assertion($award->uniquehash, OPEN_BADGES_V2); diff --git a/badges/tests/behat/backpack.feature b/badges/tests/behat/backpack.feature index edebf072857cc..8a152fa991faf 100644 --- a/badges/tests/behat/backpack.feature +++ b/badges/tests/behat/backpack.feature @@ -150,13 +150,9 @@ Feature: Backpack badges Then "Include authentication details with the backpack" "checkbox" should not be visible And I should not see "Badge issuer email address" And I should not see "Badge issuer password" - And I set the field "apiversion" to "1" - And "Include authentication details with the backpack" "checkbox" should be visible - And I click on "includeauthdetails" "checkbox" - And I should see "Badge issuer email address" - And I should not see "Badge issuer password" And I set the field "apiversion" to "2" And "Include authentication details with the backpack" "checkbox" should be visible + And I click on "includeauthdetails" "checkbox" And I should see "Badge issuer email address" And I should see "Badge issuer password" And I set the field "backpackemail" to "test@test.com" diff --git a/lib/badgeslib.php b/lib/badgeslib.php index 6030c3aa2a005..9067254faa72b 100644 --- a/lib/badgeslib.php +++ b/lib/badgeslib.php @@ -102,16 +102,15 @@ define('BADGRIO_BACKPACKAPIURL', 'https://api.badgr.io/v2'); define('BADGRIO_BACKPACKWEBURL', 'https://badgr.io'); -/* - * @deprecated since 3.9 (MDL-66357). +/** + * @deprecated since Moodle 4.5. + * @todo Final deprecation in Moodle 6.0. See MDL-82332. */ -define('BADGE_BACKPACKAPIURL', 'https://backpack.openbadges.org'); -define('BADGE_BACKPACKWEBURL', 'https://backpack.openbadges.org'); +define('OPEN_BADGES_V1', 1); /* * Open Badges specifications. */ -define('OPEN_BADGES_V1', 1); define('OPEN_BADGES_V2', 2); define('OPEN_BADGES_V2P1', 2.1); @@ -1100,7 +1099,6 @@ function badges_change_sortorder_backpacks(int $backpackid, int $direction): voi */ function badges_get_badge_api_versions() { return [ - (string)OPEN_BADGES_V1 => get_string('openbadgesv1', 'badges'), (string)OPEN_BADGES_V2 => get_string('openbadgesv2', 'badges'), (string)OPEN_BADGES_V2P1 => get_string('openbadgesv2p1', 'badges') ];