Skip to content

Commit

Permalink
MDL-58454 badges: Open Badges Specification Version 2.0 Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
tungthai authored and sarjona committed Nov 5, 2018
1 parent bebef89 commit d363a5c
Show file tree
Hide file tree
Showing 24 changed files with 2,202 additions and 15 deletions.
12 changes: 9 additions & 3 deletions badges/assertion.php
Expand Up @@ -35,8 +35,9 @@

$hash = required_param('b', PARAM_ALPHANUM); // Issued badge unique hash for badge assertion.
$action = optional_param('action', null, PARAM_BOOL); // Generates badge class if true.
$obversion = optional_param('obversion', 1, PARAM_INT); // For control format OB specification version.

$assertion = new core_badges_assertion($hash);
$assertion = new core_badges_assertion($hash, $obversion);

if (!is_null($action)) {
// Get badge class or issuer information depending on $action.
Expand All @@ -48,11 +49,16 @@
$json = $assertion->get_badge_assertion();
} else { // Revoked badge.
header("HTTP/1.0 410 Gone");
echo json_encode(array("revoked" => true));
$assertion = array();
if ($obversion == 2) {
$assertionurl = new moodle_url('/badges/assertion.php', array('b' => $hash));
$assertion['id'] = $assertionurl->out();
}
$assertion['revoked'] = true;
echo json_encode($assertion);
die();
}
}


echo $OUTPUT->header();
echo json_encode($json);
126 changes: 126 additions & 0 deletions badges/badge_json.php
@@ -0,0 +1,126 @@
<?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 BadgeClass JSON for related badge.
*
* @package core
* @subpackage badges
* @copyright 2018 Tung Thai
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @author Tung Thai <Tung.ThaiDuc@nashtechglobal.com>
*/
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');

