MDL-85621 core_badges: Replace manual JSON with exporters

This commit is contained in:
Sara Arjona
2025-11-12 10:55:30 +01:00
parent 8bb1a47fad
commit ccbcb9732d
11 changed files with 251 additions and 344 deletions
@@ -0,0 +1,11 @@
issueNumber: MDL-85621
notes:
core_badges:
- message: >-
The class core_badges_assertion has been deprecated and replaced by
\core_badges\achievement_credential.
The method badges_get_default_issuer() has also been deprecated because
it is no longer needed.
The file badges/endorsement.php has been removed because it stopped being used
when MDL-84323 was integrated.
type: deprecated
+17 -14
View File
@@ -25,6 +25,8 @@
require_once(__DIR__ . '/../config.php');
require_once($CFG->libdir . '/badgeslib.php');
use core_badges\local\backpack\helper;
require_login();
$userbackpack = badges_get_user_backpack();
@@ -32,13 +34,13 @@ if (badges_open_badges_backpack_api($userbackpack->id) != OPEN_BADGES_V2) {
throw new coding_exception('No backpacks support Open Badges V2.');
}
$id = required_param('hash', PARAM_ALPHANUM);
$assertionhash = required_param('hash', PARAM_ALPHANUM);
$PAGE->set_url('/badges/backpack-add.php', array('hash' => $id));
$PAGE->set_url('/badges/backpack-add.php', ['hash' => $assertionhash]);
$PAGE->set_context(context_system::instance());
$output = $PAGE->get_renderer('core', 'badges');
$issuedbadge = new \core_badges\output\issued_badge($id);
$issuedbadge = new \core_badges\output\issued_badge($assertionhash);
if (!empty($issuedbadge->recipient->id)) {
// The flow for issuing a badge is:
// * Create issuer
@@ -55,9 +57,7 @@ if (!empty($issuedbadge->recipient->id)) {
$badge = new badge($badgeid);
$backpack = $DB->get_record('badge_backpack', array('userid' => $USER->id));
$userbackpack = badges_get_site_backpack($backpack->externalbackpackid, $USER->id);
$assertion = new core_badges_assertion($id, OPEN_BADGES_V2);
$assertiondata = $assertion->get_badge_assertion(false, false);
$assertionid = $assertion->get_assertion_hash();
$assertiondata = helper::export_achievement_credential(OPEN_BADGES_V2, $assertionhash, false, false);
$assertionentityid = $assertiondata['id'];
$badgeadded = false;
$issuerexists = false;
@@ -69,7 +69,7 @@ if (!empty($issuedbadge->recipient->id)) {
// A numeric response indicates a valid successful authentication. Else an error object will be returned.
if (is_numeric($response)) {
// Create issuer.
$issuer = $assertion->get_issuer();
$issuer = helper::export_issuer(OPEN_BADGES_V2, $badgeid);
if (!($issuerentityid = badges_external_get_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_ISSUER, $issuer['email']))) {
$response = $api->put_issuer($issuer);
if ($response) {
@@ -85,8 +85,11 @@ if (!empty($issuedbadge->recipient->id)) {
}
if ($issuerexists) {
// Create badge.
$badge = $assertion->get_badge_class(false);
$badgeid = $assertion->get_badge_id();
$badge = helper::export_credential(
OPEN_BADGES_V2,
$badgeid,
false,
);
if (!($badgeentityid = badges_external_get_mapping($sitebackpack->id, OPEN_BADGES_V2_TYPE_BADGE, $badgeid))) {
$response = $api->put_badgeclass($issuerentityid, $badge);
if ($response) {
@@ -104,7 +107,7 @@ if (!empty($issuedbadge->recipient->id)) {
$assertionentityid = badges_external_get_mapping(
$sitebackpack->id,
OPEN_BADGES_V2_TYPE_ASSERTION,
$assertionid
$assertionhash
);
if ($assertionentityid && strpos($sitebackpack->backpackapiurl, 'badgr')) {
@@ -128,7 +131,7 @@ if (!empty($issuedbadge->recipient->id)) {
badges_external_create_mapping(
$sitebackpack->id,
OPEN_BADGES_V2_TYPE_ASSERTION,
$assertionid,
$assertionhash,
$response->id,
);
}
@@ -137,7 +140,7 @@ if (!empty($issuedbadge->recipient->id)) {
$internalid = badges_external_get_mapping(
$sitebackpack->id,
OPEN_BADGES_V2_TYPE_ASSERTION,
$assertionid,
$assertionhash,
'externalid'
);
$response = $api->update_assertion($internalid, $assertiondata);
@@ -152,7 +155,7 @@ if (!empty($issuedbadge->recipient->id)) {
// - This is only needed when the backpacks are from different regions.
if (
$assertionentityid
&& (!$issuerexists || !badges_external_get_mapping($userbackpack->id, OPEN_BADGES_V2_TYPE_ASSERTION, $assertionid))
&& (!$issuerexists || !badges_external_get_mapping($userbackpack->id, OPEN_BADGES_V2_TYPE_ASSERTION, $assertionhash))
) {
$userapi = new \core_badges\backpack_api($userbackpack, $backpack);
$userapi->authenticate();
@@ -163,7 +166,7 @@ if (!empty($issuedbadge->recipient->id)) {
badges_external_create_mapping(
$userbackpack->id,
OPEN_BADGES_V2_TYPE_ASSERTION,
$assertionid,
$assertionhash,
$assertionentityid,
);
}
+146 -142
View File
@@ -16,6 +16,12 @@
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/badgeslib.php');
require_once($CFG->dirroot . '/badges/renderer.php');
use core_badges\local\backpack\helper;
use core_badges\local\backpack\ob_factory;
/**
* Open Badges Assertions specification 2.0
* {@link https://www.imsglobal.org/sites/default/files/Badges/OBv2p0Final/index.html#Assertion}
@@ -24,18 +30,19 @@ defined('MOODLE_INTERNAL') || die();
* - 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)
*/
require_once($CFG->libdir . '/badgeslib.php');
require_once($CFG->dirroot . '/badges/renderer.php');
/**
* 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 <[email protected]>
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\achievement_credential',
since: '5.1',
mdl: 'MDL-85621',
)]
class core_badges_assertion {
/** @var object Issued badge information from database */
private $_data;
@@ -51,10 +58,19 @@ class core_badges_assertion {
*
* @param string $hash Badge unique hash from badge_issued table.
* @param int $obversion to control version JSON-LD.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\achievement_credential::instance()',
since: '5.1',
mdl: 'MDL-85621',
)]
public function __construct($hash, $obversion = OPEN_BADGES_V2) {
global $DB;
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$this->_data = $DB->get_record_sql('
SELECT
bi.dateissued,
@@ -86,8 +102,17 @@ class core_badges_assertion {
* Get the local id for this badge.
*
* @return int
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\achievement_credential::get_badge_id()',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_badge_id() {
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$badgeid = 0;
if ($this->_data) {
$badgeid = $this->_data->id;
@@ -99,8 +124,17 @@ class core_badges_assertion {
* Get the local id for this badge assertion.
*
* @return string
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\achievement_credential::get_hash()',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_assertion_hash() {
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$hash = '';
if ($this->_data) {
$hash = $this->_data->uniquehash;
@@ -114,55 +148,23 @@ class core_badges_assertion {
* @param boolean $issued Include the nested badge issued information.
* @param boolean $usesalt Hash the identity and include the salt information for the hash.
* @return array Badge assertion.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\local\backpack\helper::export_achievement_credential',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_badge_assertion($issued = true, $usesalt = true) {
global $CFG;
$assertion = array();
if ($this->_data) {
$hash = $this->_data->uniquehash;
$email = empty($this->_data->backpackemail) ? $this->_data->email : $this->_data->backpackemail;
$assertionurl = new moodle_url('/badges/assertion.php', array('b' => $hash, 'obversion' => $this->_obversion));
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
if ($this->_obversion >= OPEN_BADGES_V2) {
$classurl = new moodle_url('/badges/badge_json.php', array('id' => $this->get_badge_id()));
} else {
$classurl = new moodle_url('/badges/assertion.php', array('b' => $hash, 'action' => 1));
}
// Required.
$assertion['uid'] = $hash;
$assertion['recipient'] = array();
if ($usesalt) {
$assertion['recipient']['identity'] = 'sha256$' . hash('sha256', $email . $CFG->badges_badgesalt);
} else {
$assertion['recipient']['identity'] = $email;
}
$assertion['recipient']['type'] = 'email'; // Currently the only supported type.
$assertion['recipient']['hashed'] = true; // We are always hashing recipient.
if ($usesalt) {
$assertion['recipient']['salt'] = $CFG->badges_badgesalt;
}
if ($issued) {
$assertion['badge'] = $classurl->out(false);
}
$assertion['verify'] = array();
$assertion['verify']['type'] = 'hosted'; // 'Signed' is not implemented yet.
$assertion['verify']['url'] = $assertionurl->out(false);
$assertion['issuedOn'] = $this->_data->dateissued;
if ($issued) {
$assertion['evidence'] = $this->_url->out(false); // Currently issued badge URL.
}
// Optional.
if (!empty($this->_data->dateexpire)) {
$assertion['expires'] = $this->_data->dateexpire;
}
$tags = $this->get_tags();
if (is_array($tags) && count($tags) > 0) {
$assertion['tags'] = $tags;
}
$this->embed_data_badge_version2($assertion, OPEN_BADGES_V2_TYPE_ASSERTION);
}
return $assertion;
return helper::export_achievement_credential(
helper::convert_apiversion($this->_obversion),
$this->get_assertion_hash(),
$issued,
$usesalt,
);
}
/**
@@ -170,63 +172,43 @@ class core_badges_assertion {
*
* @param boolean $issued Include the nested badge issuer information.
* @return array Badge Class information.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\local\backpack\helper::export_credential',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_badge_class($issued = true) {
$class = [];
if ($this->_data) {
if (empty($this->_data->courseid)) {
$context = context_system::instance();
} else {
$context = context_course::instance($this->_data->courseid);
}
// Required.
$class['name'] = $this->_data->name;
$class['description'] = $this->_data->description;
$storage = get_file_storage();
$imagefile = $storage->get_file($context->id, 'badges', 'badgeimage', $this->_data->id, '/', 'f3.png');
if ($imagefile) {
$imagedata = base64_encode($imagefile->get_content());
} else {
if (defined('PHPUNIT_TEST') && PHPUNIT_TEST) {
// Unit tests the file might not exist yet.
$imagedata = '';
} else {
throw new coding_exception('Image file does not exist.');
}
}
$class['image'] = 'data:image/png;base64,' . $imagedata;
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$params = ['id' => $this->get_badge_id()];
$badgeurl = new moodle_url('/badges/badgeclass.php', $params);
$class['criteria'] = $badgeurl->out(false); // Currently badge URL.
if ($issued) {
$params = ['id' => $this->get_badge_id()];
$issuerurl = new moodle_url('/badges/issuer_json.php', $params);
$class['issuer'] = $issuerurl->out(false);
}
$tags = $this->get_tags();
if (is_array($tags) && count($tags) > 0) {
$class['tags'] = $tags;
}
$this->embed_data_badge_version2($class, OPEN_BADGES_V2_TYPE_BADGE);
if (!$issued) {
unset($class['issuer']);
}
}
return $class;
return helper::export_credential(
helper::convert_apiversion($this->_obversion),
$this->get_badge_id(),
$issued,
);
}
/**
* Get badge issuer information.
*
* @return array Issuer information.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\local\backpack\helper::export_issuer',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_issuer() {
$badge = new badge($this->get_badge_id());
$issuer = $badge->get_badge_issuer();
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$this->embed_data_badge_version2($issuer, OPEN_BADGES_V2_TYPE_ISSUER);
return $issuer;
return helper::export_issuer(
helper::convert_apiversion($this->_obversion),
$this->get_badge_id(),
);
}
/**
@@ -234,32 +216,40 @@ class core_badges_assertion {
*
* @param badge $badge Badge object.
* @return array|bool List related badges.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\local\backpack\ob\badge_exporter_interface::export_related_badges',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_related_badges(badge $badge) {
global $DB;
$arraybadges = array();
$relatedbadges = $badge->get_related_badges(true);
if ($relatedbadges) {
foreach ($relatedbadges as $rb) {
$url = new moodle_url('/badges/badge_json.php', array('id' => $rb->id));
$arraybadges[] = array(
'id' => $url->out(false),
'version' => $rb->version,
'@language' => $rb->language
);
}
}
return $arraybadges;
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$badgeexporter = ob_factory::create_badge_exporter_from_id(
$badge->id,
helper::convert_apiversion($this->_obversion),
);
return $badgeexporter->export_related_badges();
}
/**
* Get endorsement of the badge.
*
* @return false|stdClass Endorsement information.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_endorsement() {
global $DB;
$endorsement = array();
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$record = $DB->get_record_select('badge_endorsement', 'badgeid = ?', array($this->_data->id));
return $record;
}
@@ -268,46 +258,44 @@ class core_badges_assertion {
* Get criteria of badge class.
*
* @return array|string Criteria information.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\local\backpack\ob\badge_exporter_interface::export_criteria',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_criteria_badge_class() {
$badge = new badge($this->_data->id);
$narrative = $badge->markdown_badge_criteria();
$params = ['id' => $this->get_badge_id()];
$badgeurl = new moodle_url('/badges/badgeclass.php', $params);
if (!empty($narrative)) {
$criteria = [];
$criteria['id'] = $badgeurl->out(false);
$criteria['narrative'] = $narrative;
return $criteria;
} else {
return $badgeurl->out(false);
}
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$badgeexporter = ob_factory::create_badge_exporter_from_id(
$this->get_badge_id(),
helper::convert_apiversion(OPEN_BADGES_V2),
);
return $badgeexporter->export_criteria();
}
/**
* Get alignment of the badge.
*
* @return array information.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
replacement: '\core_badges\local\backpack\ob\badge_exporter_interface::export_alignments',
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_alignments() {
global $DB;
$badgeid = $this->_data->id;
$alignments = array();
$items = $DB->get_records_select('badge_alignment', 'badgeid = ?', array($badgeid));
foreach ($items as $item) {
$alignment = array('targetName' => $item->targetname, 'targetUrl' => $item->targeturl);
if ($item->targetdescription) {
$alignment['targetDescription'] = $item->targetdescription;
}
if ($item->targetframework) {
$alignment['targetFramework'] = $item->targetframework;
}
if ($item->targetcode) {
$alignment['targetCode'] = $item->targetcode;
}
$alignments[] = $alignment;
}
return $alignments;
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
$badgeexporter = ob_factory::create_badge_exporter_from_id(
$this->get_badge_id(),
helper::convert_apiversion(OPEN_BADGES_V2),
);
return $badgeexporter->export_alignments();
}
/**
@@ -315,8 +303,16 @@ class core_badges_assertion {
*
* @param array $json for assertion, badges, issuer.
* @param string $type Content type.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
since: '5.1',
mdl: 'MDL-85621',
)]
protected function embed_data_badge_version2(&$json, $type = OPEN_BADGES_V2_TYPE_ASSERTION) {
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
// Specification Version 2.0.
if ($this->_obversion >= OPEN_BADGES_V2) {
$badge = new badge($this->_data->id);
@@ -390,8 +386,16 @@ class core_badges_assertion {
* Get tags of the badge.
*
* @return array tags.
* @deprecated since Moodle 5.1.
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
since: '5.1',
mdl: 'MDL-85621',
)]
public function get_tags(): array {
\core\deprecation::emit_deprecation_if_present([self::class, __FUNCTION__]);
return array_values(\core_tag_tag::get_item_tags_array('core_badges', 'badge', $this->get_badge_id()));
}
}
+6 -2
View File
@@ -24,6 +24,8 @@
namespace core_badges;
use core_badges\local\backpack\helper;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/filelib.php');
@@ -265,8 +267,10 @@ class backpack_api2p1 {
$this->tokendata = $this->get_stored_token($this->externalbackpack->id);
$assertion = new \core_badges_assertion($hash, OPEN_BADGES_V2);
$data['assertion'] = $assertion->get_badge_assertion();
$data['assertion'] = helper::export_achievement_credential(
OPEN_BADGES_V2,
$hash,
);
$response = $this->curl_request('post.assertions', $data);
if ($response && isset($response->status->statusCode) && $response->status->statusCode == 200) {
$msg['status'] = \core\output\notification::NOTIFY_SUCCESS;
+8 -9
View File
@@ -16,6 +16,9 @@
namespace core_badges;
use core_badges\local\backpack\helper;
use core_badges\local\backpack\ob_factory;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot.'/lib/badgeslib.php');
@@ -24,7 +27,6 @@ use context_system;
use context_course;
use context_user;
use moodle_exception;
use moodle_url;
use core_text;
use award_criteria;
use core_php_time_limit;
@@ -937,14 +939,11 @@ class badge {
* @return array Issuer informations of the badge.
*/
public function get_badge_issuer(?int $obversion = null) {
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,
];
$issuerexporter = ob_factory::create_issuer_exporter_from_id(
$this->id,
helper::convert_apiversion($obversion),
);
return $issuerexporter->export();
}
/**
+12 -3
View File
@@ -26,6 +26,8 @@
namespace core_badges\output;
use core_badges\local\backpack\helper;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/badgeslib.php');
@@ -72,12 +74,12 @@ class issued_badge implements renderable {
global $DB;
$this->hash = $hash;
$assertion = new \core_badges_assertion($hash, badges_open_badges_backpack_api());
$this->issued = $assertion->get_badge_assertion();
// Get achievement credential data using OBv2.0 specification.
// In the future, we may want to support other OB versions.
$this->issued = helper::export_achievement_credential(OPEN_BADGES_V2, $hash);
if (array_key_exists('issuedOn', $this->issued) && !is_numeric($this->issued['issuedOn'])) {
$this->issued['issuedOn'] = strtotime($this->issued['issuedOn']);
}
$this->badgeclass = $assertion->get_badge_class();
$rec = $DB->get_record_sql('SELECT userid, visible, badgeid
FROM {badge_issued}
@@ -92,6 +94,13 @@ class issued_badge implements renderable {
$this->recipient = $user;
$this->visible = $rec->visible;
$this->badgeid = $rec->badgeid;
// Get the badge class using OBv2.0 specification.
// In the future, we may want to support other OB versions.
$this->badgeclass = helper::export_credential(
OPEN_BADGES_V2,
$this->badgeid,
);
}
}
-69
View File
@@ -1,69 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Serve endorsement JSON for assertion.
*
* @package core
* @subpackage badges
* @copyright 2018 Tung Thai
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Tung Thai <[email protected]>
*/
define('AJAX_SCRIPT', true);
define('NO_MOODLE_COOKIES', true); // No need for a session here.
require_once(__DIR__ . '/../config.php');
require_once($CFG->libdir . '/badgeslib.php');
if (empty($CFG->enablebadges)) {
throw new \moodle_exception('badgesdisabled', 'badges');
}
global $DB;
$id = required_param('id', PARAM_INT);
$action = optional_param('action', null, PARAM_BOOL); // Generates endorsement issuer class if true.
$badge = new badge($id);
$json = array();
$endorsement = $badge->get_endorsement();
$endorsementurl = new moodle_url('/badges/endorsement_json.php', array('id' => $id));
if ($endorsement) {
$issuer = array();
$issuerurl = new moodle_url('/badges/endorsement_json.php', array('id' => $id, 'action' => 1));
$issuer['id'] = $issuerurl->out(false);
$issuer['name'] = $endorsement->issuername;
$issuer['email'] = $endorsement->issueremail;
$issuer['url'] = $endorsement->issuerurl;
if ($action) {
$json = $issuer;
} else {
$json['@context'] = OPEN_BADGES_V2_CONTEXT;
$json['type'] = OPEN_BADGES_V2_TYPE_ENDORSEMENT;
$json['id'] = $endorsementurl->out(false);
$json['issuer'] = $issuer;
if (!empty($endorsement->claimcomment)) {
$json['claim']['id'] = $endorsement->claimid;
$json['claim']['endorsementComment'] = $endorsement->claimcomment;
} else {
$json['claim'] = $endorsement->claimid;
}
$json['issuedOn'] = date('c', $endorsement->dateissued);
$json['verification'] = array('type' => 'hosted');
}
}
echo $OUTPUT->header();
echo json_encode($json);
+1 -45
View File
@@ -15,6 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
use core_badges\helper;
use core_badges\local\backpack\ob_factory;
use core_badges\tests\badges_testcase;
use core\task\manager;
@@ -759,51 +760,6 @@ final class badgeslib_test extends badges_testcase {
$this->assertSame(0, $badge->review_all_criteria()); // Verify award_criteria_cohort->get_completed_criteria_sql().
}
/**
* Test badges assertion generated when a badge is issued.
*/
public function test_badges_assertion(): void {
$this->preventResetByRollback(); // Messaging is not compatible with transactions.
$badge = new badge($this->coursebadge);
$this->assertFalse($badge->is_issued($this->user->id));
$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();
user_update_user($this->user, false);
$this->assertCount(1, $sink->get_messages());
$sink->close();
// Check if badge is awarded.
$this->assertDebuggingCalled('Error baking badge image!');
$awards = $badge->get_awards();
$this->assertCount(1, $awards);
// Test Openbadge specification version 2.0.
// Get assertion version 2.
$award = reset($awards);
$assertion2 = new core_badges_assertion($award->uniquehash, OPEN_BADGES_V2);
$testassertion2 = $this->assertion2;
// Make sure JSON strings have the same structure.
$this->assertStringMatchesFormat($testassertion2->badge, json_encode($assertion2->get_badge_assertion()));
$this->assertStringMatchesFormat($testassertion2->class, json_encode($assertion2->get_badge_class()));
$this->assertStringMatchesFormat($testassertion2->issuer, json_encode($assertion2->get_issuer()));
// Test Openbadge specification version 2.1. It has the same format as OBv2.0.
// Get assertion version 2.1.
$award = reset($awards);
$assertion2 = new core_badges_assertion($award->uniquehash, OPEN_BADGES_V2P1);
// Make sure JSON strings have the same structure.
$this->assertStringMatchesFormat($testassertion2->badge, json_encode($assertion2->get_badge_assertion()));
$this->assertStringMatchesFormat($testassertion2->class, json_encode($assertion2->get_badge_class()));
$this->assertStringMatchesFormat($testassertion2->issuer, json_encode($assertion2->get_issuer()));
}
/**
* Tests the core_badges_myprofile_navigation() function.
*/
@@ -34,10 +34,6 @@ abstract class badges_testcase extends \advanced_testcase {
protected $user;
protected $module;
protected $coursebadge;
protected $assertion;
/** @var $assertion2 to define json format for Open badge version 2 */
protected $assertion2;
#[\Override]
public static function setUpBeforeClass(): void {
@@ -150,32 +146,5 @@ abstract class badges_testcase extends \advanced_testcase {
// Insert tags.
core_tag_tag::set_item_tags('core_badges', 'badge', $badge->id, $badge->get_context(), ['tag1', 'tag2']);
$this->assertion = new stdClass();
$this->assertion->badge = '{"uid":"%s","recipient":{"identity":"%s","type":"email","hashed":true,"salt":"%s"},' .
'"badge":"%s","verify":{"type":"hosted","url":"%s"},"issuedOn":"%d","evidence":"%s","tags":%s}';
$this->assertion->class = '{"name":"%s","description":"%s","image":"%s","criteria":"%s","issuer":"%s","tags":%s}';
$this->assertion->issuer = '{"name":"%s","url":"%s","email":"%s"}';
// Format JSON-LD for Openbadge specification version 2.0.
$this->assertion2 = new stdClass();
$this->assertion2->badge = '{"recipient":{"identity":"%s","type":"email","hashed":true,"salt":"%s"},' .
'"badge":{"name":"%s","description":"%s","image":"%s",' .
'"criteria":{"id":"%s","narrative":"%s"},"issuer":{"name":"%s","url":"%s","email":"%s",' .
'"@context":"https:\/\/w3id.org\/openbadges\/v2","id":"%s","type":"Issuer"},' .
'"tags":%s,"@context":"https:\/\/w3id.org\/openbadges\/v2","id":"%s","type":"BadgeClass","version":"%s",' .
'"@language":"en","related":[{"id":"%s","version":"%s","@language":"%s"}],' .
'"alignments":[{"targetName":"%s","targetUrl":"%s","targetDescription":"%s","targetFramework":"%s",' .
'"targetCode":"%s"}]},"verify":{"type":"hosted","url":"%s"},"issuedOn":"%s","evidence":"%s","tags":%s,' .
'"@context":"https:\/\/w3id.org\/openbadges\/v2","type":"Assertion","id":"%s"}';
$this->assertion2->class = '{"name":"%s","description":"%s","image":"%s",' .
'"criteria":{"id":"%s","narrative":"%s"},"issuer":{"name":"%s","url":"%s","email":"%s",' .
'"@context":"https:\/\/w3id.org\/openbadges\/v2","id":"%s","type":"Issuer"},' .
'"tags":%s,"@context":"https:\/\/w3id.org\/openbadges\/v2","id":"%s","type":"BadgeClass","version":"%s",' .
'"@language":"%s","related":[{"id":"%s","version":"%s","@language":"%s"}],' .
'"alignments":[{"targetName":"%s","targetUrl":"%s","targetDescription":"%s","targetFramework":"%s",' .
'"targetCode":"%s"}]}';
$this->assertion2->issuer = '{"name":"%s","url":"%s","email":"%s",' .
'"@context":"https:\/\/w3id.org\/openbadges\/v2","id":"%s","type":"Issuer"}';
}
}
+16 -29
View File
@@ -132,6 +132,8 @@ define('BACKPACK_MOVE_DOWN', 1);
class_alias('\core_badges\badge', 'badge');
use core_badges\png_metadata_handler;
use core_badges\local\backpack\helper;
use core_badges\local\backpack\ob_factory;
/**
* Sends notifications to users about awarded badges.
@@ -708,7 +710,7 @@ function print_badge_image(badge $badge, stdClass $context, $size = 'small') {
* @return string|moodle_url|null Returns either new file path hash or new file URL
*/
function badges_bake($hash, $badgeid, $userid = 0, $pathhash = false) {
global $CFG, $USER;
global $USER;
$badge = new badge($badgeid);
$badge_context = $badge->get_context();
@@ -721,10 +723,19 @@ function badges_bake($hash, $badgeid, $userid = 0, $pathhash = false) {
$contents = $file->get_content();
$filehandler = new png_metadata_handler($contents);
// For now, the site backpack OB version will be used as default.
$obversion = badges_open_badges_backpack_api();
$assertion = new core_badges_assertion($hash, $obversion);
$assertionjson = json_encode($assertion->get_badge_assertion());
// For now, the user backpack OB version will be used as default (or site if the user doesn't have).
// Make OB version configurable in the future, to let users choose which use.
$backpack = badges_get_user_backpack($userid);
if ($backpack) {
$obversion = $backpack->apiversion;
} else {
$obversion = badges_open_badges_backpack_api();
}
$assertionexporter = ob_factory::create_assertion_exporter_from_hash(
$hash,
helper::convert_apiversion($obversion),
);
$assertionjson = $assertionexporter->get_json();
if ($filehandler->check_chunks("iTXt", "openbadges")) {
// Add assertion URL iTXt chunk.
$newcontents = $filehandler->add_chunks("iTXt", "openbadges", $assertionjson);
@@ -1211,30 +1222,6 @@ function badges_get_badge_api_versions() {
];
}
/**
* Get the default issuer for a badge from this site.
*
* @return array
*/
function badges_get_default_issuer() {
global $CFG, $SITE;
$sitebackpack = badges_get_site_primary_backpack();
$issuer = array();
$issuerurl = new moodle_url('/');
$issuer['name'] = $CFG->badges_defaultissuername;
if (empty($issuer['name'])) {
$issuer['name'] = $SITE->fullname ? $SITE->fullname : $SITE->shortname;
}
$issuer['url'] = $issuerurl->out(false);
$issuer['email'] = $sitebackpack->backpackemail ?: $CFG->badges_defaultissuercontact;
$issuer['@context'] = OPEN_BADGES_V2_CONTEXT;
$issuerid = new moodle_url('/badges/issuer_json.php');
$issuer['id'] = $issuerid->out(false);
$issuer['type'] = OPEN_BADGES_V2_TYPE_ISSUER;
return $issuer;
}
/**
* Disconnect from the user backpack by deleting the user preferences.
*
+34
View File
@@ -899,3 +899,37 @@ function file_encode_url($urlbase, $path, $forcedownload = false, $https = false
return $return;
}
/**
* Get the default issuer for a badge from this site.
*
* @return array
*
* @deprecated Since Moodle 5.2
* @todo MDL-85730 Final deprecation in Moodle 6.0.
*/
#[\core\attribute\deprecated(
since: '5.2',
mdl: 'MDL-85621',
reason: 'It is no longer used.'
)]
function badges_get_default_issuer() {
\core\deprecation::emit_deprecation(__FUNCTION__);
global $CFG, $SITE;
$sitebackpack = badges_get_site_primary_backpack();
$issuer = [];
$issuerurl = new moodle_url('/');
$issuer['name'] = $CFG->badges_defaultissuername;
if (empty($issuer['name'])) {
$issuer['name'] = $SITE->fullname ? $SITE->fullname : $SITE->shortname;
}
$issuer['url'] = $issuerurl->out(false);
$issuer['email'] = $sitebackpack->backpackemail ?: $CFG->badges_defaultissuercontact;
$issuer['@context'] = OPEN_BADGES_V2_CONTEXT;
$issuerid = new moodle_url('/badges/issuer_json.php');
$issuer['id'] = $issuerid->out(false);
$issuer['type'] = OPEN_BADGES_V2_TYPE_ISSUER;
return $issuer;
}