diff --git a/backup/moodle2/backup_acclaim_stepslib.php b/backup/moodle2/backup_acclaim_stepslib.php index b29871f..37111a9 100644 --- a/backup/moodle2/backup_acclaim_stepslib.php +++ b/backup/moodle2/backup_acclaim_stepslib.php @@ -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)); diff --git a/block_acclaim.php b/block_acclaim.php index 3bf1536..4d04f47 100755 --- a/block_acclaim.php +++ b/block_acclaim.php @@ -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; } /** @@ -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; @@ -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 .= "

Error: Course [" . $COURSE->id . "] not found."; - } else { - $this->content->text .= "

Acclaim id: {$course->id}"; - $this->content->text .= "
Course id: {$course->courseid}, {$COURSE->id}"; - $this->content->text .= "
Badge id: {$course->badgeid}"; - $this->content->text .= "
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 .= "

Error: Course [" . $COURSE->id . "] not found or badge not selected yet.
"; + } else { + $this->content->text .= "

Credly id: {$course->id}"; + $this->content->text .= "
Course id: {$course->courseid}, {$COURSE->id}"; + $this->content->text .= "
Badge id: {$course->badgeid}"; + $this->content->text .= "
Badge name: {$course->badgename}
"; + if (!empty($pending_badges)) { + $this->content->text .= "
Pending Badge Count: {$badge_count}"; + foreach ($pending_badges as $badge) { + $this->content->text .= "
Pending Issue Template id: {$badge->badgetemplateid}"; + $this->content->text .= "
Earner email: {$badge->recipientemail}"; + + if ($badge->expiration) { + $expiration = $this->convert_time_stamp($badge->expiration); + $this->content->text .= "
Pending Badge expiration: {$expiration}"; + } + } + } else { + $this->content->text .= "

Pending Badge Count: {$badge_count}"; + $this->content->text .= "
There are no pending badges
"; + } + } } - */ + $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')); } diff --git a/block_acclaim_form.php b/block_acclaim_form.php index dec2072..42a07e7 100755 --- a/block_acclaim_form.php +++ b/block_acclaim_form.php @@ -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(); } diff --git a/db/install.xml b/db/install.xml index d04a622..e4171a0 100755 --- a/db/install.xml +++ b/db/install.xml @@ -11,6 +11,7 @@ + diff --git a/lang/en/block_acclaim.php b/lang/en/block_acclaim.php index f0ccabb..65684ef 100755 --- a/lang/en/block_acclaim.php +++ b/lang/en/block_acclaim.php @@ -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'; \ No newline at end of file +$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'; diff --git a/lib.php b/lib.php index 68ca3ea..1b8eaf8 100644 --- a/lib.php +++ b/lib.php @@ -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)) { @@ -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, @@ -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)); @@ -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); @@ -168,17 +188,31 @@ 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; } @@ -186,53 +220,56 @@ function badge_names() { // 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; } /** diff --git a/tests/block_acclaim_lib_Test.php b/tests/block_acclaim_lib_Test.php index c21bcf6..27df382 100644 --- a/tests/block_acclaim_lib_Test.php +++ b/tests/block_acclaim_lib_Test.php @@ -202,7 +202,7 @@ public function test_issue_pending_badges_mutltiple() { $this->assert_pending_badge_count(0); } - + //////////////////// // Private functions //////////////////// diff --git a/version.php b/version.php index 356ceb1..ee8c240 100755 --- a/version.php +++ b/version.php @@ -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) diff --git a/view.php b/view.php index 74a3303..e70c951 100755 --- a/view.php +++ b/view.php @@ -43,7 +43,7 @@ $PAGE->set_pagelayout('standard'); $PAGE->set_heading(get_string('acclaim', 'block_acclaim')); -$settingsnode = $PAGE->settingsnav->add('acclaim'); +$settingsnode = $PAGE->settingsnav->add('Credly'); $editurl = new moodle_url('/blocks/acclaim/view.php', array('id' => $id, 'courseid' => $courseid, 'blockid' => $blockid)); $editnode = $settingsnode->add(get_string('select_badge', 'block_acclaim'), $editurl); $editnode->make_active();