Commit 27e4948b authored by Aaron Wells's avatar Aaron Wells Committed by Gerrit Code Review

Merge changes from topic 'openbadges'

* changes:
  Bug 1536393: tidying up some final bits of the plugin
  Fix errors when exporting Leap2A. Bug 1536393
  Fix modal dialog for openbadgedisplayer. Bug 1536393
  Enhance the openbadgedisplayer plugin. Bug 1536393
  Add default openbadge sources. Bug 1536393
  Openbadges - Style, add icon, remove inline css. Bug 1536393
  Add openbadgedisplayer plugin. Bug 1536393
parents 7eb59ff0 b544595e
<?php
/**
*
* @package mahara
* @subpackage blocktype-openbadgedisplayer
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
define('INTERNAL', 1);
define('JSON', 1);
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
safe_require('blocktype', 'openbadgedisplayer');
$host = param_variable('host', null);
$email = param_variable('email', null);
if (!isset($host) || !isset($email)) {
json_reply('local', get_string('parameterexception', 'error'));
}
// Make sure the email belongs to the current user
$emails = get_column('artefact_internal_profile_email', 'email', 'owner', $USER->id, 'verified', 1);
if (!isset($emails) || !in_array($email, $emails)) {
json_reply('local', get_string('accessdeniedbadge', 'error'));
}
$uid = PluginBlocktypeOpenbadgedisplayer::get_backpack_id($host, $email);
$hosttitle = get_string('title_' . $host, 'blocktype.openbadgedisplayer');
json_reply(false, array(
'host' => $host,
'hosttitle' => $hosttitle,
'uid' => $uid,
'badgegroups' => isset($uid) ? PluginBlocktypeOpenbadgedisplayer::get_badgegroupnames($host, $uid) : null,
'nobackpackmsg' => get_string('nobackpackidin', 'blocktype.openbadgedisplayer', $hosttitle),
'nobadgegroupsmsg' => get_string('nobadgegroupsin', 'blocktype.openbadgedisplayer', $hosttitle)
));
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="lib/db" VERSION="20060926" COMMENT="XMLDB file for core Mahara tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="blocktype_openbadgedisplayer_data">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" SEQUENCE="true" NOTNULL="true" />
<FIELD NAME="host" TYPE="char" LENGTH="255" NOTNULL="true" />
<FIELD NAME="uid" TYPE="int" LENGTH="10" NOTNULL="true" />
<FIELD NAME="badgegroupid" TYPE="int" LENGTH="10" NOTNULL="true" />
<FIELD NAME="name" TYPE="text" NOTNULL="false" />
<FIELD NAME="html" TYPE="text" NOTNULL="false" />
<FIELD NAME="lastupdate" TYPE="datetime" NOTNULL="false" />
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" />
</KEYS>
<INDEXES>
<INDEX NAME="hostuidix" UNIQUE="false" FIELDS="host,uid"/>
<INDEX NAME="hostuidbadgegroupidix" UNIQUE="true" FIELDS="host,uid,badgegroupid"/>
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
<?php
defined('INTERNAL') || die();
function xmldb_blocktype_openbadgedisplayer_upgrade($oldversion = 0) {
if ($oldversion < 2015062301) {
$blocks = get_records_array('block_instance', 'blocktype', 'openbadgedisplayer');
if (is_array($blocks)) {
foreach ($blocks as $block) {
$configdata = unserialize($block->configdata);
if (isset($configdata['badgegroup'])) {
// Append source to legacy values
if (is_string($configdata['badgegroup'])) {
$configdata['badgegroup'] = 'backpack:' . $configdata['badgegroup'];
}
else if (is_array($configdata['badgegroup'])) {
foreach ($configdata['badgegroup'] as &$group) {
$group = str_replace('https://openbadgepassport.com/', 'passport', $group);
$group = str_replace('https://backpack.openbadges.org/', 'backpack', $group);
}
}
$block->configdata = serialize($configdata);
update_record('block_instance', $block, 'id');
}
}
}
}
if ($oldversion < 2016030200) {
// Add a new table blocktype_openbadgedisplayer_data for storing prefetch badges
$table = new XMLDBTable('blocktype_openbadgedisplayer_data');
$table->addFieldInfo('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE);
$table->addFieldInfo('host', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL);
$table->addFieldInfo('uid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL);
$table->addFieldInfo('badgegroupid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL);
$table->addFieldInfo('name', XMLDB_TYPE_TEXT);
$table->addFieldInfo('html', XMLDB_TYPE_TEXT);
$table->addFieldInfo('lastupdate', XMLDB_TYPE_DATETIME);
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->addIndexInfo('hostuidix', XMLDB_INDEX_NOTUNIQUE, array('host', 'uid'));
$table->addIndexInfo('hostuidbadgegroupidix', XMLDB_INDEX_UNIQUE, array('host', 'uid', 'badgegroupid'));
create_table($table);
}
return true;
}
\ No newline at end of file
/**
* Asynchronous loading badges
*
* @package mahara
* @subpackage blocktype-openbadgedisplayer
* @author Discendum Oy
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*/
/* pieform_element_checkboxes_get_headdata() includes the javascript
needed by the "Select all/none" -links. That function isn't called
when the config form is rendered, so let's just copy the code here
and add it to window scope.*/
if (typeof pieform_element_checkboxes_update === 'undefined') {
window.pieform_element_checkboxes_update = function (p, v) {
forEach(getElementsByTagAndClassName('input', 'checkboxes', p), function(e) {
if (!e.disabled) {
e.checked = v;
}
});
if (typeof formchangemanager !== 'undefined') {
var form = jQuery('div#' + p).closest('form')[0];
formchangemanager.setFormState(form, FORM_CHANGED);
}
};
}
var badgegroups_hosts = JSON.parse(jQuery("input#instconf_hosts").val());
var badgegroups_emails = JSON.parse(jQuery("input#instconf_emails").val());
var selectedbadgegroups = JSON.parse(jQuery("input#instconf_selectedbadgegroups").val());
if ((badgegroups_hosts instanceof Array && badgegroups_hosts.length >= 1)
&& (badgegroups_emails instanceof Array && badgegroups_emails.length >= 1)) {
var count=0;
jQuery("div#instconf_loadinginfo_container > p.alert").removeClass('hidden');
for (var i=0; i < badgegroups_hosts.length; i++) {
var h = badgegroups_hosts[i];
for (var j=0; j < badgegroups_emails.length; j++) {
var e = badgegroups_emails[j];
var params = {'host': h, 'email': e};
count++;
/* Fetching the badge info via ajax and render the pieform checkbox element */
sendjsonrequest(config['wwwroot'] + '/blocktype/openbadgedisplayer/badgegroupnames.json.php', params, 'POST', function(data) {
var icon = jQuery('<span class="icon icon-lg icon-exclamation-triangle left" aria-hidden="true" role="presentation"></span>');
var container = jQuery('<div class="alert alert-warning" role="alert">');
if (!data.uid) {
var msg = jQuery('<span>').text(data.nobackpackmsg);
container.append(icon).append(msg);
jQuery("div#instconf_loadinginfo_container > div").append(container);
}
else if (!data.badgegroups || data.badgegroups.length === 0) {
var msg = jQuery('<span>').text(data.nobadgegroupsmsg);
container.append(icon).append(msg);
jQuery("div#instconf_loadinginfo_container > div").append(container);
}
else {
var htmlstr =
'<div id="instconf_' + data.host + '_container" class="checkboxes form-group">' +
'<span class="pseudolabel">' + data["hosttitle"] + '</span>' +
'<div class="btn-group">' +
'<a href="" class="btn btn-default btn-xs" onclick="pieform_element_checkboxes_update(\'instconf_' + data["host"] + '_container\', true); return false;">Select all</a>' +
'<a href="" class="btn btn-default btn-xs" onclick="pieform_element_checkboxes_update(\'instconf_' + data["host"] + '_container\', false); return false;">Select none</a>&nbsp;' +
'</div>';
for (var badgegroupid in data.badgegroups) {
var badgegroupname = data.badgegroups[badgegroupid];
var checkboxvalue = data["host"] + ':' + data["uid"] + ':' + badgegroupid;
var checkboxid = data["host"] + '_' + data["uid"] + '_' + badgegroupid;
var selected = '';
if (jQuery.inArray(checkboxvalue, selectedbadgegroups) != -1) {
selected = 'checked';
}
htmlstr +=
'<div class="checkboxes-option checkbox">' +
'<input type="checkbox" id="instconf_' + checkboxid + '"name="' + data["host"] + '[]" value="' + checkboxvalue + '" ' + selected + ' class="checkboxes">' +
'<label class="checkbox" for="instconf_' + checkboxid + '">' +
'<span class="accessible-hidden sr-only">' + data["hosttitle"] + ': </span>' +
badgegroupname +
'</label>' +
'</div>';
}
htmlstr +=
'<div class="cl"></div>' +
'</div>';
jQuery("div#instconf_loadinginfo_container > div").append(htmlstr);
}
count--;
if (count == 0) {
jQuery("div#instconf_loadinginfo_container > p.alert").addClass('hidden');
}
});
}
}
}
/**
* Show badges details in a modal dialog
*
* @package mahara
* @subpackage blocktype-openbadgedisplayer
* @author Discendum Oy
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*/
function shorten(str) {
var n = 40;
return str.substr(0, n - 1) + (str.length > n ? '...' : '');
}
function formatDate(date) {
if (!date) {
return '-';
}
if (date.toString().match(/^[0-9]+$/)) {
var d = new Date(0);
d.setUTCSeconds(date);
return d.toLocaleDateString();
}
return date;
}
function urlElement(url) {
if (!url) {
return '-';
}
return jQuery('<a/>').attr({ href: url, title: url }).text(shorten(url));
}
function buildBadgeContent(assertion) {
var el = jQuery('.badge-template').clone().removeClass('badge-template');
el.find('img.badge-image').attr('src', assertion.badge.image);
el.find('tr.issuer-name td.value').text(assertion.badge.issuer.name);
el.find('tr.issuer-url td.value').html(urlElement(assertion.badge.issuer.origin));
el.find('tr.issuer-organization td.value').text(assertion.badge.issuer.org || '-');
el.find('tr.badge-name td.value').text(assertion.badge.name);
el.find('tr.badge-description td.value').text(assertion.badge.description);
el.find('tr.badge-criteria td.value').html(urlElement(assertion.badge.criteria));
el.find('tr.issuance-evidence td.value').html(urlElement(assertion.evidence));
el.find('tr.issuance-issuedon td.value').text(formatDate(assertion.issued_on));
el.find('tr.issuance-expires td.value').text(formatDate(assertion.expires));
return el.prop('outerHTML');
}
function showBadgeContent(data) {
/* Add a modal dialog if not exists */
if (jQuery('div#content').length == 1 && jQuery('div#content #badge-content-dialog').length == 0) {
jQuery('div#content').append(
'<div id="badge-content-dialog" class="modal fade page-modal js-page-modal" role="dialog">' +
' <div class="modal-dialog">' +
' <div class="modal-content">' +
' <div class="modal-body"></div>' +
' <div class="modal-footer">' +
' <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>' +
' </div>' +
' </div>' +
' </div>' +
'</div>');
}
jQuery('#badge-content-dialog .modal-body').html(data.html);
jQuery('#badge-content-dialog').modal('show');
}
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2011 Catalyst IT Ltd and others; see:
* http://wiki.mahara.org/Contributors
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package mahara
* @subpackage blocktype-openbadgedisplayer
* @author Discendum Oy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2012 Discedum Oy http://discendum.com
* @copyright (C) 2011 Catalyst IT Ltd http://catalyst.net.nz
*
*/
defined('INTERNAL') || die();
$string['title'] = 'Open Badges';
$string['description'] = 'Display your Open Badges';
$string['issuerdetails'] = 'Issuer Details';
$string['badgedetails'] = 'Badge Details';
$string['issuancedetails'] = 'Issuance Details';
$string['name'] = 'Name';
$string['url'] = 'URL';
$string['organization'] = 'Organization';
$string['evidence'] = 'Evidence';
$string['issuedon'] = 'Issued On';
$string['expires'] = 'Expires';
$string['desc'] = 'Description';
$string['criteria'] = 'Criteria';
$string['nbadges'] = array('1 badge', '%s badges');
$string['nobackpack'] = 'No Backpack found.<br> Please add your <a href="%s">Backpack</a> email address to your <a href="%s">profile</a>.';
$string['nobadgegroups'] = 'No public badge collections/badges found.';
$string['nobackpackidin'] = 'Your email is not found in the service %s.';
$string['nobadgegroupsin'] = 'No public badge collections/badges found in the service: %s.';
$string['confighelp'] = 'Select the badge collections to show in this block.<br/>Visit the following services to manage your collections and badges:<br/>%s';
$string['obppublicbadges'] = 'All public badges in Open Badge Passport';
$string['title_backpack'] = 'Mozilla Backpack';
$string['title_passport'] = 'Open Badge Passport';
$string['fetchingbadges'] = 'Fetching entries. This may take a while.';
This diff is collapsed.
<?php
/**
* Mahara: Electronic portfolio, weblog, resume builder and social networking
* Copyright (C) 2006-2011 Catalyst IT Ltd and others; see:
* http://wiki.mahara.org/Contributors
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* @package mahara
* @subpackage blocktype-openbadgedisplayer
* @author Discendum Oy
* @author Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2012 Discedum Oy http://discendum.com
* @copyright (C) 2011 Catalyst IT Ltd http://catalyst.net.nz
*
*/
defined('INTERNAL') || die();
$config = new StdClass;
$config->version = 2016030200;
$config->release = '1.0.5';
......@@ -12,14 +12,14 @@
function showPreview(size, data) {
if (size === 'small') {
jQuery('.js-page-modal .modal-dialog').removeClass('modal-lg');
jQuery('#page-modal .modal-dialog').removeClass('modal-lg');
}
else {
jQuery('.js-page-modal .modal-dialog').addClass('modal-lg');
jQuery('#page-modal .modal-dialog').addClass('modal-lg');
}
jQuery('.js-page-modal .modal-body').html(data.html);
jQuery('.js-page-modal').modal('show');
jQuery('#page-modal .modal-body').html(data.html);
jQuery('#page-modal').modal('show');
}
......
......@@ -91,6 +91,7 @@ $string['accessdenied'] = 'Access denied';
$string['accessdeniedobjection'] = 'Access denied. The objection has already been resolved by another administrator.';
$string['accessdeniedexception'] = 'You do not have access to view this page.';
$string['accessdeniednourlsecret'] = 'You do not have access to this functionality. Please provide the value for "urlsecret" from your config.php file as part of the URL.';
$string['accessdeniedbadge'] = 'You do not have access to view this badge.';
$string['viewnotfoundexceptiontitle'] = 'Page not found';
$string['viewnotfoundexceptionmessage'] = 'You tried to access a page that does not exist.';
......
......@@ -695,3 +695,12 @@ $cfg->urlsecret = 'mysupersecret';
* There are up to 20 alternate salts (e.g. $cfg->passwordsaltalt2, $cfg->passwordsaltalt3, etc)
*/
$cfg->passwordsaltalt1 = 'old salt value';
/**
* @global array $cfg->openbadgedisplayer_source The open badge sources
* The default sources are Mozilla Backpack and openbadgepassport.com
*/
$cfg->openbadgedisplayer_source = array(
'backpack' => 'https://backpack.openbadges.org/',
'passport' => 'https://openbadgepassport.com/'
);
......@@ -4405,5 +4405,12 @@ function xmldb_core_upgrade($oldversion=0) {
change_field_precision($table, $field);
}
if ($oldversion < 2016033100) {
log_debug('Upgrade openbadgedisplayer plugin');
if ($data = check_upgrades('blocktype.openbadgedisplayer')) {
upgrade_plugin($data);
}
}
return $status;
}
......@@ -16,7 +16,7 @@ $config = new stdClass();
// See https://wiki.mahara.org/wiki/Developer_Area/Version_Numbering_Policy
// For upgrades on stable branches, increment the version by one. On master, use the date.
$config->version = 2016032900;
$config->version = 2016033100;
$config->series = '16.04';
$config->release = '16.04dev';
$config->minupgradefrom = 2012080604;
......
.openbadgedisplayer {
padding: 10px;
}
.openbadgedisplayer img {
cursor: pointer;
margin: 0 10px 10px 0;
width: 90px;
height: 90px;
}
.badge-template {
display: none;
}
.badge-container .badge-image {
width: 90px;
height: 90px;
float: left;
}
.badge-container .openbadge-details {
margin-left: 120px;
}
.openbadges-block img {
width: 90px;
height: 90px;
float: left;
cursor: pointer;
padding: 5px;
}
.openbadge-img {
float: left;
width: 90px;
}
.openbadge-details {
margin-left: 120px;
}
.openbadge-details h3:first-child {
margin-top: 0;
}
.openbadge-details tr td:first-child {
min-width: 80px;
}
{{$sec = 'blocktype.openbadgedisplayer'}}
<div class="badge-template badge-container">
<img class="badge-image" src="" />
<div class="openbadge-details">
<h3>{{str tag=issuerdetails section=$sec}}</h3>
<table>
<tbody>
<tr class="issuer-name"><td>{{str tag=name section=$sec}}</td><td class="value"></td></tr>
<tr class="issuer-url"><td>{{str tag=url section=$sec}}</td><td class="value"></td></tr>
<tr class="issuer-organization"><td>{{str tag=organization section=$sec}}</td><td class="value"></td></tr>
</tbody>
</table>
<h3>{{str tag=badgedetails section=$sec}}</h3>
<table>
<tbody>
<tr class="badge-name"><td>{{str tag=name section=$sec}}</td><td class="value"></td></tr>
<tr class="badge-description"><td>{{str tag=desc section=$sec}}</td><td class="value"></td></tr>
<tr class="badge-criteria"><td>{{str tag=criteria section=$sec}}</td><td class="value"></td></tr>
</tbody>
</table>
<h3>{{str tag=issuancedetails section=$sec}}</h3>
<table>
<tbody>
<tr class="issuance-evidence"><td>{{str tag=evidence section=$sec}}</td><td class="value"></td></tr>
<tr class="issuance-issuedon"><td>{{str tag=issuedon section=$sec}}</td><td class="value"></td></tr>
<tr class="issuance-expires"><td>{{str tag=expires section=$sec}}</td><td class="value"></td></tr>
</tbody>
</table>
</div>
</div>
\ No newline at end of file
<div id="openbadges{{$id}}" class="openbadgedisplayer">{{$badgehtml|safe}}</div>
<script type="application/javascript">
(function ($) {
$(function () {
$('#openbadges{{$id}}').on('click', 'img', function () {
showBadgeContent({html: buildBadgeContent($(this).data('assertion'))});
});
});
})(jQuery);
</script>
{{include file="blocktype:openbadgedisplayer:badge.tpl"}}
......@@ -3,7 +3,7 @@
<div class="modal-content">
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-default" data-dismiss="modal">{str tag=Close}</button>
</div>
</div>
</div>
......
@javascript @core @blocktype @blocktype_openbadgedisplayer
Feature: The openbadges block should be present
In order to make sure it is installed
As a user I add the block to a page
Background:
Given the following "users" exist:
| username | password | email | firstname | lastname | institution | authname | role |
| userA | Kupuhipa1 | test01@example.com | Pete | Mc | mahara | internal | member |
And the following "pages" exist:
| title | description| ownertype | ownername |
| Page 1 | page P1 | user | userA |
Scenario: Open badges block
# As the open badges block normally fetches user data from third
# party site we can't currently test that part and ship the details in this test
# So all we can do is check that the block exists and saves to a page
Given I log in as "userA" with password "Kupuhipa1"
And I choose "Pages" in "Portfolio"
And I follow "Edit \"Page 1\""
And I expand "External" node
And I wait "1" seconds
And I follow "Open Badges"
And I press "Add"
And I wait "5" seconds
Then I should see "Your email is not found in the service"
And I press "Save"
Then I should see "No public badge collections/badges found."
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment