mirror of
https://github.com/moodle/moodle.git
synced 2025-04-13 04:22:07 +02:00
MDL-66940 badges: Create page to display badges info
The OBv2.0 specification includes a field "Criteria" for BadgeClass. Until now, this field was filled using the URL of the badge assertion, but that is causing some issues in Badgr because it linked to the badge assertion of the first user sending this badge to the Badgr backpack (so then, the following users linked to the first user assertion page too). This patch adds a new page, badgeclass.php which will be used from now to display any badge information which is not related to any assertion (like happens with the criteria in BadgeClass).
This commit is contained in:
parent
1d99ba19a2
commit
bc7dec8c2b
@ -66,7 +66,9 @@ if ($badge->status != BADGE_STATUS_INACTIVE) {
|
||||
$json['image'] = $urlimage;
|
||||
}
|
||||
|
||||
$json['criteria']['id'] = $url->out(false);
|
||||
$params = ['id' => $badge->id];
|
||||
$badgeurl = new moodle_url('/badges/badgeclass.php', $params);
|
||||
$json['criteria']['id'] = $badgeurl->out(false);
|
||||
$json['criteria']['narrative'] = $badge->markdown_badge_criteria();
|
||||
$json['issuer'] = $badge->get_badge_issuer();
|
||||
$json['@context'] = OPEN_BADGES_V2_CONTEXT;
|
||||
|
57
badges/badgeclass.php
Normal file
57
badges/badgeclass.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Display details of a badge.
|
||||
*
|
||||
* @package core_badges
|
||||
* @copyright 2022 Sara Arjona (sara@moodle.com)
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../config.php');
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
|
||||
$badgeid = required_param('id', PARAM_ALPHANUM);
|
||||
$badgeclass = new \core_badges\output\badgeclass($badgeid);
|
||||
|
||||
$context = !empty($badgeclass) ? $badgeclass->context : \context_system::instance();
|
||||
$PAGE->set_context($context);
|
||||
$output = $PAGE->get_renderer('core', 'badges');
|
||||
$PAGE->set_url('/badges/badgeclass.php', ['id' => $badgeid]);
|
||||
$PAGE->set_pagelayout('base');
|
||||
$PAGE->set_title(get_string('badgedetails', 'badges'));
|
||||
|
||||
if (!empty($badgeclass->badge)) {
|
||||
$PAGE->navbar->add($badgeclass->badge->name);
|
||||
$url = new moodle_url($CFG->wwwroot);
|
||||
navigation_node::override_active_url($url);
|
||||
|
||||
echo $OUTPUT->header();
|
||||
echo $output->render($badgeclass);
|
||||
} else {
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->notification(get_string('error:relatedbadgedoesntexist', 'badges'));
|
||||
}
|
||||
|
||||
// Trigger event, badge viewed.
|
||||
$other = ['badgeid' => $badgeclass->badgeid];
|
||||
$eventparams = ['context' => $PAGE->context, 'other' => $other];
|
||||
|
||||
$event = \core\event\badge_viewed::create($eventparams);
|
||||
$event->trigger();
|
||||
|
||||
echo $OUTPUT->footer();
|
@ -196,7 +196,10 @@ class core_badges_assertion {
|
||||
}
|
||||
}
|
||||
$class['image'] = 'data:image/png;base64,' . $imagedata;
|
||||
$class['criteria'] = $this->_url->out(false); // Currently issued badge URL.
|
||||
|
||||
$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(), 'obversion' => $this->_obversion];
|
||||
$issuerurl = new moodle_url('/badges/issuer_json.php', $params);
|
||||
@ -281,13 +284,15 @@ class core_badges_assertion {
|
||||
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 = array();
|
||||
$criteria['id'] = $this->_url->out(false);
|
||||
$criteria = [];
|
||||
$criteria['id'] = $badgeurl->out(false);
|
||||
$criteria['narrative'] = $narrative;
|
||||
return $criteria;
|
||||
} else {
|
||||
return $this->_url->out(false);
|
||||
return $badgeurl->out(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ class badge {
|
||||
$data = $DB->get_record('badge', array('id' => $badgeid));
|
||||
|
||||
if (empty($data)) {
|
||||
print_error('error:nosuchbadge', 'badges', $badgeid);
|
||||
throw new moodle_exception('error:nosuchbadge', 'badges', '', $badgeid);
|
||||
}
|
||||
|
||||
foreach ((array)$data as $field => $value) {
|
||||
|
175
badges/classes/output/badgeclass.php
Normal file
175
badges/classes/output/badgeclass.php
Normal file
@ -0,0 +1,175 @@
|
||||
<?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/>.
|
||||
|
||||
namespace core_badges\output;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/badgeslib.php');
|
||||
|
||||
use coding_exception;
|
||||
use context_course;
|
||||
use stdClass;
|
||||
use renderable;
|
||||
use core_badges\badge;
|
||||
use moodle_url;
|
||||
use renderer_base;
|
||||
|
||||
/**
|
||||
* Page to display badge information, such as name, description or criteria. This information is unrelated to assertions.
|
||||
*
|
||||
* @package core_badges
|
||||
* @copyright 2022 Sara Arjona (sara@moodle.com)
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class badgeclass implements renderable {
|
||||
|
||||
/** @var badge class */
|
||||
public $badge;
|
||||
|
||||
/** @var badge class */
|
||||
public $badgeid = 0;
|
||||
|
||||
/** @var \context The badge context*/
|
||||
public $context;
|
||||
|
||||
/**
|
||||
* Initializes the badge to display.
|
||||
*
|
||||
* @param int $id Id of the badge to display.
|
||||
*/
|
||||
public function __construct(int $id) {
|
||||
$this->badgeid = $id;
|
||||
$this->badge = new badge($this->badgeid);
|
||||
if ($this->badge->status == BADGE_STATUS_INACTIVE) {
|
||||
// Inactive badges that haven't been published previously can't be displayed.
|
||||
$this->badge = null;
|
||||
} else {
|
||||
$this->context = $this->badge->get_context();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export this data so it can be used as the context for a mustache template.
|
||||
*
|
||||
* @param renderer_base $output Renderer base.
|
||||
* @return stdClass
|
||||
*/
|
||||
public function export_for_template(renderer_base $output): stdClass {
|
||||
global $DB, $SITE;
|
||||
|
||||
$data = new stdClass();
|
||||
if ($this->context instanceof context_course) {
|
||||
$data->coursefullname = format_string($DB->get_field('course', 'fullname', ['id' => $this->badge->courseid]),
|
||||
true, ['context' => $this->context]);
|
||||
} else {
|
||||
$data->sitefullname = format_string($SITE->fullname, true, ['context' => $this->context]);
|
||||
}
|
||||
|
||||
// Field: Image.
|
||||
$storage = get_file_storage();
|
||||
$imagefile = $storage->get_file($this->context->id, 'badges', 'badgeimage', $this->badgeid, '/', '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.');
|
||||
}
|
||||
}
|
||||
$data->badgeimage = 'data:image/png;base64,' . $imagedata;
|
||||
|
||||
// Fields: Name, description.
|
||||
$data->badgename = $this->badge->name;
|
||||
$data->badgedescription = $this->badge->description;
|
||||
|
||||
// Field: Criteria.
|
||||
// This method will return the HTML with the badge criteria.
|
||||
$data->criteria = $output->print_badge_criteria($this->badge);
|
||||
|
||||
// Field: Issuer.
|
||||
$data->issuedby = format_string($this->badge->issuername, true, ['context' => $this->context]);
|
||||
if (isset($this->badge->issuercontact) && !empty($this->badge->issuercontact)) {
|
||||
$data->issuedbyemailobfuscated = obfuscate_mailto($this->badge->issuercontact, $data->issuedby);
|
||||
}
|
||||
|
||||
// Fields: Other details, such as language or version.
|
||||
$data->hasotherfields = false;
|
||||
if (!empty($this->badge->language)) {
|
||||
$data->hasotherfields = true;
|
||||
$languages = get_string_manager()->get_list_of_languages();
|
||||
$data->language = $languages[$this->badge->language];
|
||||
}
|
||||
if (!empty($this->badge->version)) {
|
||||
$data->hasotherfields = true;
|
||||
$data->version = $this->badge->version;
|
||||
}
|
||||
if (!empty($this->badge->imageauthorname)) {
|
||||
$data->hasotherfields = true;
|
||||
$data->imageauthorname = $this->badge->imageauthorname;
|
||||
}
|
||||
if (!empty($this->badge->imageauthoremail)) {
|
||||
$data->hasotherfields = true;
|
||||
$data->imageauthoremail = obfuscate_mailto($this->badge->imageauthoremail, $this->badge->imageauthoremail);
|
||||
}
|
||||
if (!empty($this->badge->imageauthorurl)) {
|
||||
$data->hasotherfields = true;
|
||||
$data->imageauthorurl = $this->badge->imageauthorurl;
|
||||
}
|
||||
if (!empty($this->badge->imagecaption)) {
|
||||
$data->hasotherfields = true;
|
||||
$data->imagecaption = $this->badge->imagecaption;
|
||||
}
|
||||
|
||||
// Field: Endorsement.
|
||||
$endorsement = $this->badge->get_endorsement();
|
||||
if (!empty($endorsement)) {
|
||||
$data->hasotherfields = true;
|
||||
$endorsement = $this->badge->get_endorsement();
|
||||
$endorsement->issueremail = obfuscate_mailto($endorsement->issueremail, $endorsement->issueremail);
|
||||
$data->endorsement = (array) $endorsement;
|
||||
}
|
||||
|
||||
// Field: Related badges.
|
||||
$relatedbadges = $this->badge->get_related_badges(true);
|
||||
if (!empty($relatedbadges)) {
|
||||
$data->hasotherfields = true;
|
||||
$data->hasrelatedbadges = true;
|
||||
$data->relatedbadges = [];
|
||||
foreach ($relatedbadges as $related) {
|
||||
if (isloggedin() && !is_guest($this->context)) {
|
||||
$related->url = (new moodle_url('/badges/overview.php', ['id' => $related->id]))->out(false);
|
||||
}
|
||||
$data->relatedbadges[] = (array)$related;
|
||||
}
|
||||
}
|
||||
|
||||
// Field: Alignments.
|
||||
$alignments = $this->badge->get_alignments();
|
||||
if (!empty($alignments)) {
|
||||
$data->hasotherfields = true;
|
||||
$data->hasalignments = true;
|
||||
$data->alignments = [];
|
||||
foreach ($alignments as $alignment) {
|
||||
$data->alignments[] = (array)$alignment;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -327,6 +327,17 @@ class core_badges_renderer extends plugin_renderer_base {
|
||||
return parent::render_from_template('core_badges/issued_badge', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an issued badge.
|
||||
*
|
||||
* @param \core_badges\output\badgeclass $badge
|
||||
* @return string
|
||||
*/
|
||||
protected function render_badgeclass(\core_badges\output\badgeclass $badge) {
|
||||
$data = $badge->export_for_template($this);
|
||||
return parent::render_from_template('core_badges/issued_badge', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render an external badge.
|
||||
*
|
||||
|
@ -23,14 +23,14 @@
|
||||
* coursefullname - Course name (only available if it's a course badge).
|
||||
* sitefullname - Site name (only available if it's a site badge).
|
||||
* badgeimage - Badge image.
|
||||
* expireddate - Date (in the past) when the badge expired (if defined). If expiredate is defined, this field will be empty.
|
||||
* expireddateformatted - Formatted expired date.
|
||||
* expiredate - Date (in the future) when the badge will expire (if defined). If expireddate is defined, this field will be empty.
|
||||
* expireddate - Date (in the past) when the badge expired. If expiredate is defined, this field will be empty [optional].
|
||||
* expireddateformatted - Formatted expired date [optional].
|
||||
* expiredate - Date (in the future) when the badge will expire. If expireddate is defined, this field will be empty [optional].
|
||||
* badgename - Badge name.
|
||||
* badgedescription - Badge description.
|
||||
* badgeissuedon - Date where the badge was issued on by the user.
|
||||
* recipientname - User awarded with the badge.
|
||||
* recipientnotification.message - Message to be displayed if there is some issue with the recipient.
|
||||
* badgeissuedon - Date where the badge was issued on by the user [optional].
|
||||
* recipientname - User awarded with the badge [optional].
|
||||
* recipientnotification.message - Message to be displayed if there is some issue with the recipient [optional].
|
||||
* criteria - HTML code with the criteria to display.
|
||||
* issuedby - Badge issuer.
|
||||
* issuedbyemailobfuscated - Badge issuer email link obfuscated.
|
||||
@ -139,22 +139,27 @@
|
||||
|
||||
<div id="badge-details-col" class="col">
|
||||
<h2>{{badgename}}</h2>
|
||||
|
||||
{{#recipientname}}
|
||||
<div id="badge-awardedto" class="pt-1 pb-2">
|
||||
{{#recipientnotification}}
|
||||
{{> core/notification_warning}}
|
||||
{{/recipientnotification}}
|
||||
{{#str}}awardedto, core_badges, {{recipientname}}{{/str}}
|
||||
</div>
|
||||
{{/recipientname}}
|
||||
|
||||
<div id="badge-issued-expire" class="pt-1 pb-2">
|
||||
<div class="pb-3">
|
||||
<small>
|
||||
{{#str}}
|
||||
issuedon,
|
||||
core_badges,
|
||||
{{#userdate}}{{badgeissuedon}}, {{#str}} strftimedatetime, langconfig {{/str}}{{/userdate}}
|
||||
{{/str}}
|
||||
<br/>
|
||||
{{#badgeissuedon}}
|
||||
{{#str}}
|
||||
issuedon,
|
||||
core_badges,
|
||||
{{#userdate}}{{badgeissuedon}}, {{#str}} strftimedatetime, langconfig {{/str}}{{/userdate}}
|
||||
{{/str}}
|
||||
<br/>
|
||||
{{/badgeissuedon}}
|
||||
{{#expiredate}}
|
||||
{{#str}}
|
||||
expiresin,
|
||||
|
@ -73,7 +73,11 @@ class badge_viewed extends base {
|
||||
* @return \moodle_url
|
||||
*/
|
||||
public function get_url() {
|
||||
return new \moodle_url('/badges/badge.php', array('hash' => $this->other['badgehash']));
|
||||
if (isset($this->other['badgehash'])) {
|
||||
return new \moodle_url('/badges/badge.php', ['hash' => $this->other['badgehash']]);
|
||||
}
|
||||
|
||||
return new \moodle_url('/badges/badgeclass.php', ['id' => $this->other['badgeid']]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,9 +92,6 @@ class badge_viewed extends base {
|
||||
if (!isset($this->other['badgeid'])) {
|
||||
throw new \coding_exception('The \'badgeid\' must be set in other.');
|
||||
}
|
||||
if (!isset($this->other['badgehash'])) {
|
||||
throw new \coding_exception('The \'badgehash\' must be set in other.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user