Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

MDL-39063 badges: Improve external backpack usability and workflow

  • Loading branch information...
commit e280531436d080082aad9ef56de1598c06303065 1 parent 9aae755
Yuliya Bozhko ybozhko authored
9 admin/settings/badges.php
@@ -70,7 +70,14 @@
70 70 new admin_externalpage('managebadges',
71 71 new lang_string('managebadges', 'badges'),
72 72 new moodle_url($CFG->wwwroot . '/badges/index.php', array('type' => BADGE_TYPE_SITE)),
73   - array('moodle/badges:viewawarded')
  73 + array(
  74 + 'moodle/badges:viewawarded',
  75 + 'moodle/badges:createbadge',
  76 + 'moodle/badges:awardbadge',
  77 + 'moodle/badges:configuremessages',
  78 + 'moodle/badges:configuredetails',
  79 + 'moodle/badges:deletebadge'
  80 + )
74 81 )
75 82 );
76 83
2  badges/action.php
@@ -125,7 +125,7 @@
125 125 } else {
126 126 $awards = $badge->review_all_criteria();
127 127 $returnurl->param('awards', $awards);
128   - }
  128 + }
129 129 redirect($returnurl);
130 130 }
131 131
100 badges/backpack_form.php
@@ -42,14 +42,17 @@ public function definition() {
42 42 global $USER;
43 43 $mform = $this->_form;
44 44
45   - $mform->addElement('header', 'backpackheader', get_string('backpackdetails', 'badges'));
  45 + $mform->addElement('header', 'backpackheader', get_string('backpackconnection', 'badges'));
  46 + $mform->addHelpButton('backpackheader', 'backpackconnection', 'badges');
46 47 $mform->addElement('static', 'url', get_string('url'), 'http://backpack.openbadges.org');
  48 + $status = html_writer::tag('span', get_string('notconnected', 'badges'), array('class' => 'notconnected'));
  49 + $mform->addElement('static', 'status', get_string('status'), $status);
47 50
48 51 $mform->addElement('text', 'email', get_string('email'), array('size' => '50'));
49 52 $mform->setDefault('email', $USER->email);
50   - $mform->setType('email', PARAM_EMAIL);
  53 + $mform->setType('email', PARAM_RAW);
51 54 $mform->addRule('email', get_string('required'), 'required', null , 'client');
52   - $mform->addRule('email', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
  55 + $mform->addHelpButton('email', 'backpackemail', 'badges');
53 56
54 57 $mform->addElement('hidden', 'userid', $USER->id);
55 58 $mform->setType('userid', PARAM_INT);
@@ -57,15 +60,38 @@ public function definition() {
57 60 $mform->addElement('hidden', 'backpackurl', 'http://backpack.openbadges.org');
58 61 $mform->setType('backpackurl', PARAM_URL);
59 62
60   - $this->add_action_buttons();
  63 + $this->add_action_buttons(true, get_string('connect', 'badges'));
  64 + }
  65 +
  66 + /**
  67 + * Validates form data
  68 + */
  69 + public function validation($data, $files) {
  70 + global $DB;
  71 + $errors = parent::validation($data, $files);
  72 +
  73 + if (!validate_email($data['email'])) {
  74 + $errors['email'] = get_string('invalidemail');
  75 + } else {
  76 + $check = new stdClass();
  77 + $check->backpackurl = $data['backpackurl'];
  78 + $check->email = $data['email'];
  79 +
  80 + $bp = new OpenBadgesBackpackHandler($check);
  81 + $request = $bp->curl_request('user');
  82 + if (isset($request->status) && $request->status == 'missing') {
  83 + $errors['email'] = get_string('error:nosuchuser', 'badges');
  84 + }
  85 + }
  86 + return $errors;
61 87 }
62 88 }
63 89
64 90 /**
65   - * Form to select backpack group options.
  91 + * Form to select backpack collections.
66 92 *
67 93 */
68   -class edit_backpack_group_form extends moodleform {
  94 +class edit_collections_form extends moodleform {
69 95
70 96 /**
71 97 * Defines the form
@@ -73,38 +99,48 @@ class edit_backpack_group_form extends moodleform {
73 99 public function definition() {
74 100 global $USER;
75 101 $mform = $this->_form;
76   - $data = $this->_customdata['data'];
77   - $groups = $this->_customdata['groups'];
78   - $uid = $this->_customdata['backpackuid'];
79   -
80   - $selet = array();
81   - foreach ($groups as $group) {
82   - $select[$group->groupId] = $group->name;
  102 + $email = $this->_customdata['email'];
  103 + $bid = $this->_customdata['backpackid'];
  104 + $selected = $this->_customdata['selected'];
  105 +
  106 + if (isset($this->_customdata['groups'])) {
  107 + $groups = $this->_customdata['groups'];
  108 + $nogroups = null;
  109 + } else {
  110 + $groups = null;
  111 + $nogroups = $this->_customdata['nogroups'];
83 112 }
84 113
85   - $mform->addElement('header', 'groupheader', get_string('backpackdetails', 'badges'));
  114 + $mform->addElement('header', 'backpackheader', get_string('backpackconnection', 'badges'));
  115 + $mform->addHelpButton('backpackheader', 'backpackconnection', 'badges');
86 116 $mform->addElement('static', 'url', get_string('url'), 'http://backpack.openbadges.org');
87 117
88   - $mform->addElement('text', 'email', get_string('email'), array('size' => '50'));
89   - $mform->setType('email', PARAM_EMAIL);
90   - $mform->setDefault('email', $data->email);
91   - $mform->freeze(array('email'));
92   -
93   - $mform->addElement('select', 'backpackgid', get_string('selectgroup', 'badges'), $select);
94   - $mform->addRule('backpackgid', get_string('required'), 'required', null , 'client');
95   - if (isset($data->backpackgid)) {
96   - $mform->setDefault('backpackgid', $data->backpackgid);
  118 + $status = html_writer::tag('span', get_string('connected', 'badges'), array('class' => 'connected'));
  119 + $mform->addElement('static', 'status', get_string('status'), $status);
  120 + $mform->addElement('static', 'email', get_string('email'), $email);
  121 + $mform->addHelpButton('email', 'backpackemail', 'badges');
  122 + $mform->addElement('submit', 'disconnect', get_string('disconnect', 'badges'));
  123 +
  124 + $mform->addElement('header', 'collectionheader', get_string('backpackimport', 'badges'));
  125 + $mform->addHelpButton('collectionheader', 'backpackimport', 'badges');
  126 +
  127 + if (!empty($groups)) {
  128 + $mform->addElement('static', 'selectgroup', '', get_string('selectgroup_start', 'badges'));
  129 + foreach ($groups as $group) {
  130 + $name = $group->name . ' (' . $group->badges . ')';
  131 + $mform->addElement('advcheckbox', 'group[' . $group->groupId . ']', null, $name, array('group' => 1), array(false, $group->groupId));
  132 + if (in_array($group->groupId, $selected)) {
  133 + $mform->setDefault('group[' . $group->groupId . ']', $group->groupId);
  134 + }
  135 + }
  136 + $mform->addElement('static', 'selectgroup', '', get_string('selectgroup_end', 'badges'));
  137 + } else {
  138 + $mform->addElement('static', 'selectgroup', '', $nogroups);
97 139 }
98 140
99   - $mform->addElement('hidden', 'userid', $data->userid);
100   - $mform->setType('userid', PARAM_INT);
101   -
102   - $mform->addElement('hidden', 'backpackurl', 'http://backpack.openbadges.org');
103   - $mform->setType('backpackurl', PARAM_URL);
104   -
105   - $mform->addElement('hidden', 'backpackuid', $uid);
106   - $mform->setType('backpackuid', PARAM_INT);
  141 + $mform->addElement('hidden', 'backpackid', $bid);
  142 + $mform->setType('backpackid', PARAM_INT);
107 143
108 144 $this->add_action_buttons();
109 145 }
110   -}
  146 +}
15 badges/edit_form.php
@@ -83,8 +83,7 @@ public function definition() {
83 83 if (isset($CFG->badges_defaultissuercontact)) {
84 84 $mform->setDefault('issuercontact', $CFG->badges_defaultissuercontact);
85 85 }
86   - $mform->setType('issuercontact', PARAM_EMAIL);
87   - $mform->addRule('issuercontact', get_string('invalidemail', 'moodle'), 'email', null, 'client', true);
  86 + $mform->setType('issuercontact', PARAM_RAW);
88 87 $mform->addHelpButton('issuercontact', 'contact', 'badges');
89 88
90 89 $mform->addElement('header', 'issuancedetails', get_string('issuancedetails', 'badges'));
@@ -163,6 +162,10 @@ public function validation($data, $files) {
163 162 global $DB;
164 163 $errors = parent::validation($data, $files);
165 164
  165 + if (!empty($data['issuercontact']) && !validate_email($data['issuercontact'])) {
  166 + $errors['issuercontact'] = get_string('invalidemail');
  167 + }
  168 +
166 169 if ($data['expiry'] == 2 && $data['expireperiod'] <= 0) {
167 170 $errors['expirydategr'] = get_string('error:invalidexpireperiod', 'badges');
168 171 }
@@ -173,11 +176,11 @@ public function validation($data, $files) {
173 176
174 177 // Check for duplicate badge names.
175 178 if ($data['action'] == 'new') {
176   - $duplicate = $DB->record_exists_select('badge', 'name = :name',
177   - array('name' => $data['name']));
  179 + $duplicate = $DB->record_exists_select('badge', 'name = :name AND status != :deleted',
  180 + array('name' => $data['name'], 'deleted' => BADGE_STATUS_ARCHIVED));
178 181 } else {
179   - $duplicate = $DB->record_exists_select('badge', 'name = :name AND id != :badgeid',
180   - array('name' => $data['name'], 'badgeid' => $data['id']));
  182 + $duplicate = $DB->record_exists_select('badge', 'name = :name AND id != :badgeid AND status != :deleted',
  183 + array('name' => $data['name'], 'badgeid' => $data['id'], 'deleted' => BADGE_STATUS_ARCHIVED));
181 184 }
182 185
183 186 if ($duplicate) {
8 badges/index.php
@@ -87,7 +87,13 @@
87 87 );
88 88 }
89 89
90   -if (!has_capability('moodle/badges:awardbadge', $PAGE->context)) {
  90 +if (!has_any_capability(array(
  91 + 'moodle/badges:viewawarded',
  92 + 'moodle/badges:createbadge',
  93 + 'moodle/badges:awardbadge',
  94 + 'moodle/badges:configuremessages',
  95 + 'moodle/badges:configuredetails',
  96 + 'moodle/badges:deletebadge'), $PAGE->context)) {
91 97 redirect($CFG->wwwroot);
92 98 }
93 99
15 badges/lib/backpacklib.php
@@ -36,28 +36,26 @@ class OpenBadgesBackpackHandler {
36 36 private $backpack;
37 37 private $email;
38 38 private $backpackuid = 0;
39   - private $backpackgid = 0;
40 39
41 40 public function __construct($record) {
42 41 $this->backpack = $record->backpackurl;
43 42 $this->email = $record->email;
44 43 $this->backpackuid = isset($record->backpackuid) ? $record->backpackuid : 0;
45   - $this->backpackgid = isset($record->backpackgid) ? $record->backpackgid : 0;
46 44 }
47 45
48   - public function curl_request($action) {
  46 + public function curl_request($action, $collection = null) {
49 47 $curl = new curl();
50 48
51 49 switch($action) {
52 50 case 'user':
53   - $url = $this->backpack."/displayer/convert/email";
  51 + $url = $this->backpack . "/displayer/convert/email";
54 52 $param = array('email' => $this->email);
55 53 break;
56 54 case 'groups':
57 55 $url = $this->backpack . '/displayer/' . $this->backpackuid . '/groups.json';
58 56 break;
59 57 case 'badges':
60   - $url = $this->backpack . '/displayer/' . $this->backpackuid . '/group/'. $this->backpackgid . '.json';
  58 + $url = $this->backpack . '/displayer/' . $this->backpackuid . '/group/' . $collection . '.json';
61 59 break;
62 60 }
63 61
@@ -86,11 +84,10 @@ private function check_status($status) {
86 84 'message' => get_string('error:nosuchuser', 'badges')
87 85 );
88 86 return $response;
89   - break;
90 87 }
91 88 }
92 89
93   - public function get_groups() {
  90 + public function get_collections() {
94 91 $json = $this->curl_request('user', $this->email);
95 92 if (isset($json->status)) {
96 93 if ($json->status != 'okay') {
@@ -102,13 +99,13 @@ public function get_groups() {
102 99 }
103 100 }
104 101
105   - public function get_badges() {
  102 + public function get_badges($collection) {
106 103 $json = $this->curl_request('user', $this->email);
107 104 if (isset($json->status)) {
108 105 if ($json->status != 'okay') {
109 106 return $this->check_status($json->status);
110 107 } else {
111   - return $this->curl_request('badges');
  108 + return $this->curl_request('badges', $collection);
112 109 }
113 110 }
114 111 }
144 badges/mybackpack.php
@@ -38,7 +38,7 @@
38 38 $context = context_user::instance($USER->id);
39 39 require_capability('moodle/badges:manageownbadges', $context);
40 40
41   -$clear = optional_param('clear', false, PARAM_BOOL);
  41 +$disconnect = optional_param('disconnect', false, PARAM_BOOL);
42 42
43 43 if (empty($CFG->badges_allowexternalbackpack)) {
44 44 redirect($CFG->wwwroot);
@@ -52,113 +52,77 @@
52 52 $PAGE->set_heading($title);
53 53 $PAGE->set_pagelayout('mydashboard');
54 54
55   -navigation_node::override_active_url(new moodle_url('/badges/mybadges.php'));
56   -$PAGE->navbar->add(get_string('mybackpack', 'badges'));
  55 +$backpack = $DB->get_record('badge_backpack', array('userid' => $USER->id));
57 56
58   -if ($clear) {
59   - $DB->delete_records('badge_backpack', array('userid' => $USER->id));
60   - redirect(new moodle_url('/badges/mybadges.php'));
  57 +if ($disconnect && $backpack) {
  58 + require_sesskey();
  59 + $DB->delete_records('badge_external', array('backpackid' => $backpack->id));
  60 + $DB->delete_records('badge_backpack', array('userid' => $USER->id));
  61 + redirect(new moodle_url('/badges/mybackpack.php'));
61 62 }
62 63
63   -$backpack = $DB->get_record('badge_backpack', array('userid' => $USER->id));
64   -
65 64 if ($backpack) {
  65 + // If backpack is connected, need to select collections.
66 66 $bp = new OpenBadgesBackpackHandler($backpack);
67   - $request = $bp->get_groups();
68   -
  67 + $request = $bp->get_collections();
69 68 if (empty($request->groups)) {
70   - unset($SESSION->badgesparams);
71   - redirect(new moodle_url('/badges/mybadges.php'), get_string('error:nogroups', 'badges'), 20);
  69 + $params['nogroups'] = get_string('error:nogroups', 'badges');
  70 + } else {
  71 + $params['groups'] = $request->groups;
72 72 }
  73 + $params['email'] = $backpack->email;
  74 + $params['selected'] = $DB->get_fieldset_select('badge_external', 'collectionid', 'backpackid = :bid', array('bid' => $backpack->id));
  75 + $params['backpackid'] = $backpack->id;
  76 + $form = new edit_collections_form(new moodle_url('/badges/mybackpack.php'), $params);
73 77
74   - $params = array(
75   - 'data' => $backpack,
76   - 'backpackuid' => $request->userId,
77   - 'groups' => $request->groups
78   - );
79   - $groupform = new edit_backpack_group_form(new moodle_url('/badges/mybackpack.php'), $params);
80   -
81   - if ($groupform->is_cancelled()) {
  78 + if ($form->is_cancelled()) {
82 79 redirect(new moodle_url('/badges/mybadges.php'));
83   - } else if ($groupdata = $groupform->get_data()) {
84   - $obj = new stdClass();
85   - $obj->userid = $groupdata->userid;
86   - $obj->email = $groupdata->email;
87   - $obj->backpackurl = $groupdata->backpackurl;
88   - $obj->backpackuid = $groupdata->backpackuid;
89   - $obj->backpackgid = $groupdata->backpackgid;
90   - $obj->autosync = 0;
91   - $obj->password = '';
92   - if ($rec = $DB->get_record('badge_backpack', array('userid' => $groupdata->userid))) {
93   - $obj->id = $rec->id;
94   - $DB->update_record('badge_backpack', $obj);
95   - } else {
96   - $DB->insert_record('badge_backpack', $obj);
  80 + } else if ($data = $form->get_data()) {
  81 + $groups = array_filter($data->group);
  82 +
  83 + // Remove all unselected collections if there are any.
  84 + $sqlparams = array('backpack' => $backpack->id);
  85 + $select = 'backpackid = :backpack ';
  86 + if (!empty($groups)) {
  87 + list($grouptest, $groupparams) = $DB->get_in_or_equal($groups, SQL_PARAMS_NAMED, 'col', false);
  88 + $select .= ' AND collectionid ' . $grouptest;
  89 + $sqlparams = array_merge($sqlparams, $groupparams);
  90 + }
  91 + $DB->delete_records_select('badge_external', $select, $sqlparams);
  92 +
  93 + // Insert selected collections if they are not in database yet.
  94 + foreach ($groups as $group) {
  95 + $obj = new stdClass();
  96 + $obj->backpackid = $data->backpackid;
  97 + $obj->collectionid = (int) $group;
  98 + if (!$DB->record_exists('badge_external', array('backpackid' => $obj->backpackid, 'collectionid' => $obj->collectionid))) {
  99 + $DB->insert_record('badge_external', $obj);
  100 + }
97 101 }
98 102 redirect(new moodle_url('/badges/mybadges.php'));
99 103 }
100   -
101   - echo $OUTPUT->header();
102   - $groupform->display();
103   - echo $OUTPUT->footer();
104   - die();
105 104 } else {
  105 + // If backpack is not connected, need to connect first.
106 106 $form = new edit_backpack_form();
107 107
108 108 if ($form->is_cancelled()) {
109 109 redirect(new moodle_url('/badges/mybadges.php'));
110   - } else if (($data = $form->get_data()) || !empty($SESSION->badgesparams)) {
111   - if (empty($SESSION->badgesparams)) {
112   - $bp = new OpenBadgesBackpackHandler($data);
113   - $request = $bp->get_groups();
114   -
115   - // If there is an error, start over.
116   - if (is_array($request) && $request['status'] == 'missing') {
117   - unset($SESSION->badgesparams);
118   - redirect(new moodle_url('/badges/mybackpack.php'), $request['message'], 10);
119   - } else if (empty($request->groups)) {
120   - unset($SESSION->badgesparams);
121   - redirect(new moodle_url('/badges/mybadges.php'), get_string('error:nogroups', 'badges'), 20);
122   - }
123   -
124   - $params = array(
125   - 'data' => $data,
126   - 'backpackuid' => $request->userId,
127   - 'groups' => $request->groups
128   - );
129   - $SESSION->badgesparams = $params;
130   - }
131   - $groupform = new edit_backpack_group_form(new moodle_url('/badges/mybackpack.php', array('addgroups' => true)), $SESSION->badgesparams);
  110 + } else if ($data = $form->get_data()) {
  111 + $bp = new OpenBadgesBackpackHandler($data);
132 112
133   - if ($groupform->is_cancelled()) {
134   - unset($SESSION->badgesparams);
135   - redirect(new moodle_url('/badges/mybadges.php'));
136   - } else if ($groupdata = $groupform->get_data()) {
137   - $obj = new stdClass();
138   - $obj->userid = $groupdata->userid;
139   - $obj->email = $groupdata->email;
140   - $obj->backpackurl = $groupdata->backpackurl;
141   - $obj->backpackuid = $groupdata->backpackuid;
142   - $obj->backpackgid = $groupdata->backpackgid;
143   - $obj->autosync = 0;
144   - $obj->password = '';
145   - if ($rec = $DB->get_record('badge_backpack', array('userid' => $groupdata->userid))) {
146   - $obj->id = $rec->id;
147   - $DB->update_record('badge_backpack', $obj);
148   - } else {
149   - $DB->insert_record('badge_backpack', $obj);
150   - }
151   - unset($SESSION->badgesparams);
152   - redirect(new moodle_url('/badges/mybadges.php'));
153   - }
  113 + $obj = new stdClass();
  114 + $obj->userid = $data->userid;
  115 + $obj->email = $data->email;
  116 + $obj->backpackurl = $data->backpackurl;
  117 + $obj->backpackuid = $bp->curl_request('user')->userId;
  118 + $obj->autosync = 0;
  119 + $obj->password = '';
  120 + $DB->insert_record('badge_backpack', $obj);
154 121
155   - echo $OUTPUT->header();
156   - $groupform->display();
157   - echo $OUTPUT->footer();
158   - die();
  122 + redirect(new moodle_url('/badges/mybackpack.php'));
159 123 }
160   -
161   - echo $OUTPUT->header();
162   - $form->display();
163   - echo $OUTPUT->footer();
164 124 }
  125 +
  126 +echo $OUTPUT->header();
  127 +$form->display();
  128 +echo $OUTPUT->footer();
65 badges/preferences.php
... ... @@ -0,0 +1,65 @@
  1 +<?php
  2 +// This file is part of Moodle - http://moodle.org/
  3 +//
  4 +// Moodle is free software: you can redistribute it and/or modify
  5 +// it under the terms of the GNU General Public License as published by
  6 +// the Free Software Foundation, either version 3 of the License, or
  7 +// (at your option) any later version.
  8 +//
  9 +// Moodle is distributed in the hope that it will be useful,
  10 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 +// GNU General Public License for more details.
  13 +//
  14 +// You should have received a copy of the GNU General Public License
  15 +// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 +/**
  18 + * Badges user preferences page.
  19 + *
  20 + * @package core
  21 + * @subpackage badges
  22 + * @copyright 2013 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  23 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24 + * @author Yuliya Bozhko <yuliya.bozhko@totaralms.com>
  25 + */
  26 +
  27 +require_once(dirname(dirname(__FILE__)) . '/config.php');
  28 +require_once('preferences_form.php');
  29 +
  30 +$url = new moodle_url('/badges/preferences.php');
  31 +
  32 +require_login();
  33 +$PAGE->set_context(context_system::instance());
  34 +$PAGE->set_url($url);
  35 +$PAGE->set_pagelayout('standard');
  36 +
  37 +if (empty($CFG->enablebadges)) {
  38 + print_error('badgesdisabled', 'badges');
  39 +}
  40 +
  41 +$mform = new badges_preferences_form();
  42 +$mform->set_data(array('badgeprivacysetting' => get_user_preferences('badgeprivacysetting')));
  43 +
  44 +if (!$mform->is_cancelled() && $data = $mform->get_data()) {
  45 + $setting = $data->badgeprivacysetting;
  46 + set_user_preference('badgeprivacysetting', $setting);
  47 +}
  48 +
  49 +if ($mform->is_cancelled()) {
  50 + redirect($CFG->wwwroot . '/badges/mybadges.php');
  51 +}
  52 +
  53 +$strpreferences = get_string('preferences');
  54 +$strbadges = get_string('badges');
  55 +
  56 +$title = "$strbadges: $strpreferences";
  57 +$PAGE->set_title($title);
  58 +$PAGE->set_heading($title);
  59 +
  60 +echo $OUTPUT->header();
  61 +echo $OUTPUT->heading("$strbadges: $strpreferences", 2);
  62 +
  63 +$mform->display();
  64 +
  65 +echo $OUTPUT->footer();
47 badges/preferences_form.php
... ... @@ -0,0 +1,47 @@
  1 +<?php
  2 +// This file is part of Moodle - http://moodle.org/
  3 +//
  4 +// Moodle is free software: you can redistribute it and/or modify
  5 +// it under the terms of the GNU General Public License as published by
  6 +// the Free Software Foundation, either version 3 of the License, or
  7 +// (at your option) any later version.
  8 +//
  9 +// Moodle is distributed in the hope that it will be useful,
  10 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12 +// GNU General Public License for more details.
  13 +//
  14 +// You should have received a copy of the GNU General Public License
  15 +// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  16 +
  17 +/**
  18 + * Form class for editing badges preferences.
  19 + *
  20 + * @package core
  21 + * @subpackage badges
  22 + * @copyright 2013 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/}
  23 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24 + * @author Yuliya Bozhko <yuliya.bozhko@totaralms.com>
  25 + */
  26 +
  27 +if (!defined('MOODLE_INTERNAL')) {
  28 + die('Direct access to this script is forbidden.');
  29 +}
  30 +
  31 +require_once($CFG->libdir . '/formslib.php');
  32 +
  33 +class badges_preferences_form extends moodleform {
  34 + public function definition() {
  35 + global $USER, $CFG;
  36 +
  37 + $mform =& $this->_form;
  38 +
  39 + $mform->addElement('header', 'badgeprivacy', get_string('badgeprivacysetting', 'badges'));
  40 + $mform->addElement('advcheckbox', 'badgeprivacysetting', '', get_string('badgeprivacysetting_str', 'badges'));
  41 + $mform->setType('badgeprivacysetting', PARAM_INT);
  42 + $mform->setDefault('badgeprivacysetting', 1);
  43 + $mform->addHelpButton('badgeprivacy', 'badgeprivacysetting', 'badges');
  44 +
  45 + $this->add_action_buttons();
  46 + }
  47 +}
209 badges/renderer.php
@@ -60,7 +60,9 @@ public function print_badges_list($badges, $userid, $profile = false, $external
60 60 $download = $status = $push = '';
61 61 if (($userid == $USER->id) && !$profile) {
62 62 $url = new moodle_url('mybadges.php', array('download' => $badge->id, 'hash' => $badge->uniquehash, 'sesskey' => sesskey()));
63   - if (!empty($CFG->badges_allowexternalbackpack) && (empty($badge->dateexpire) || $badge->dateexpire > time())) {
  63 + $notexpiredbadge = (empty($badge->dateexpire) || $badge->dateexpire > time());
  64 + $backpackexists = badges_user_has_backpack($USER->id);
  65 + if (!empty($CFG->badges_allowexternalbackpack) && $notexpiredbadge && $backpackexists) {
64 66 $assertion = new moodle_url('/badges/assertion.php', array('b' => $badge->uniquehash));
65 67 $action = new component_action('click', 'addtobackpack', array('assertion' => $assertion->out(false)));
66 68 $push = $this->output->action_icon(new moodle_url('#'), new pix_icon('t/backpack', get_string('addtobackpack', 'badges')), $action);
@@ -279,100 +281,94 @@ protected function render_issued_badge(issued_badge $ibadge) {
279 281 $today_date = date('Y-m-d');
280 282 $today = strtotime($today_date);
281 283
282   - if ($ibadge->visible
283   - || ($USER->id == $ibadge->recipient)
284   - || has_capability('moodle/badges:viewawarded', context_system::instance())) {
285   - $table = new html_table();
  284 + $table = new html_table();
286 285
287   - $imagetable = new html_table();
288   - $imagetable->attributes = array('class' => 'clearfix badgeissuedimage');
289   - $imagetable->data[] = array(html_writer::empty_tag('img', array('src' => $issued['badge']['image'])));
290   - if ($USER->id == $ibadge->recipient && !empty($CFG->enablebadges)) {
291   - $imagetable->data[] = array($this->output->single_button(
292   - new moodle_url('/badges/badge.php', array('hash' => $ibadge->hash, 'bake' => true)),
293   - get_string('download'),
294   - 'POST'));
295   - $expiration = isset($issued['expires']) ? strtotime($issued['expires']) : $today + 1;
296   - if (!empty($CFG->badges_allowexternalbackpack) && ($expiration > $today)) {
297   - $assertion = new moodle_url('/badges/assertion.php', array('b' => $ibadge->hash));
298   - $attributes = array(
299   - 'type' => 'button',
300   - 'value' => get_string('addtobackpack', 'badges'),
301   - 'onclick' => 'OpenBadges.issue(["' . $assertion->out(false) . '"], function(errors, successes) { })');
302   - $tobackpack = html_writer::tag('input', '', $attributes);
303   - $imagetable->data[] = array($tobackpack);
304   - }
305   - }
306   - $datatable = new html_table();
307   - $datatable->attributes = array('class' => 'badgeissuedinfo');
308   - $datatable->colclasses = array('bfield', 'bvalue');
309   - $datatable->data[] = array($this->output->heading(get_string('issuerdetails', 'badges'), 3), '');
310   - $datatable->data[] = array(get_string('issuername', 'badges'), $badge->issuername);
311   - if (isset($badge->issuercontact) && !empty($badge->issuercontact)) {
312   - $datatable->data[] = array(get_string('contact', 'badges'),
313   - html_writer::tag('a', $badge->issuercontact, array('href' => 'mailto:' . $badge->issuercontact)));
  286 + $imagetable = new html_table();
  287 + $imagetable->attributes = array('class' => 'clearfix badgeissuedimage');
  288 + $imagetable->data[] = array(html_writer::empty_tag('img', array('src' => $issued['badge']['image'])));
  289 + if ($USER->id == $ibadge->recipient && !empty($CFG->enablebadges)) {
  290 + $imagetable->data[] = array($this->output->single_button(
  291 + new moodle_url('/badges/badge.php', array('hash' => $ibadge->hash, 'bake' => true)),
  292 + get_string('download'),
  293 + 'POST'));
  294 + $expiration = isset($issued['expires']) ? strtotime($issued['expires']) : $today + 1;
  295 + if (!empty($CFG->badges_allowexternalbackpack) && ($expiration > $today) && badges_user_has_backpack($USER->id)) {
  296 + $assertion = new moodle_url('/badges/assertion.php', array('b' => $ibadge->hash));
  297 + $attributes = array(
  298 + 'type' => 'button',
  299 + 'value' => get_string('addtobackpack', 'badges'),
  300 + 'onclick' => 'OpenBadges.issue(["' . $assertion->out(false) . '"], function(errors, successes) { })');
  301 + $tobackpack = html_writer::tag('input', '', $attributes);
  302 + $imagetable->data[] = array($tobackpack);
314 303 }
315   - $datatable->data[] = array($this->output->heading(get_string('badgedetails', 'badges'), 3), '');
316   - $datatable->data[] = array(get_string('name'), $badge->name);
317   - $datatable->data[] = array(get_string('description', 'badges'), $badge->description);
  304 + }
  305 + $datatable = new html_table();
  306 + $datatable->attributes = array('class' => 'badgeissuedinfo');
  307 + $datatable->colclasses = array('bfield', 'bvalue');
  308 + $datatable->data[] = array($this->output->heading(get_string('issuerdetails', 'badges'), 3), '');
  309 + $datatable->data[] = array(get_string('issuername', 'badges'), $badge->issuername);
  310 + if (isset($badge->issuercontact) && !empty($badge->issuercontact)) {
  311 + $datatable->data[] = array(get_string('contact', 'badges'),
  312 + html_writer::tag('a', $badge->issuercontact, array('href' => 'mailto:' . $badge->issuercontact)));
  313 + }
  314 + $datatable->data[] = array($this->output->heading(get_string('badgedetails', 'badges'), 3), '');
  315 + $datatable->data[] = array(get_string('name'), $badge->name);
  316 + $datatable->data[] = array(get_string('description', 'badges'), $badge->description);
318 317
319   - if ($badge->type == BADGE_TYPE_COURSE && isset($badge->courseid)) {
320   - $coursename = $DB->get_field('course', 'fullname', array('id' => $badge->courseid));
321   - $datatable->data[] = array(get_string('course'), $coursename);
322   - }
  318 + if ($badge->type == BADGE_TYPE_COURSE && isset($badge->courseid)) {
  319 + $coursename = $DB->get_field('course', 'fullname', array('id' => $badge->courseid));
  320 + $datatable->data[] = array(get_string('course'), $coursename);
  321 + }
323 322
324   - $datatable->data[] = array(get_string('bcriteria', 'badges'), self::print_badge_criteria($badge));
325   - $datatable->data[] = array($this->output->heading(get_string('issuancedetails', 'badges'), 3), '');
326   - $datatable->data[] = array(get_string('dateawarded', 'badges'), $issued['issued_on']);
327   - if (isset($issued['expires'])) {
328   - $expiration = strtotime($issued['expires']);
329   - if ($expiration < $today) {
330   - $cell = new html_table_cell($issued['expires'] . get_string('warnexpired', 'badges'));
331   - $cell->attributes = array('class' => 'notifyproblem warning');
332   - $datatable->data[] = array(get_string('expirydate', 'badges'), $cell);
333   -
334   - $image = html_writer::start_tag('div', array('class' => 'badge'));
335   - $image .= html_writer::empty_tag('img', array('src' => $issued['badge']['image']));
336   - $image .= $this->output->pix_icon('i/expired',
337   - get_string('expireddate', 'badges', $issued['expires']),
338   - 'moodle',
339   - array('class' => 'expireimage'));
340   - $image .= html_writer::end_tag('div');
341   - $imagetable->data[0] = array($image);
342   - } else {
343   - $datatable->data[] = array(get_string('expirydate', 'badges'), $issued['expires']);
344   - }
  323 + $datatable->data[] = array(get_string('bcriteria', 'badges'), self::print_badge_criteria($badge));
  324 + $datatable->data[] = array($this->output->heading(get_string('issuancedetails', 'badges'), 3), '');
  325 + $datatable->data[] = array(get_string('dateawarded', 'badges'), $issued['issued_on']);
  326 + if (isset($issued['expires'])) {
  327 + $expiration = strtotime($issued['expires']);
  328 + if ($expiration < $today) {
  329 + $cell = new html_table_cell($issued['expires'] . get_string('warnexpired', 'badges'));
  330 + $cell->attributes = array('class' => 'notifyproblem warning');
  331 + $datatable->data[] = array(get_string('expirydate', 'badges'), $cell);
  332 +
  333 + $image = html_writer::start_tag('div', array('class' => 'badge'));
  334 + $image .= html_writer::empty_tag('img', array('src' => $issued['badge']['image']));
  335 + $image .= $this->output->pix_icon('i/expired',
  336 + get_string('expireddate', 'badges', $issued['expires']),
  337 + 'moodle',
  338 + array('class' => 'expireimage'));
  339 + $image .= html_writer::end_tag('div');
  340 + $imagetable->data[0] = array($image);
  341 + } else {
  342 + $datatable->data[] = array(get_string('expirydate', 'badges'), $issued['expires']);
345 343 }
  344 + }
346 345
347   - // Print evidence.
348   - $agg = $badge->get_aggregation_methods();
349   - $evidence = $badge->get_criteria_completions($ibadge->recipient);
350   - $eids = array_map(create_function('$o', 'return $o->critid;'), $evidence);
351   - unset($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]);
352   -
353   - $items = array();
354   - foreach ($badge->criteria as $type => $c) {
355   - if (in_array($c->id, $eids)) {
356   - if (count($c->params) == 1) {
357   - $items[] = get_string('criteria_descr_single_' . $type , 'badges') . $c->get_details();
358   - } else {
359   - $items[] = get_string('criteria_descr_' . $type , 'badges',
360   - strtoupper($agg[$badge->get_aggregation_method($type)])) . $c->get_details();
361   - }
  346 + // Print evidence.
  347 + $agg = $badge->get_aggregation_methods();
  348 + $evidence = $badge->get_criteria_completions($ibadge->recipient);
  349 + $eids = array_map(create_function('$o', 'return $o->critid;'), $evidence);
  350 + unset($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]);
  351 +
  352 + $items = array();
  353 + foreach ($badge->criteria as $type => $c) {
  354 + if (in_array($c->id, $eids)) {
  355 + if (count($c->params) == 1) {
  356 + $items[] = get_string('criteria_descr_single_' . $type , 'badges') . $c->get_details();
  357 + } else {
  358 + $items[] = get_string('criteria_descr_' . $type , 'badges',
  359 + strtoupper($agg[$badge->get_aggregation_method($type)])) . $c->get_details();
362 360 }
363 361 }
  362 + }
364 363
365   - $datatable->data[] = array(get_string('evidence', 'badges'),
366   - get_string('completioninfo', 'badges') .
367   - html_writer::alist($items, array(), 'ul'));
368   - $table->attributes = array('class' => 'generalbox boxaligncenter issuedbadgebox');
369   - $table->data[] = array(html_writer::table($imagetable), html_writer::table($datatable));
370   - $htmlbadge = html_writer::table($table);
  364 + $datatable->data[] = array(get_string('evidence', 'badges'),
  365 + get_string('completioninfo', 'badges') .
  366 + html_writer::alist($items, array(), 'ul'));
  367 + $table->attributes = array('class' => 'generalbox boxaligncenter issuedbadgebox');
  368 + $table->data[] = array(html_writer::table($imagetable), html_writer::table($datatable));
  369 + $htmlbadge = html_writer::table($table);
371 370
372   - return $htmlbadge;
373   - } else {
374   - return get_string('hiddenbadge', 'badges');
375   - }
  371 + return $htmlbadge;
376 372 }
377 373
378 374 // Outputs external badge.
@@ -443,9 +439,17 @@ protected function render_external_badge(external_badge $ibadge) {
443 439 // Outputs table of user badges.
444 440 protected function render_badge_user_collection(badge_user_collection $badges) {
445 441 global $CFG, $USER, $SITE;
  442 + $backpack = $badges->backpack;
  443 + $mybackpack = new moodle_url('/badges/mybackpack.php');
  444 +
446 445 $paging = new paging_bar($badges->totalcount, $badges->page, $badges->perpage, $this->page->url, 'page');
447 446 $htmlpagingbar = $this->render($paging);
448 447
  448 + // Set backpack connection string.
  449 + $backpackconnect = '';
  450 + if (!empty($CFG->badges_allowexternalbackpack) && is_null($backpack)) {
  451 + $backpackconnect = $this->output->box(get_string('localconnectto', 'badges', $mybackpack->out()), 'noticebox');
  452 + }
449 453 // Search box.
450 454 $searchform = $this->output->box($this->helper_search_form($badges->search), 'boxwidthwide boxaligncenter');
451 455
@@ -465,39 +469,32 @@ protected function render_badge_user_collection(badge_user_collection $badges) {
465 469 $downloadbutton = html_writer::table($table);
466 470
467 471 $htmllist = $this->print_badges_list($badges->badges, $USER->id);
468   - $localhtml .= $downloadbutton . $searchform . $htmlpagingbar . $htmllist . $htmlpagingbar;
  472 + $localhtml .= $backpackconnect . $downloadbutton . $searchform . $htmlpagingbar . $htmllist . $htmlpagingbar;
469 473 } else {
470 474 $localhtml .= $searchform . $this->output->notification(get_string('nobadges', 'badges'));
471 475 }
472 476 $localhtml .= html_writer::end_tag('fieldset');
473 477
474 478 // External badges.
475   - $backpack = $badges->backpack;
476 479 $externalhtml = "";
477 480 if (!empty($CFG->badges_allowexternalbackpack)) {
478 481 $externalhtml .= html_writer::start_tag('fieldset', array('class' => 'generalbox'));
479 482 $externalhtml .= html_writer::tag('legend', $this->output->heading_with_help(get_string('externalbadges', 'badges'), 'externalbadges', 'badges'));
480 483 if (!is_null($backpack)) {
481   - if ($backpack->totalbadges > 0) {
482   - $externalhtml .= get_string('backpackbadges', 'badges', $backpack);
  484 + if ($backpack->totalcollections == 0) {
  485 + $externalhtml .= get_string('nobackpackcollections', 'badges', $backpack);
483 486 } else {
484   - $externalhtml .= get_string('nobackpackbadges', 'badges', $backpack);
  487 + if ($backpack->totalbadges == 0) {
  488 + $externalhtml .= get_string('nobackpackbadges', 'badges', $backpack);
  489 + } else {
  490 + $externalhtml .= get_string('backpackbadges', 'badges', $backpack);
  491 + $externalhtml .= '<br/><br/>' . $this->print_badges_list($backpack->badges, $USER->id, true, true);
  492 + }
485 493 }
486   - $label = get_string('editsettings', 'badges');
487   - $externalhtml .= $this->output->single_button(
488   - new moodle_url('mybackpack.php', array('clear' => true)),
489   - get_string('clearsettings', 'badges'),
490   - 'POST',
491   - array('class' => 'backpackform'));
492 494 } else {
493   - $externalhtml .= get_string('nobackpack', 'badges');
494   - $label = get_string('setup', 'badges');
  495 + $externalhtml .= get_string('externalconnectto', 'badges', $mybackpack->out());
495 496 }
496   - $externalhtml .= $this->output->single_button('mybackpack.php', $label, 'POST', array('class' => 'backpackform'));
497 497
498   - if (isset($backpack->totalbadges) && $backpack->totalbadges !== 0) {
499   - $externalhtml .= '<br/><br/>' . $this->print_badges_list($backpack->badges, $USER->id, true, true);
500   - }
501 498 $externalhtml .= html_writer::end_tag('fieldset');
502 499 }
503 500
@@ -994,7 +991,7 @@ class badge_management extends badge_collection implements renderable {
994 991 */
995 992 class badge_user_collection extends badge_collection implements renderable {
996 993 /** @var array backpack settings */
997   - public $backpack;
  994 + public $backpack = null;
998 995
999 996 /** @var string search */
1000 997 public $search = '';
@@ -1006,7 +1003,11 @@ class badge_user_collection extends badge_collection implements renderable {
1006 1003 * @param int $userid Badges owner
1007 1004 */
1008 1005 public function __construct($badges, $userid) {
  1006 + global $CFG;
1009 1007 parent::__construct($badges);
1010   - $this->backpack = get_backpack_settings($userid);
  1008 +
  1009 + if (!empty($CFG->badges_allowexternalbackpack)) {
  1010 + $this->backpack = get_backpack_settings($userid);
  1011 + }
1011 1012 }
1012 1013 }
38 lang/en/badges.php
@@ -79,14 +79,29 @@
79 79 ##What if I can\'t make my whole site publically accessible?
80 80
81 81 The only URL required for verification is [your-site-url]/badges/assertion.php so if you are able to modify your firewall to allow external access to that file, badge verification will still work.';
82   -$string['backpackbadges'] = 'You have {$a->totalbadges} badge(s) displayed from your backpack at <a href="{$a->backpackurl}">{$a->backpackurl}</a>.<br/>';
  82 +$string['backpackbadges'] = 'You have {$a->totalbadges} badge(s) displayed from {$a->totalcollections} collection(s). <a href="mybackpack.php">Change backpack settings</a>.';
  83 +$string['backpackconnection'] = 'Backpack connection';
  84 +$string['backpackconnection_help'] = 'This page allows you to set up connection to an external backpack provider. Connecting to a backpack lets you display external badges within this site and push badges earned here to your backpack.
  85 +
  86 +Currently, only <a href="http://backpack.openbadges.org">Mozilla OpenBadges Backpack</a> is supported. You need to sign up for a backpack service before trying to set up backpack connection on this page.';
83 87 $string['backpackdetails'] = 'Backpack settings';
  88 +$string['backpackemail'] = 'Email address';
  89 +$string['backpackemail_help'] = 'Email address associated with your backpack';
  90 +$string['backpackimport'] = 'Badge import settings';
  91 +$string['backpackimport_help'] = 'After backpack connection is successfully established, badges from your backpack can be displayed on your "My Badges" page and your profile page.
  92 +
  93 +In this area, you can select collections of badges from your backpack that you would like to display in your profile.';
84 94 $string['badgedetails'] = 'Badge details';
85 95 $string['badgeimage'] = 'Image';
86 96 $string['badgeimage_help'] = 'This is an image that will be used when this badge is issued.
87 97
88 98 To add a new image, browse and select an image (in JPG or PNG format) then click "Save changes". The image will be cropped to a square and resized to match badge image requirements. ';
89 99
  100 +$string['badgeprivacysetting'] = 'Badge privacy settings';
  101 +$string['badgeprivacysetting_help'] = 'Badges you earn can be displayed on your account profile page. This setting allows you to automatically set visibility of the newly earned badges.
  102 +
  103 +You can still control individual badge privacy settings on your <a href="mybadges.php">My badges</a> page.';
  104 +$string['badgeprivacysetting_str'] = 'Automatically show badges I earn on my profile page';
90 105 $string['badgesalt'] = 'Salt for hashing the recepient\'s email address';
91 106 $string['badgesalt_desc'] = 'Using a hash allows backpack services to confirm the badge earner without having to expose their email address. This setting should only use numbers and letters.';
92 107 $string['badgesdisabled'] = 'Badges are not enabled on this site.';
@@ -111,6 +126,8 @@
111 126 $string['completioninfo'] = 'This badge was issued for completing: ';
112 127 $string['configenablebadges'] = 'When enabled, this feature lets you create badges and award them to site users.';
113 128 $string['configuremessage'] = 'Badge message';
  129 +$string['connect'] = 'Connect';
  130 +$string['connected'] = 'Connected';
114 131 $string['contact'] = 'Contact';
115 132 $string['contact_help'] = 'An email address associated with the badge issuer.';
116 133 $string['copyof'] = 'Copy of {$a}';
@@ -177,6 +194,7 @@
177 194 $string['delcritconfirm'] = 'Are you sure that you want to delete this criterion?';
178 195 $string['delparamconfirm'] = 'Are you sure that you want to delete this parameter?';
179 196 $string['description'] = 'Description';
  197 +$string['disconnect'] = 'Disconnect';
180 198 $string['donotaward'] = 'Currently, this badge is not active, so it cannot be awarded to users. If you would like to award this badge, please set its status to active.';
181 199 $string['editsettings'] = 'Edit settings';
182 200 $string['enablebadges'] = 'Enable badges';
@@ -192,8 +210,7 @@
192 210 $string['error:noactivities'] = 'There are no activities with completion criteria enabled in this course.';
193 211 $string['error:nocourses'] = 'Course completion is not enabled for any of the courses in this site, so none can be displayed. You can enable course completion in the course settings.';
194 212 $string['error:nogroups'] = '<p>There are no public collections of badges available in your backpack. </p>
195   -<p>To display external badges, you will need to visit your backpack and make at least one collection of badges public. </p>
196   -<p>If you already have backpack service connection established and your previously selected badge collection has been removed, clear these settings and try again.</p>';
  213 +<p>Only public collections are shown, <a href="http://backpack.openbadges.org">visit your backpack</a> to create some public collections.</p>';
197 214 $string['error:nopermissiontoview'] = 'You have no permissions to view badge recipients';
198 215 $string['error:nosuchbadge'] = 'Badge with id {$a} does not exist.';
199 216 $string['error:nosuchcourse'] = 'Warning: This course is no longer available.';
@@ -215,13 +232,10 @@
215 232 $string['expireperiods'] = 'This badge expires {$a} second(s) after being issued.';
216 233 $string['expirydate'] = 'Expiry date';
217 234 $string['expirydate_help'] = 'Optionally, badges can expire on a specific date, or the date can be calculated based on the date when the badge was issued to a user. ';
  235 +$string['externalconnectto'] = 'To display external badges you need to <a href="{$a}">connect to a backpack</a>.';
218 236 $string['externalbadges'] = 'My badges from other web sites';
219 237 $string['externalbadgesp'] = 'Badges from other web sites:';
220   -$string['externalbadges_help'] = 'This area allows to set up connection to an external backpack provider.
221   -
222   -Currently, only <a href="http://backpack.openbadges.org">Mozilla OpenBadges Backpack</a> is supported. You need to sign up for a backpack service before trying to set up backpack connection on this page.
223   -
224   -After such connection is successfully established, a number of badges from your backpack will be displayed on this page. A list of badges from a backpack along with their details and description can be found on a user profile page.';
  238 +$string['externalbadges_help'] = 'This area displays badges from your external backpack.';
225 239 $string['fixed'] = 'Fixed date';
226 240 $string['hidden'] = 'Hidden';
227 241 $string['hiddenbadge'] = 'Unfortunately, badge owner has not made this information available.';
@@ -231,6 +245,7 @@
231 245 $string['issuername'] = 'Issuer name';
232 246 $string['issuername_help'] = 'Name of the issuing agent or authority.';
233 247 $string['issuerurl'] = 'Issuer URL';
  248 +$string['localconnectto'] = 'To share these badges outside this web site you need to <a href="{$a}">connect to a backpack</a>.';
234 249 $string['localbadges'] = 'My badges from {$a} web site';
235 250 $string['localbadgesh'] = 'My badges from this web site';
236 251 $string['localbadgesh_help'] = 'All badges earned within this web site by completing courses, course activities, and other requirements.
@@ -257,13 +272,15 @@
257 272 $string['newimage'] = 'New image';
258 273 $string['noawards'] = 'This badge has not been earned yet.';
259 274 $string['nobackpack'] = 'There is no backpack service connected to this account.<br/>';
260   -$string['nobackpackbadges'] = 'There are no badges displayed from your backpack at <a href="{$a->backpackurl}">{$a->backpackurl}</a>.<br/>';
  275 +$string['nobackpackbadges'] = 'There are no badges in the collections you have selected. <a href="mybackpack.php">Add more collections</a>.';
  276 +$string['nobackpackcollections'] = 'No badge collections have been selected. <a href="mybackpack.php">Add collections</a>.';
261 277 $string['nobadges'] = 'There are no badges available.';
262 278 $string['nocriteria'] = 'Criteria for this badge have not been set up yet.';
263 279 $string['noexpiry'] = 'This badge does not have an expiry date.';
264 280 $string['noparamstoadd'] = 'There are no additional parameters available to add to this badge requirement.';
265 281 $string['notacceptedrole'] = 'Your current role assignment is not among the roles that can manually issue this badge.<br/>
266 282 If you would like to see users who have already earned this badge, you can visit {$a} page. ';
  283 +$string['notconnected'] = 'Not connected';
267 284 $string['nothingtoadd'] = 'There are no available criteria to add.';
268 285 $string['notification'] = 'Notify badge creator';
269 286 $string['notification_help'] = 'This setting manages notifications sent to a badge creator to let them know that the badge has been issued.
@@ -295,7 +312,8 @@
295 312 <p>Would you like to proceed?</p>';
296 313 $string['save'] = 'Save';
297 314 $string['searchname'] = 'Search by name';
298   -$string['selectgroup'] = 'Select badge collection';
  315 +$string['selectgroup_end'] = 'Only public collections are shown, <a href="http://backpack.openbadges.org">visit your backpack</a> to create more public collections.';
  316 +$string['selectgroup_start'] = 'Select collections from your backpack to display on this site:';
299 317 $string['selecting'] = 'With selected badges...';
300 318 $string['setup'] = 'Set up connection';
301 319 $string['sitebadges'] = 'Site badges';
45 lib/badgeslib.php
@@ -387,8 +387,9 @@ public function issue($userid, $nobake = false) {
387 387 $issued->dateexpire = null;
388 388 }
389 389
390   - // Issued badges always being issued as private.
391   - $issued->visible = 0;
  390 + // Take into account user badges privacy settings.
  391 + // If none set, badges default visibility is set to public.
  392 + $issued->visible = get_user_preferences('badgeprivacysetting', 1, $userid);
392 393
393 394 $result = $DB->insert_record('badge_issued', $issued, true);
394 395
@@ -1150,7 +1151,7 @@ function badges_bake($hash, $badgeid, $userid = 0, $pathhash = false) {
1150 1151 }
1151 1152
1152 1153 /**
1153   - * Returns backpack service settings.
  1154 + * Returns external backpack settings and badges from this backpack.
1154 1155 *
1155 1156 * @param int $userid Backpack user ID.
1156 1157 * @return null|object Returns null is there is no backpack or object with backpack settings.
@@ -1159,14 +1160,30 @@ function get_backpack_settings($userid) {
1159 1160 global $DB;
1160 1161 require_once(dirname(dirname(__FILE__)) . '/badges/lib/backpacklib.php');
1161 1162
1162   - $record = $DB->get_record('badge_backpack', array('userid' => $userid), '*', IGNORE_MISSING);
  1163 + $record = $DB->get_record('badge_backpack', array('userid' => $userid));
1163 1164 if ($record) {
1164 1165 $backpack = new OpenBadgesBackpackHandler($record);
1165 1166 $out = new stdClass();
1166 1167 $out->backpackurl = $backpack->get_url();
1167   - $badges = $backpack->get_badges();
1168   - $out->badges = isset($badges->badges) ? $badges->badges : array();
1169   - $out->totalbadges = count($out->badges);
  1168 +
  1169 + if ($collections = $DB->get_records('badge_external', array('backpackid' => $record->id))) {
  1170 + $out->totalcollections = count($collections);
  1171 + $out->totalbadges = 0;
  1172 + $out->badges = array();
  1173 + foreach ($collections as $collection) {
  1174 + $badges = $backpack->get_badges($collection->collectionid);
  1175 + if (isset($badges->badges)) {
  1176 + $out->badges = array_merge($out->badges, $badges->badges);
  1177 + $out->totalbadges += count($out->badges);
  1178 + } else {
  1179 + $out->badges = array_merge($out->badges, array());
  1180 + }
  1181 + }
  1182 + } else {
  1183 + $out->totalbadges = 0;
  1184 + $out->totalcollections = 0;
  1185 + }
  1186 +
1170 1187 return $out;
1171 1188 }
1172 1189
@@ -1258,9 +1275,8 @@ function badges_check_backpack_accessibility() {
1258 1275 $options = array(
1259 1276 'FRESH_CONNECT' => true,
1260 1277 'RETURNTRANSFER' => true,
1261   - 'FORBID_REUSE' => true,
1262 1278 'HEADER' => 0,
1263   - 'CONNECTTIMEOUT_MS' => 1000,
  1279 + 'CONNECTTIMEOUT_MS' => 2000,
1264 1280 );
1265 1281 $location = 'http://backpack.openbadges.org/baker';
1266 1282 $out = $curl->get($location, array('assertion' => $fakeassertion->out(false)), $options);
@@ -1278,3 +1294,14 @@ function badges_check_backpack_accessibility() {
1278 1294
1279 1295 return false;
1280 1296 }
  1297 +
  1298 +/**
  1299 + * Checks if user has external backpack connected.
  1300 + *
  1301 + * @param int $userid ID of a user.
  1302 + * @return bool True|False whether backpack connection exists.
  1303 + */
  1304 +function badges_user_has_backpack($userid) {
  1305 + global $DB;
  1306 + return $DB->record_exists('badge_backpack', array('userid' => $userid));
  1307 +}
14 lib/db/install.xml
... ... @@ -1,5 +1,5 @@
1 1 <?xml version="1.0" encoding="UTF-8" ?>
2   -<XMLDB PATH="lib/db" VERSION="20130405" COMMENT="XMLDB file for core Moodle tables"
  2 +<XMLDB PATH="lib/db" VERSION="20130412" COMMENT="XMLDB file for core Moodle tables"
3 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 4 xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
5 5 >
@@ -3052,7 +3052,6 @@
3052 3052 <FIELD NAME="email" TYPE="char" LENGTH="100" NOTNULL="true" SEQUENCE="false"/>
3053 3053 <FIELD NAME="backpackurl" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
3054 3054 <FIELD NAME="backpackuid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
3055   - <FIELD NAME="backpackgid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
3056 3055 <FIELD NAME="autosync" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
3057 3056 <FIELD NAME="password" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false"/>
3058 3057 </FIELDS>
@@ -3061,5 +3060,16 @@
3061 3060 <KEY NAME="fk_userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id"/>
3062 3061 </KEYS>
3063 3062 </TABLE>
  3063 + <TABLE NAME="badge_external" COMMENT="Setting for external badges display">
  3064 + <FIELDS>
  3065 + <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
  3066 + <FIELD NAME="backpackid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of a backpack"/>
  3067 + <FIELD NAME="collectionid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Badge collection id in the backpack"/>
  3068 + </FIELDS>
  3069 + <KEYS>
  3070 + <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
  3071 + <KEY NAME="fk_backpackid" TYPE="foreign" FIELDS="backpackid" REFTABLE="badge_backpack" REFFIELDS="id"/>
  3072 + </KEYS>
  3073 + </TABLE>
3064 3074 </TABLES>
3065 3075 </XMLDB>
42 lib/db/upgrade.php
@@ -2000,5 +2000,47 @@ function xmldb_main_upgrade($oldversion) {
2000 2000 upgrade_main_savepoint(true, 2013041200.00);
2001 2001 }
2002 2002
  2003 + if ($oldversion < 2013041500.00) {
  2004 + // Create a new 'badge_external' table first.
  2005 + // Define table 'badge_external' to be created.
  2006 + $table = new xmldb_table('badge_external');
  2007 +
  2008 + // Adding fields to table 'badge_external'.
  2009 + $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
  2010 + $table->add_field('backpackid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
  2011 + $table->add_field('collectionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'backpackid');
  2012 +
  2013 + // Adding keys to table 'badge_external'.
  2014 + $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
  2015 + $table->add_key('fk_backpackid', XMLDB_KEY_FOREIGN, array('backpackid'), 'badge_backpack', array('id'));
  2016 +
  2017 + // Conditionally launch create table for 'badge_external'.
  2018 + if (!$dbman->table_exists($table)) {
  2019 + $dbman->create_table($table);
  2020 + }
  2021 +
  2022 + // Perform user data migration.
  2023 + $usercollections = $DB->get_records('badge_backpack');
  2024 + foreach ($usercollections as $usercollection) {
  2025 + $collection = new stdClass();
  2026 + $collection->backpackid = $usercollection->id;
  2027 + $collection->collectionid = $usercollection->backpackgid;
  2028 + $DB->insert_record('badge_external', $collection);
  2029 + }
  2030 +
  2031 + // Finally, drop the column.
  2032 + // Define field backpackgid to be dropped from 'badge_backpack'.
  2033 + $table = new xmldb_table('badge_backpack');
  2034 + $field = new xmldb_field('backpackgid');
  2035 +
  2036 + // Conditionally launch drop field backpackgid.
  2037 + if ($dbman->field_exists($table, $field)) {
  2038 + $dbman->drop_field($table, $field);
  2039 + }
  2040 +
  2041 + // Main savepoint reached.
  2042 + upgrade_main_savepoint(true, 2013041500.00);
  2043 + }
  2044 +
2003 2045 return true;
2004 2046 }
9 lib/navigationlib.php
@@ -4049,6 +4049,15 @@ protected function generate_user_settings($courseid, $userid, $gstitle='usercurr
4049 4049 }
4050 4050 }
4051 4051
  4052 + // Badges.
  4053 + if ($currentuser && !empty($CFG->enablebadges)) {
  4054 + $badges = $usersetting->add(get_string('badges'), null, navigation_node::TYPE_CONTAINER, null, 'badges');
  4055 + $badges->add(get_string('preferences'), new moodle_url('/badges/preferences.php'), navigation_node::TYPE_SETTING);
  4056 + if (!empty($CFG->badges_allowexternalbackpack)) {
  4057 + $badges->add(get_string('backpackdetails', 'badges'), new moodle_url('/badges/mybackpack.php'), navigation_node::TYPE_SETTING);
  4058 + }
  4059 + }
  4060 +
4052 4061 // Add reports node.
4053 4062 $reporttab = $usersetting->add(get_string('activityreports'));
4054 4063 $reports = get_plugin_list_with_function('report', 'extend_navigation_user', 'lib.php');
3  theme/base/style/core.css
@@ -1353,8 +1353,9 @@ div.badge { position: relative; display: block; }
1353 1353 div.badge .expireimage { width: 100px; height: 100px; left: 20px; top: 0px; }
1354 1354 .expireimage { width: 90px; height: 90px; left: 30px; top: 0px; position: absolute; z-index:10; filter: alpha(opacity = 85); -moz-opacity: 0.85; -khtml-opacity: 0.85; opacity: 0.85;}
1355 1355
1356   -.backpackform { width: 100px !important; float: left; }
1357 1356 .badge-profile { vertical-align: top; }
  1357 +.connected { color: #006600; }
  1358 +.notconnected { color: #660000; }
1358 1359
1359 1360 #page-badges-award .recipienttable { background-color: #EEEEEE; border: 1px solid #BBBBBB; width: 100%; vertical-align: top; }