From 129e7dffebdd229bc24f3c6d94db0ed1bab49c8d Mon Sep 17 00:00:00 2001 From: Yuliya Bozhko Date: Mon, 2 Sep 2013 13:45:13 +0800 Subject: [PATCH] MDL-40924 badges: Add caching to external badges --- badges/external.php | 42 +++++++++++++++++++++++++++++++++++++++--- badges/mybackpack.php | 3 +++ badges/renderer.php | 13 +++++++------ lang/en/badges.php | 5 ++++- lang/en/cache.php | 1 + lib/badgeslib.php | 15 ++++++++++++++- lib/db/caches.php | 6 ++++++ version.php | 2 +- 8 files changed, 75 insertions(+), 12 deletions(-) diff --git a/badges/external.php b/badges/external.php index 5436f016ecd..cf0ac0f8fd1 100644 --- a/badges/external.php +++ b/badges/external.php @@ -27,14 +27,50 @@ require_once(dirname(dirname(__FILE__)) . '/config.php'); require_once($CFG->libdir . '/badgeslib.php'); -$json = required_param('badge', PARAM_RAW); +$json = optional_param('badge', null, PARAM_RAW); +// Redirect to homepage if users are trying to access external badge through old url. +if ($json) { + redirect($CFG->wwwroot, get_string('invalidrequest', 'error'), 3); +} + +$hash = required_param('hash', PARAM_ALPHANUM); +$userid = required_param('user', PARAM_INT); + +$PAGE->set_url(new moodle_url('/badges/external.php', array('hash' => $hash, 'user' => $userid))); + +// Using the same setting as user profile page. +if (!empty($CFG->forceloginforprofiles)) { + require_login(); + if (isguestuser()) { + $SESSION->wantsurl = $PAGE->url->out(false); + redirect(get_login_url()); + } +} else if (!empty($CFG->forcelogin)) { + require_login(); +} + +// Get all external badges of a user. +$out = get_backpack_settings($userid); +$badges = $out->badges; + +// Loop through the badges and check if supplied badge hash exists in user external badges. +foreach ($badges as $b) { + if ($hash == hash("md5", $b->hostedUrl)) { + $badge = $b; + break; + } +} + +// If we didn't find the badge, a user might be trying to replace userid parameter. +if (is_null($badge)) { + print_error(get_string('error:externalbadgedoesntexist', 'badges')); +} $PAGE->set_context(context_system::instance()); $output = $PAGE->get_renderer('core', 'badges'); -$badge = new external_badge(unserialize($json)); +$badge = new external_badge($badge); -$PAGE->set_url('/badges/external.php'); $PAGE->set_pagelayout('base'); $PAGE->set_title(get_string('issuedbadge', 'badges')); diff --git a/badges/mybackpack.php b/badges/mybackpack.php index 1f524539900..875d025b1d3 100644 --- a/badges/mybackpack.php +++ b/badges/mybackpack.php @@ -53,11 +53,13 @@ $PAGE->set_heading($title); $PAGE->set_pagelayout('mydashboard'); $backpack = $DB->get_record('badge_backpack', array('userid' => $USER->id)); +$badgescache = cache::make('core', 'externalbadges'); if ($disconnect && $backpack) { require_sesskey(); $DB->delete_records('badge_external', array('backpackid' => $backpack->id)); $DB->delete_records('badge_backpack', array('userid' => $USER->id)); + $badgescache->delete($USER->id); redirect(new moodle_url('/badges/mybackpack.php')); } @@ -103,6 +105,7 @@ if ($backpack) { $DB->insert_record('badge_external', $obj); } } + $badgescache->delete($USER->id); redirect(new moodle_url('/badges/mybadges.php')); } } else { diff --git a/badges/renderer.php b/badges/renderer.php index 69452c8fdea..dec661d61bb 100644 --- a/badges/renderer.php +++ b/badges/renderer.php @@ -81,9 +81,10 @@ class core_badges_renderer extends plugin_renderer_base { $url = new moodle_url('badge.php', array('hash' => $badge->uniquehash)); } else { if (!$external) { - $url = new moodle_url($CFG->wwwroot . '/badges/badge.php', array('hash' => $badge->uniquehash)); + $url = new moodle_url('/badges/badge.php', array('hash' => $badge->uniquehash)); } else { - $url = new moodle_url($CFG->wwwroot . '/badges/external.php', array('badge' => serialize($badge))); + $hash = hash('md5', $badge->hostedUrl); + $url = new moodle_url('/badges/external.php', array('hash' => $hash, 'user' => $userid)); } } $actions = html_writer::tag('div', $push . $download . $status, array('class' => 'badge-actions')); @@ -918,10 +919,10 @@ class external_badge implements renderable { /** * Initializes the badge to display * - * @param string $json External badge information. + * @param object $badge External badge information. */ - public function __construct($json) { - $this->issued = $json; + public function __construct($badge) { + $this->issued = $badge; } } @@ -1016,7 +1017,7 @@ class badge_user_collection extends badge_collection implements renderable { parent::__construct($badges); if (!empty($CFG->badges_allowexternalbackpack)) { - $this->backpack = get_backpack_settings($userid); + $this->backpack = get_backpack_settings($userid, true); } } } diff --git a/lang/en/badges.php b/lang/en/badges.php index 9e5b147dabe..bc45007bc1c 100644 --- a/lang/en/badges.php +++ b/lang/en/badges.php @@ -101,7 +101,9 @@ $string['badgeprivacysetting_help'] = 'Badges you earn can be displayed on your You can still control individual badge privacy settings on your "My badges" page.'; $string['badgeprivacysetting_str'] = 'Automatically show badges I earn on my profile page'; $string['badgesalt'] = 'Salt for hashing the recepient\'s email address'; -$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.'; +$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. + +Note: For recipient verification purposes, please avoid changing this setting once you start issuing badges.'; $string['badgesdisabled'] = 'Badges are not enabled on this site.'; $string['badgesearned'] = 'Number of badges earned: {$a}'; $string['badgesettings'] = 'Badges settings'; @@ -203,6 +205,7 @@ $string['error:cannotact'] = 'Cannot activate the badge. '; $string['error:cannotawardbadge'] = 'Cannot award badge to a user.'; $string['error:clone'] = 'Cannot clone the badge.'; $string['error:duplicatename'] = 'Badge with such name already exists in the system.'; +$string['error:externalbadgedoesntexist'] = 'Badge not found'; $string['error:invalidbadgeurl'] = 'Invalid badge issuer URL format.'; $string['error:invalidcriteriatype'] = 'Invalid criteria type.'; $string['error:invalidexpiredate'] = 'Expiry date has to be in the future.'; diff --git a/lang/en/cache.php b/lang/en/cache.php index 58c7d9db4a9..4a46f62a00b 100644 --- a/lang/en/cache.php +++ b/lang/en/cache.php @@ -44,6 +44,7 @@ $string['cachedef_coursecontacts'] = 'List of course contacts'; $string['cachedef_coursecattree'] = 'Course categories tree'; $string['cachedef_databasemeta'] = 'Database meta information'; $string['cachedef_eventinvalidation'] = 'Event invalidation'; +$string['cachedef_externalbadges'] = 'External badges for particular user'; $string['cachedef_groupdata'] = 'Course group information'; $string['cachedef_htmlpurifier'] = 'HTML Purifier - cleaned content'; $string['cachedef_locking'] = 'Locking'; diff --git a/lib/badgeslib.php b/lib/badgeslib.php index 253ab94a209..82bd6d044f8 100644 --- a/lib/badgeslib.php +++ b/lib/badgeslib.php @@ -1167,13 +1167,25 @@ function badges_bake($hash, $badgeid, $userid = 0, $pathhash = false) { /** * Returns external backpack settings and badges from this backpack. * + * This function first checks if badges for the user are cached and + * tries to retrieve them from the cache. Otherwise, badges are obtained + * through curl request to the backpack. + * * @param int $userid Backpack user ID. + * @param boolean $refresh Refresh badges collection in cache. * @return null|object Returns null is there is no backpack or object with backpack settings. */ -function get_backpack_settings($userid) { +function get_backpack_settings($userid, $refresh = false) { global $DB; require_once(dirname(dirname(__FILE__)) . '/badges/lib/backpacklib.php'); + // Try to get badges from cache first. + $badgescache = cache::make('core', 'externalbadges'); + $out = $badgescache->get($userid); + if ($out !== false && !$refresh) { + return $out; + } + // Get badges through curl request to the backpack. $record = $DB->get_record('badge_backpack', array('userid' => $userid)); if ($record) { $backpack = new OpenBadgesBackpackHandler($record); @@ -1198,6 +1210,7 @@ function get_backpack_settings($userid) { $out->totalcollections = 0; } + $badgescache->set($userid, $out); return $out; } diff --git a/lib/db/caches.php b/lib/db/caches.php index 2ec5b98503d..af2a37b351a 100644 --- a/lib/db/caches.php +++ b/lib/db/caches.php @@ -236,4 +236,10 @@ $definitions = array( 'mode' => cache_store::MODE_REQUEST, 'persistent' => true, ), + // Used to store external badges. + 'externalbadges' => array( + 'mode' => cache_store::MODE_APPLICATION, + 'simplekeys' => true, + 'ttl' => 3600, + ), ); diff --git a/version.php b/version.php index da1c7e0cd37..eae4e8dd079 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2013051401.12; // 20130514 = branching date YYYYMMDD - do not modify! +$version = 2013051401.13; // 20130514 = branching date YYYYMMDD - do not modify! // RR = release increments - 00 in DEV branches // .XX = incremental changes