Skip to content

Commit

Permalink
Update Moodle Verbiage to Credly [IN-881]
Browse files Browse the repository at this point in the history
Updated Acclaim verbiage to Credly
Added debugging code and toggle
Added link from selected template to public badge
  • Loading branch information
tylersp7 committed Jan 14, 2023
1 parent 88fbfa4 commit 12d6d4c
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 78 deletions.
2 changes: 1 addition & 1 deletion backup/moodle2/backup_acclaim_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected function define_structure() {
$acclaim = new backup_nested_element(
'acclaim_course',
array('id'),
array('courseid', 'badgeid', 'expiration', 'badgename')
array('courseid', 'badgeid', 'expiration', 'badgename', 'badgeurl')
);

$acclaim->set_source_table('block_acclaim_courses', array('courseid' => backup::VAR_COURSEID));
Expand Down
75 changes: 56 additions & 19 deletions block_acclaim.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,24 @@ public function has_config() {
* Display specialized text for the course block (the selected badge name).
*/
public function specialization() {
// There are times when this function does not seem to be called, resulted in unexpected UI. Because of
// this, all logic is in get_content.
if(!isset($this->config)){
$this->config = new stdClass();
}
global $COURSE;
$course_id = $COURSE->id;

$badge_name = $this->acclaim->get_course_info($course_id, 'badgename');
$badge_url = $this->acclaim->get_course_info($course_id, 'badgeurl');

if (!isset($badge_name) || $badge_name == '') {
$badge_name = 'No Badge Selected';
}
if (!isset($badge_url) || $badge_url == '') {
$badge_url = 'No URL Set';
}

$this->config->text = $badge_name;
$this->config->text2 = $badge_url;
}

/**
Expand Down Expand Up @@ -88,7 +104,7 @@ public function applicable_formats() {
* @return string
*/
public function get_content() {
global $COURSE;
global $COURSE, $DB, $OUTPUT, $CFG, $PAGE;

if ($this->content !== null) {
return $this->content;
Expand All @@ -97,30 +113,51 @@ public function get_content() {
$badge_name = $this->acclaim->get_course_info($COURSE->id, 'badgename');

$this->content = new stdClass;
if (empty($badge_name)) {
$this->content->text = get_string('no_badge', 'block_acclaim');
} else {
$this->content->text = $badge_name;
if (!empty($this->config->text) && $this->config->text != "No Badge Selected") {
$this->content->text = html_writer::link($this->config->text2, $this->config->text);
} elseif (!empty($this->config->text)) {
$this->content->text = $this->config->text;
}

/* Debugging
global $DB;
$course = $DB->get_record('block_acclaim_courses', array('courseid' => $COURSE->id));
if (empty($course)) {
$this->content->text .= "<br><br>Error: Course [" . $COURSE->id . "] not found.";
} else {
$this->content->text .= "<br><br>Acclaim id: {$course->id}";
$this->content->text .= "<br>Course id: {$course->courseid}, {$COURSE->id}";
$this->content->text .= "<br>Badge id: {$course->badgeid}";
$this->content->text .= "<br>Badge name: {$course->badgename}";
/* Debugging */
// Output goes to block screen on course homes.
if (block_acclaim_lib::$allow_debug) {
$course = $DB->get_record('block_acclaim_courses', array('courseid' => $COURSE->id));
$pending_badges = $DB->get_records('block_acclaim_pending_badges');
$badge_count = count($pending_badges);

if (empty($course)) {
$this->content->text .= "<br><br>Error: Course [" . $COURSE->id . "] not found or badge not selected yet.<br>";
} else {
$this->content->text .= "<br><br>Credly id: {$course->id}";
$this->content->text .= "<br>Course id: {$course->courseid}, {$COURSE->id}";
$this->content->text .= "<br>Badge id: {$course->badgeid}";
$this->content->text .= "<br>Badge name: {$course->badgename}<br>";
if (!empty($pending_badges)) {
$this->content->text .= "<br>Pending Badge Count: {$badge_count}";
foreach ($pending_badges as $badge) {
$this->content->text .= "<br>Pending Issue Template id: {$badge->badgetemplateid}";
$this->content->text .= "<br>Earner email: {$badge->recipientemail}";

if ($badge->expiration) {
$expiration = $this->convert_time_stamp($badge->expiration);
$this->content->text .= "<br>Pending Badge expiration: {$expiration}";
}
}
} else {
$this->content->text .= "<br><br>Pending Badge Count: {$badge_count}";
$this->content->text .= "<br>There are no pending badges<br>";
}
}
}
*/


$url = new moodle_url(
'/blocks/acclaim/view.php',
array('blockid' => $this->instance->id, 'courseid' => $COURSE->id)
);


$context = context_course::instance($COURSE->id);
if (has_capability('block/acclaim:editbadge', $this->context)) {
$this->content->footer = html_writer::link($url, get_string('select_badge', 'block_acclaim'));
}
Expand Down
21 changes: 17 additions & 4 deletions block_acclaim_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,30 @@ function definition() {

//populate form
$mform->addElement('header','displayinfo', get_string('select_badge', 'block_acclaim'));
$badge_items = (new \block_acclaim_lib())->badge_names();
$badge_data = (new \block_acclaim_lib());
$badge_items = $badge_data->badge_names();
$badge_urls = $badge_data->badge_names('urls');
$mform->addElement('select', 'badgeid', get_string('acclaim_badges', 'block_acclaim'), $badge_items, '');
$mform->addElement('date_time_selector', 'expiration', get_string('expires', 'block_acclaim'), array('optional' => true));
$mform->setAdvanced('optional');

// hidden elements
$mform->addElement('hidden', 'blockid');
$badge_items_ext = array_merge($badge_items, $badge_urls);
$badges_encoded = json_encode($badge_items_ext);
if (block_acclaim_lib::$allow_debug) {
$mform->addElement('static', 'label', 'hidden field blockid');
$mform->addElement('text', 'blockid');
$mform->addElement('static', 'label2', 'hidden field courseid');
$mform->addElement('text', 'courseid');
$mform->addElement('static','label3', 'hidden field badge name and url');
$mform->addElement('textarea', 'badgenamedisplay',$badges_encoded);
} else {
$mform->addElement('hidden', 'blockid');
$mform->addElement('hidden', 'courseid');
}
$mform->addElement('hidden','badgename', $badges_encoded);
$mform->setType('blockid', PARAM_INT);
$mform->addElement('hidden', 'courseid');
$mform->setType('courseid', PARAM_INT);
$mform->addElement('hidden','badgename', json_encode($badge_items));
$mform->setType('badgename', PARAM_RAW);
$this->add_action_buttons();
}
Expand Down
1 change: 1 addition & 0 deletions db/install.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<FIELD NAME="badgeid" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Badge Template ID"/>
<FIELD NAME="expiration" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Badge Expiration"/>
<FIELD NAME="badgename" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Badge Name"/>
<FIELD NAME="badgeurl" TYPE="text" NOTNULL="true" SEQUENCE="false" COMMENT="Badge URL"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
Expand Down
29 changes: 14 additions & 15 deletions lang/en/block_acclaim.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,23 @@

// Re-reading this file requires a version change.
// In development, set this in config.php instead: $CFG->langstringcache = false;
$string['pluginname'] = 'Acclaim';
$string['acclaim'] = 'Acclaim';
$string['config_header'] = 'Create a new Acclaim block for this course';
$string['config_instructions'] = 'This block will issue an Acclaim badge on course completion. The badge may be selected from the course page.';
$string['acclaim:addinstance'] = 'Add a new Acclaim block';
$string['acclaim:myaddinstance'] = 'Add a new Acclaim block to the My Moodle page';
$string['pluginname'] = 'Credly';
$string['acclaim'] = 'Credly';
$string['config_header'] = 'Create a new Credly block for this course';
$string['config_instructions'] = 'This block will issue an Credly badge on course completion. The badge may be selected from the course page.';
$string['acclaim:addinstance'] = 'Add a new Credly block';
$string['acclaim:myaddinstance'] = 'Add a new Credly block to the My Moodle page';
$string['acclaim:editbadge'] = 'Select a badge to associate with a course';
$string['privacy:metadata'] = 'The Acclaim block only stores course and badge template details. User data is stored in a temporary table and removed once issued';
$string['privacy:metadata'] = 'The Credly block only stores course and badge template details. User data is stored in a temporary table and removed once issued';
$string['select_badge'] = 'Select Badge';
$string['no_badge'] = 'No badge selected';
$string['acclaim_badges'] = 'Acclaim Badges';
$string['acclaim_badges'] = 'Credly Badges';
$string['expires'] = 'Expires';
$string['production'] = 'Production'; // The name of the Acclaim production server.
$string['sandbox'] = 'Sandbox'; // The name of the Acclaim demo server.
$string['setting_domain'] = 'Acclaim Server';
$string['setting_org_id'] = 'Acclaim Organization ID';
$string['setting_domain'] = 'Credly Server';
$string['setting_org_id'] = 'Credly Organization ID';
$string['setting_org_help'] = 'Example: {$a}';
$string['setting_app_token'] = 'Acclaim App Token';
$string['setting_app_token_help'] = 'This is obtained from Acclaim support. Example: {$a}';
$string['setting_app_token_help'] = 'This is obtained from Acclaim support. Example: {$a}';
$string['issuecredentials_task_name'] = 'Acclaim - Issue Badges';
$string['setting_app_token'] = 'Credly App Token';
$string['setting_app_token_help'] = 'This is obtained from Credly support. Example: {$a}';
$string['setting_app_token_help'] = 'This is obtained from Credly support. Example: {$a}';
$string['issuecredentials_task_name'] = 'Credly - Issue Badges';
109 changes: 73 additions & 36 deletions lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
class block_acclaim_lib {
public static $config = null;
public static $allow_print = true;
public static $allow_debug = false;

public static function config() {
if (!isset(self::$config)) {
Expand Down Expand Up @@ -79,11 +80,17 @@ public function issue_pending_badges($curl) {

$pending_badges = $DB->get_records('block_acclaim_pending_badges');

if (self::$allow_debug) {
print_r($pending_badges);
}

foreach ($pending_badges as &$badge) {
// Output goes to the cron log.
if (self::$allow_print) {
print "Acclaim block: Issuing badge {$badge->badgetemplateid} to {$badge->recipientemail}.\n";
}


$payload = [
'badge_template_id' => $badge->badgetemplateid,
'issued_to_first_name' => $badge->firstname,
Expand All @@ -100,6 +107,8 @@ public function issue_pending_badges($curl) {
$url, $payload, array('CURLOPT_USERPWD' => block_acclaim_lib::$config->token . ':')
);

print $curl->info['http_code'];

if ($curl->info['http_code'] == 201) {
// The badge has been issued so we remove it from pending.
$DB->delete_records('block_acclaim_pending_badges', array('id' => $badge->id));
Expand Down Expand Up @@ -153,11 +162,22 @@ function get_course_info($course_id, $field) {
function set_course_badge_template($fromform) {
global $DB;

$badge_name = json_decode($fromform->badgename)->{$fromform->badgeid};
$badge_data = json_decode($fromform->badgename, true);
$badge_name = $badge_data[$fromform->badgeid];

$urlId = $fromform->badgeid.'_url';
$badge_url = $badge_data[$urlId];

if (isset($badge_name)) {
$fromform->badgename = $badge_name;
}

if (isset($badge_url)) {
$fromform->badgeurl = $badge_url;
} else {
$fromform->badgeurl = "Badge URL Isn't Set";
}

$DB->delete_records('block_acclaim_courses', array('courseid' => $fromform->courseid));

return $DB->insert_record('block_acclaim_courses', $fromform);
Expand All @@ -168,71 +188,88 @@ function set_course_badge_template($fromform) {
*
* @return array
*/
function badge_names() {
function badge_names($returntype = '') {
$badge_items = array();
$badge_urls = array();

$json = $this->search_badges();
$this->accumulate_badge_names($json, $badge_items);
$json = $this->query_api(null);
$this->accumulate_badge_names($json, $badge_items, $badge_urls);

while (isset($json['metadata']['next_page_url'])) {
$json = $this->query_api($json['metadata']['next_page_url']);
$this->accumulate_badge_names($json, $badge_items);
}
$next_page_url = '';
if (isset($json['metadata'])) {
$metadata = $json['metadata'];
$next_page_url = $metadata['next_page_url'];

while (!is_null($next_page_url)) {
$json = $this->query_api("$next_page_url&sort=name&filter=state::active");
$this->accumulate_badge_names($json, $badge_items, $badge_urls);

if (isset($json['metadata'])) {
$metadata = $json['metadata'];
$next_page_url = $metadata['next_page_url'];
}
}
}
if ($returntype == 'urls') {
return $badge_urls;
}
return $badge_items;
}

////////////////////
// Private functions
////////////////////

/**
* Get the badge list from the Acclaim API, as JSON.
*
* @param curl $curl
* @param string $url
* @param string $token
* @return object
*/
private function fetch_badge_json($curl, $url, $token) {
$params = array('sort' => 'name', 'filter' => 'state::active');
$options = array('CURLOPT_USERPWD' => $token . ':');
return $curl->get($url, $params, $options);
}

/**
* Create a user-readable list of badge names.
*
* @param object $json - Badge list JSON from the Acclaim API.
* @param array $badge_names - An accumulated list of badge names.
*/
protected function accumulate_badge_names($json, &$badge_items) {
if (isset($json['data'])) {
foreach ($json['data'] as $item) {
if (isset($item['name'])) {
$len = strlen($item['name']);
$badge_items[$item['id']] = $len > 75 ? substr($item['name'], 0, 75 - $len) . '...' : $item['name'];
} else {
error_log('block_acclaim: error parsing badge name JSON:');
error_log(print_r($item, true));
}
private function accumulate_badge_names($json, &$badge_items, &$badge_urls) {
$arr = json_decode($json, true);
if (isset($arr['data'])) {
foreach ($arr['data'] as $item) {
$len = strlen($item['name']);
$badge_items[$item['id']] = $len > 75 ? substr($item['name'], 0, 75 - $len) . '...' : $item['name'];
$badge_urls[$item['id'].'_url'] = $item['url'];
}
} else {
error_log('block_acclaim: invalid api, token or unable to connect');
error_log('invalid api, token or unable to connect');
}
}

/**
* Send a request to Credly's Acclaim API.
*
* @param string $search - Search for this string
* @param string $url - The URL to send. If omitted, request all badge templates for the
* configured organization.
* @return object - The JSON response.
*/
protected function search_badges($search = null) {
$config = self::$config;
$url = "{$config->url}/organizations/{$config->org}/badge_templates?sort=name&filter=state::active";
if ($search) {
$url .= "|name::$search";
private function query_api($url) {
if (is_null($url)) {
$config = self::$config;
$url = "{$config->url}/organizations/{$config->org}/badge_templates?sort=name&filter=state::active";
}
return $this->query_api($url);
}

/**
* Send a request to Credly's Acclaim API.
*
* @param string $url - The URL to send.
* @return object - The JSON response.
*/
protected function query_api($url) {
$params = array('sort' => 'name', 'filter' => 'state::active');
$options = array('CURLOPT_USERPWD' => self::$config->token . ':');
$result = (new curl())->get($url, null, $options);
return json_decode($result, true);
$result = (new curl())->get($url, $params, $options);
return $result;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/block_acclaim_lib_Test.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public function test_issue_pending_badges_mutltiple() {

$this->assert_pending_badge_count(0);
}

////////////////////
// Private functions
////////////////////
Expand Down
2 changes: 1 addition & 1 deletion version.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@

defined('MOODLE_INTERNAL') || die();

$plugin->version = 2022022300; // YYYYMMDDHH (year, month, day, 24-hr time)
$plugin->version = 2023010900; // YYYYMMDDHH (year, month, day, 24-hr time)
$plugin->requires = 2014050800; // Requires this Moodle version
$plugin->component = 'block_acclaim'; // Full name of the plugin (used for diagnostics)
Loading

0 comments on commit 12d6d4c

Please sign in to comment.