$id = required_param('id', PARAM_INT);
$action = optional_param('action', null, PARAM_INT); // Generates badge class if true.
$json = array();
$badge = new badge($id);
if ($badge->status != BADGE_STATUS_INACTIVE) {
if (is_null($action)) {
// Get the content of badge class.
if (empty($badge->courseid)) {
$context = context_system::instance();
} else {
$context = context_course::instance($badge->courseid);
}
$urlimage = moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $badge->id, '/', 'f1')->out(false);

$url = new moodle_url('/badges/badge_json.php', array('id' => $badge->id));

$json['name'] = $badge->name;
$json['description'] = $badge->description;
if ($badge->imageauthorname ||
$badge->imageauthoremail ||
$badge->imageauthorurl ||
$badge->imagecaption) {
$urlimage = moodle_url::make_pluginfile_url($context->id,
'badges', 'badgeimage', $badge->id, '/', 'f1')->out(false);
$json['image'] = array();
$json['image']['id'] = $urlimage;
if ($badge->imageauthorname || $badge->imageauthoremail || $badge->imageauthorurl) {
$authorimage = new moodle_url('/badges/image_author_json.php', array('id' => $badge->id));
$json['image']['author'] = $authorimage->out(false);
}
if ($badge->imagecaption) {
$json['image']['caption'] = $badge->imagecaption;
}
} else {
$json['image'] = $urlimage;
}

$json['criteria']['id'] = $url->out(false);
$json['criteria']['narrative'] = $badge->markdown_badge_criteria();
$json['issuer'] = $badge->get_badge_issuer();
$json['@context'] = OPEN_BADGES_V2_CONTEXT;
$json['id'] = $url->out();
$json['type'] = OPEN_BADGES_V2_TYPE_BADGE;
if (!empty($badge->version)) {
$json['version'] = $badge->version;
}
if (!empty($badge->language)) {
$json['@language'] = $badge->language;
}

$relatedbadges = $badge->get_related_badges(true);
if (!empty($relatedbadges)) {
foreach ($relatedbadges as $related) {
$relatedurl = new moodle_url('/badges/badge_json.php', array('id' => $related->id));
$relateds[] = array('id' => $relatedurl->out(false),
'version' => $related->version, '@language' => $related->language);
}
$json['related'] = $relateds;
}

$endorsement = $badge->get_endorsement();
if (!empty($endorsement)) {
$endorsementurl = new moodle_url('/badges/endorsement_json.php', array('id' => $badge->id));
$json['endorsement'] = $endorsementurl->out(false);
}

$competencies = $badge->get_alignment();
if (!empty($competencies)) {
foreach ($competencies 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;
}
$json['alignment'][] = $alignment;
}
}
} else if ($action == 0) {
// Get the content for issuer.
$json = $badge->get_json_issuer_related_badge();
}
} else {
// The badge doen't exist or not accessible for the users.
header("HTTP/1.0 410 Gone");
$badgeurl = new moodle_url('/badges/badge_json.php', array('id' => $id));
$json['id'] = $badgeurl->out();
$json['error'] = get_string('error:relatedbadgedoesntexist', 'badges');
}
echo $OUTPUT->header();
echo json_encode($json);
170 changes: 169 additions & 1 deletion badges/classes/assertion.php
Expand Up @@ -34,6 +34,8 @@
* - 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.
Expand All @@ -46,12 +48,16 @@ class core_badges_assertion {
/** @var moodle_url Issued badge url */
private $_url;

/** @var int $obversion to control version JSON-LD. */
private $_obversion = 1;

/**
* Constructs with issued badge unique hash.
*
* @param string $hash Badge unique hash from badge_issued table.
* @param int $obversion to control version JSON-LD.
*/
public function __construct($hash) {
public function __construct($hash, $obversion = 1) {
global $DB;

$this->_data = $DB->get_record_sql('
Expand All @@ -78,6 +84,7 @@ public function __construct($hash) {
} else {
$this->_url = new moodle_url('/badges/badge.php');
}
$this->_obversion = $obversion;
}

/**
Expand Down Expand Up @@ -111,6 +118,7 @@ public function get_badge_assertion() {
if (!empty($this->_data->dateexpire)) {
$assertion['expires'] = $this->_data->dateexpire;
}
$this->embed_data_badge_version2($assertion, OPEN_BADGES_V2_TYPE_ASSERTION);
}
return $assertion;
}
Expand All @@ -136,6 +144,7 @@ public function get_badge_class() {
$class['image'] = moodle_url::make_pluginfile_url($context->id, 'badges', 'badgeimage', $this->_data->id, '/', 'f1')->out(false);
$class['criteria'] = $this->_url->out(false); // Currently issued badge URL.
$class['issuer'] = $issuerurl->out(false);
$this->embed_data_badge_version2($class, OPEN_BADGES_V2_TYPE_BADGE);
}
return $class;
}
Expand All @@ -156,7 +165,166 @@ public function get_issuer() {
$issuer['email'] = $this->_data->issuercontact;
}
}
$this->embed_data_badge_version2($issuer, OPEN_BADGES_V2_TYPE_ISSUER);
return $issuer;
}

/**
* Get related badges of the badge.
*
* @param badge $badge Badge object.
* @return array|bool List related badges.
*/
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;
}

/**
* Get endorsement of the badge.
*
* @return false|stdClass Endorsement information.
*/
public function get_endorsement() {
global $DB;
$endorsement = array();
$record = $DB->get_record_select('badge_endorsement', 'badgeid = ?', array($this->_data->id));
return $record;
}

/**
* Get criteria of badge class.
*
* @return array|string Criteria information.
*/
public function get_criteria_badge_class() {
$badge = new badge($this->_data->id);
$narrative = $badge->markdown_badge_criteria();
if (!empty($narrative)) {
$criteria = array();
$criteria['id'] = $this->_url->out(false);
$criteria['narrative'] = $narrative;
return $criteria;
} else {
return $this->_url->out(false);
}
}

/**
* Get competencies alignment of the badge.
*
* @return array competencies information.
*/
public function get_competencies_alignment() {
global $DB;
$badgeid = $this->_data->id;
$alignments = array();
$items = $DB->get_records_select('badge_competencies', '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;
}

/**
* Embed data of Open Badges Specification Version 2.0 to json.
*
* @param array $json for assertion, badges, issuer.
* @param string $type Content type.
*/
protected function embed_data_badge_version2 (&$json, $type = OPEN_BADGES_V2_TYPE_ASSERTION) {
// Specification Version 2.0.
if ($this->_obversion == 2) {
$badge = new badge($this->_data->id);
if (empty($this->_data->courseid)) {
$context = context_system::instance();
} else {
$context = context_course::instance($this->_data->courseid);
}

$hash = $this->_data->uniquehash;
$assertionsurl = new moodle_url('/badges/assertion.php', array('b' => $hash, 'obversion' => 2));
$classurl = new moodle_url('/badges/assertion.php', array('b' => $hash, 'action' => 1, 'obversion' => 2));
$issuerurl = new moodle_url('/badges/assertion.php', array('b' => $this->_data->uniquehash, 'action' => 0,
'obversion' => 2));
// For assertion.
if ($type == OPEN_BADGES_V2_TYPE_ASSERTION) {
$json['@context'] = OPEN_BADGES_V2_CONTEXT;
$json['type'] = OPEN_BADGES_V2_TYPE_ASSERTION;
$json['id'] = $assertionsurl->out(false);
$json['badge'] = $this->get_badge_class();
$json['issuedOn'] = date('c', $this->_data->dateissued);
if (!empty($this->_data->dateexpire)) {
$json['expires'] = date('c', $this->_data->dateexpire);
}
unset($json['uid']);
}

// For Badge.
if ($type == OPEN_BADGES_V2_TYPE_BADGE) {
$json['@context'] = OPEN_BADGES_V2_CONTEXT;
$json['id'] = $classurl->out(false);
$json['type'] = OPEN_BADGES_V2_TYPE_BADGE;
$json['version'] = $this->_data->version;
$json['criteria'] = $this->get_criteria_badge_class();
$json['issuer'] = $this->get_issuer();
$json['@language'] = $this->_data->language;
if (!empty($relatedbadges = $this->get_related_badges($badge))) {
$json['related'] = $relatedbadges;
}
if ($endorsement = $this->get_endorsement()) {
$endorsementurl = new moodle_url('/badges/endorsement_json.php', array('id' => $this->_data->id));
$json['endorsement'] = $endorsementurl->out(false);
}
if ($competencies = $this->get_competencies_alignment()) {
$json['alignment'] = $competencies;
}
if ($this->_data->imageauthorname ||
$this->_data->imageauthoremail ||
$this->_data->imageauthorurl ||
$this->_data->imagecaption) {
$urlimage = moodle_url::make_pluginfile_url($context->id,
'badges', 'badgeimage', $this->_data->id, '/', 'f1')->out(false);
$json['image'] = array();
$json['image']['id'] = $urlimage;
if ($this->_data->imageauthorname || $this->_data->imageauthoremail || $this->_data->imageauthorurl) {
$authorimage = new moodle_url('/badges/image_author_json.php', array('id' => $this->_data->id));
$json['image']['author'] = $authorimage->out(false);
}
if ($this->_data->imagecaption) {
$json['image']['caption'] = $this->_data->imagecaption;
}
}
}

// For issuer.
if ($type == OPEN_BADGES_V2_TYPE_ISSUER) {
$json['@context'] = OPEN_BADGES_V2_CONTEXT;
$json['id'] = $issuerurl->out(false);
$json['type'] = OPEN_BADGES_V2_TYPE_ISSUER;
}
}
}
}

0 comments on commit d363a5c

Please sign in to comment.