/** * Reviews criteria and awards badges * * First find all badges that can be earned, then reviews each badge. * (Not sure how efficient this is timewise). */ function badge_review_cron() { global $DB, $CFG; $total = 0; $courseparams = array(); if (empty($CFG->badges_allowcoursebadges)) { $coursesql = ''; } else { $coursesql = ' OR EXISTS (SELECT id FROM {course} WHERE visible = :visible AND startdate < :current) '; $courseparams = array('visible' => true, 'current' => time()); } $sql = 'SELECT id FROM {badge} WHERE (status = :active OR status = :activelocked) AND (type = :site ' . $coursesql . ')'; $badgeparams = array('active' => BADGE_STATUS_ACTIVE, 'activelocked' => BADGE_STATUS_ACTIVE_LOCKED, 'site' => BADGE_TYPE_SITE); $params = array_merge($badgeparams, $courseparams); $badges = $DB->get_fieldset_sql($sql, $params); mtrace('Started reviewing available badges.'); foreach ($badges as $bid) { $badge = new badge($bid); if ($badge->has_criteria()) { if (debugging()) { mtrace('Processing badge "' . $badge->name . '"...'); } $issued = $badge->review_all_criteria(); if (debugging()) { mtrace('...badge was issued to ' . $issued . ' users.'); } $total += $issued; } } mtrace('Badges were issued ' . $total . ' time(s).'); }
/** * Add appropriate form elements to the criteria form * * @param stdClass $data details of overall criterion */ public function config_form_criteria($data) { global $OUTPUT; $prefix = 'criteria-' . $this->id; if (count($data->criteria) > 2) { echo $OUTPUT->box_start(); if (!empty($this->description)) { $badge = new badge($this->badgeid); echo $OUTPUT->box(format_text($this->description, $this->descriptionformat, array('context' => $badge->get_context())), 'criteria-description'); } echo $OUTPUT->heading($this->get_title(), 2); $agg = $data->get_aggregation_methods(); if (!$data->is_locked() && !$data->is_active()) { $editurl = new moodle_url('/badges/criteria_settings.php', array('badgeid' => $this->badgeid, 'edit' => true, 'type' => $this->criteriatype, 'crit' => $this->id)); $editaction = $OUTPUT->action_icon($editurl, new pix_icon('t/edit', get_string('edit')), null, array('class' => 'criteria-action')); echo $OUTPUT->box($editaction, array('criteria-header')); $url = new moodle_url('criteria.php', array('id' => $data->id, 'sesskey' => sesskey())); echo $OUTPUT->single_select($url, 'update', $agg, $data->get_aggregation_method($this->criteriatype), null, null, array('aria-describedby' => 'overall')); echo html_writer::span(get_string('overallcrit', 'badges'), '', array('id' => 'overall')); } else { echo $OUTPUT->box(get_string('criteria_descr_' . $this->criteriatype, 'badges', core_text::strtoupper($agg[$data->get_aggregation_method()])), 'clearfix'); } echo $OUTPUT->box_end(); } }
/** * Test badge awarded event. */ public function test_badge_awarded() { $systemcontext = context_system::instance(); $sink = $this->redirectEvents(); $badge = new badge($this->badgeid); $badge->issue($this->user->id, true); $badge->is_issued($this->user->id); $events = $sink->get_events(); $this->assertCount(1, $events); $event = reset($events); $this->assertInstanceOf('\\core\\event\\badge_awarded', $event); $this->assertEquals($this->badgeid, $event->objectid); $this->assertEquals($this->user->id, $event->relateduserid); $this->assertEquals($systemcontext, $event->get_context()); $sink->close(); }
* @subpackage badges * @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @author Yuliya Bozhko <*****@*****.**> */ require_once dirname(dirname(__FILE__)) . '/config.php'; require_once $CFG->libdir . '/badgeslib.php'; require_once $CFG->dirroot . '/badges/lib/awardlib.php'; $badgeid = required_param('id', PARAM_INT); $role = optional_param('role', 0, PARAM_INT); $award = optional_param('award', false, PARAM_BOOL); require_login(); if (empty($CFG->enablebadges)) { print_error('badgesdisabled', 'badges'); } $badge = new badge($badgeid); $context = $badge->get_context(); $isadmin = is_siteadmin($USER); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type)); if ($badge->type == BADGE_TYPE_COURSE) { if (empty($CFG->badges_allowcoursebadges)) { print_error('coursebadgesdisabled', 'badges'); } require_login($badge->courseid); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid)); } require_capability('moodle/badges:awardbadge', $context); $url = new moodle_url('/badges/award.php', array('id' => $badgeid, 'role' => $role)); $PAGE->set_url($url); $PAGE->set_context($context); // Set up navigation and breadcrumbs.
$sorthow = optional_param('dir', 'DESC', PARAM_ALPHA); $page = optional_param('page', 0, PARAM_INT); require_login(); if (empty($CFG->enablebadges)) { print_error('badgesdisabled', 'badges'); } if (!in_array($sortby, array('firstname', 'lastname', 'dateissued'))) { $sortby = 'dateissued'; } if ($sorthow != 'ASC' and $sorthow != 'DESC') { $sorthow = 'DESC'; } if ($page < 0) { $page = 0; } $badge = new badge($badgeid); $context = $badge->get_context(); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type)); if ($badge->type == BADGE_TYPE_COURSE) { if (empty($CFG->badges_allowcoursebadges)) { print_error('coursebadgesdisabled', 'badges'); } require_login($badge->courseid); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid)); $PAGE->set_pagelayout('standard'); navigation_node::override_active_url($navurl); } else { $PAGE->set_pagelayout('admin'); navigation_node::override_active_url($navurl, true); } $PAGE->set_context($context);
public function print_criteria_actions(badge $badge) { $output = ''; if (!$badge->is_active() && !$badge->is_locked()) { $accepted = $badge->get_accepted_criteria(); $potential = array_diff($accepted, array_keys($badge->criteria)); if (!empty($potential)) { foreach ($potential as $p) { if ($p != 0) { $select[$p] = get_string('criteria_' . $p, 'badges'); } } $output .= $this->output->single_select(new moodle_url('/badges/criteria_settings.php', array('badgeid' => $badge->id, 'add' => true)), 'type', $select, '', array('' => 'choosedots'), null, array('label' => get_string('addbadgecriteria', 'badges'))); } else { $output .= $this->output->box(get_string('nothingtoadd', 'badges'), 'clearfix'); } } return $output; }
/** * Test the badge enabled event. * */ public function test_badge_enabled() { $badge = new badge($this->badgeid); $sink = $this->redirectEvents(); // Trigger and capture the event. $badge->set_status(BADGE_STATUS_ACTIVE); $events = $sink->get_events(); $event = reset($events); $this->assertCount(2, $events); $event = $events[1]; // Check that the event data is valid. $this->assertInstanceOf('\\core\\event\\badge_enabled', $event); $this->assertEquals($badge->id, $event->objectid); $this->assertDebuggingNotCalled(); $sink->close(); }
/** * Bake issued badge. * * @param string $hash Unique hash of an issued badge. * @param int $badgeid ID of the original badge. * @param int $userid ID of badge recipient (optional). * @param boolean $pathhash Return file pathhash instead of image url (optional). * @return string|url Returns either new file path hash or new file URL */ function badges_bake($hash, $badgeid, $userid = 0, $pathhash = false) { global $CFG, $USER; require_once dirname(dirname(__FILE__)) . '/badges/lib/bakerlib.php'; $badge = new badge($badgeid); $badge_context = $badge->get_context(); $userid = $userid ? $userid : $USER->id; $user_context = context_user::instance($userid); $fs = get_file_storage(); if (!$fs->file_exists($user_context->id, 'badges', 'userbadge', $badge->id, '/', $hash . '.png')) { if ($file = $fs->get_file($badge_context->id, 'badges', 'badgeimage', $badge->id, '/', 'f1.png')) { $contents = $file->get_content(); $filehandler = new PNG_MetaDataHandler($contents); $assertion = new moodle_url('/badges/assertion.php', array('b' => $hash)); if ($filehandler->check_chunks("tEXt", "openbadges")) { // Add assertion URL tExt chunk. $newcontents = $filehandler->add_chunks("tEXt", "openbadges", $assertion->out(false)); $fileinfo = array('contextid' => $user_context->id, 'component' => 'badges', 'filearea' => 'userbadge', 'itemid' => $badge->id, 'filepath' => '/', 'filename' => $hash . '.png'); // Create a file with added contents. $newfile = $fs->create_file_from_string($fileinfo, $newcontents); if ($pathhash) { return $newfile->get_pathnamehash(); } } } else { debugging('Error baking badge image!', DEBUG_DEVELOPER); return; } } // If file exists and we just need its path hash, return it. if ($pathhash) { $file = $fs->get_file($user_context->id, 'badges', 'userbadge', $badge->id, '/', $hash . '.png'); return $file->get_pathnamehash(); } $fileurl = moodle_url::make_pluginfile_url($user_context->id, 'badges', 'userbadge', $badge->id, '/', $hash, true); return $fileurl; }
$err = get_string('error:cannotact', 'badges') . get_string('nocriteria', 'badges'); } else { if ($badge->is_locked()) { $badge->set_status(BADGE_STATUS_ACTIVE_LOCKED); $msg = get_string('activatesuccess', 'badges'); } else { require_sesskey(); $badge->set_status(BADGE_STATUS_ACTIVE); $msg = get_string('activatesuccess', 'badges'); } $returnurl->param('msg', $msg); redirect($returnurl); } } else { if ($deactivate && has_capability('moodle/badges:configuredetails', $PAGE->context)) { $badge = new badge($deactivate); if ($badge->is_locked()) { $badge->set_status(BADGE_STATUS_INACTIVE_LOCKED); $msg = get_string('deactivatesuccess', 'badges'); } else { require_sesskey(); $badge->set_status(BADGE_STATUS_INACTIVE); $msg = get_string('deactivatesuccess', 'badges'); } $returnurl->param('msg', $msg); redirect($returnurl); } } echo $OUTPUT->header(); if ($type == BADGE_TYPE_SITE) { echo $OUTPUT->heading_with_help($PAGE->heading, 'sitebadges', 'badges');
/** * Tests the core_badges_myprofile_navigation() function with a course badge. */ public function test_core_badges_myprofile_navigation_with_course_badge() { // Set up the test. $tree = new \core_user\output\myprofile\tree(); $this->setAdminUser(); $badge = new badge($this->coursebadge); $badge->issue($this->user->id, true); $iscurrentuser = false; // Check the node tree is correct. core_badges_myprofile_navigation($tree, $this->user, $iscurrentuser, $this->course); $reflector = new ReflectionObject($tree); $nodes = $reflector->getProperty('nodes'); $nodes->setAccessible(true); $this->assertArrayHasKey('localbadges', $nodes->getValue($tree)); }
* @package core * @subpackage badges * @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @author Yuliya Bozhko <*****@*****.**> */ require_once dirname(dirname(__FILE__)) . '/config.php'; require_once $CFG->libdir . '/badgeslib.php'; require_once $CFG->dirroot . '/badges/edit_form.php'; $badgeid = required_param('id', PARAM_INT); $action = optional_param('action', 'details', PARAM_TEXT); require_login(); if (empty($CFG->enablebadges)) { print_error('badgesdisabled', 'badges'); } $badge = new badge($badgeid); $context = $badge->get_context(); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type)); if ($action == 'message') { require_capability('moodle/badges:configuremessages', $context); } else { require_capability('moodle/badges:configuredetails', $context); } if ($badge->type == BADGE_TYPE_COURSE) { if (empty($CFG->badges_allowcoursebadges)) { print_error('coursebadgesdisabled', 'badges'); } require_login($badge->courseid); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid)); } $currenturl = new moodle_url('/badges/edit.php', array('id' => $badge->id, 'action' => $action));
/** * Add appropriate criteria elements * * @param stdClass $data details of various criteria */ public function config_form_criteria($data) { global $OUTPUT; $agg = $data->get_aggregation_methods(); $editurl = new moodle_url('/badges/criteria_settings.php', array('badgeid' => $this->badgeid, 'edit' => true, 'type' => $this->criteriatype, 'crit' => $this->id)); $deleteurl = new moodle_url('/badges/criteria_action.php', array('badgeid' => $this->badgeid, 'delete' => true, 'type' => $this->criteriatype)); $editaction = $OUTPUT->action_icon($editurl, new pix_icon('t/edit', get_string('edit')), null, array('class' => 'criteria-action')); $deleteaction = $OUTPUT->action_icon($deleteurl, new pix_icon('t/delete', get_string('delete')), null, array('class' => 'criteria-action')); echo $OUTPUT->box_start(); if (!$data->is_locked() && !$data->is_active()) { echo $OUTPUT->box($deleteaction . $editaction, array('criteria-header')); } echo $OUTPUT->heading($this->get_title() . $OUTPUT->help_icon('criteria_' . $this->criteriatype, 'badges'), 3, 'main help'); if (!empty($this->description)) { $badge = new badge($this->badgeid); echo $OUTPUT->box(format_text($this->description, $this->descriptionformat, array('context' => $badge->get_context())), 'criteria-description'); } if (!empty($this->params)) { if (count($this->params) > 1) { echo $OUTPUT->box(get_string('criteria_descr_' . $this->criteriatype, 'badges', core_text::strtoupper($agg[$data->get_aggregation_method($this->criteriatype)])), array('clearfix')); } else { echo $OUTPUT->box(get_string('criteria_descr_single_' . $this->criteriatype, 'badges'), array('clearfix')); } echo $OUTPUT->box($this->get_details(), array('clearfix')); } echo $OUTPUT->box_end(); }
/** * Print badge criteria. * * Modelled after core_badges_renderer::print_badge_critera(), except that * we dispatch rendering of criteria to our own renderer methods as opposed * to calling award_criteria::get_details() wherever possible. * * @param \badge $badge * @param string $short * * @return string */ public function print_badge_criteria(badge $badge, $short = '') { $output = ''; $aggregationmethods = $badge->get_aggregation_methods(); if (!$badge->criteria) { return static::string('nocriteria'); } elseif (count($badge->criteria) === 2) { if (!$short) { $output .= static::string('criteria_descr'); } } else { $stringname = 'criteria_descr_' . $short . BADGE_CRITERIA_TYPE_OVERALL; $output .= static::string($stringname, core_text::strtoupper($aggregationmethods[$badge->get_aggregation_method()])); } unset($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]); $items = array(); foreach ($badge->criteria as $type => $criteria) { $items[] = $this->print_badge_criteria_single($badge, $aggregationmethods, $type, $criteria, $short); } $output .= html_writer::alist($items, array(), 'ul'); return $output; }
/** * Triggered when 'user_updated' event happens. * * @param \core\event\user_updated $event event generated when user profile is updated. */ public static function profile_criteria_review(\core\event\user_updated $event) { global $DB, $CFG; if (!empty($CFG->enablebadges)) { require_once $CFG->dirroot . '/lib/badgeslib.php'; $userid = $event->objectid; if ($rs = $DB->get_records('badge_criteria', array('criteriatype' => BADGE_CRITERIA_TYPE_PROFILE))) { foreach ($rs as $r) { $badge = new badge($r->badgeid); if (!$badge->is_active() || $badge->is_issued($userid)) { continue; } if ($badge->criteria[BADGE_CRITERIA_TYPE_PROFILE]->review($userid)) { $badge->criteria[BADGE_CRITERIA_TYPE_PROFILE]->mark_complete($userid); if ($badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->review($userid)) { $badge->criteria[BADGE_CRITERIA_TYPE_OVERALL]->mark_complete($userid); $badge->issue($userid); } } } } } }
/** * Test the badge viewed event. * * There is no external API for viewing a badge, so the unit test will simply * create and trigger the event and ensure data is returned as expected. */ public function test_badge_viewed() { $badge = new badge($this->badgeid); // Trigger an event: badge viewed. $other = array('badgeid' => $badge->id, 'badgehash' => '12345678'); $eventparams = array('context' => $badge->get_context(), 'other' => $other); $event = \core\event\badge_viewed::create($eventparams); // Trigger and capture the event. $sink = $this->redirectEvents(); $event->trigger(); $events = $sink->get_events(); $event = reset($events); // Check that the event data is valid. $this->assertInstanceOf('\\core\\event\\badge_viewed', $event); $this->assertEquals('12345678', $event->other['badgehash']); $this->assertEquals($badge->id, $event->other['badgeid']); $this->assertDebuggingNotCalled(); $sink->close(); }
* @package core * @subpackage badges * @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @author Yuliya Bozhko <*****@*****.**> */ require_once dirname(dirname(__FILE__)) . '/config.php'; require_once $CFG->libdir . '/badgeslib.php'; $badgeid = required_param('id', PARAM_INT); $copy = optional_param('copy', 0, PARAM_BOOL); $activate = optional_param('activate', 0, PARAM_BOOL); $deactivate = optional_param('lock', 0, PARAM_BOOL); $confirm = optional_param('confirm', 0, PARAM_BOOL); $return = optional_param('return', 0, PARAM_LOCALURL); require_login(); $badge = new badge($badgeid); $context = $badge->get_context(); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type)); if ($badge->type == BADGE_TYPE_COURSE) { require_login($badge->courseid); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid)); $PAGE->set_pagelayout('standard'); navigation_node::override_active_url($navurl); } else { $PAGE->set_pagelayout('admin'); navigation_node::override_active_url($navurl, true); } $PAGE->set_context($context); $PAGE->set_url('/badges/action.php', array('id' => $badge->id)); if ($return !== 0) { $returnurl = new moodle_url($return);
* @copyright 2012 onwards Totara Learning Solutions Ltd {@link http://www.totaralms.com/} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @author Yuliya Bozhko <*****@*****.**> */ require_once dirname(dirname(__FILE__)) . '/config.php'; require_once $CFG->libdir . '/badgeslib.php'; $badgeid = optional_param('badgeid', 0, PARAM_INT); // Badge ID. $crit = optional_param('crit', 0, PARAM_INT); $type = optional_param('type', 0, PARAM_INT); // Criteria type. $delete = optional_param('delete', 0, PARAM_BOOL); $confirm = optional_param('confirm', 0, PARAM_BOOL); require_login(); $return = new moodle_url('/badges/criteria.php', array('id' => $badgeid)); $badge = new badge($badgeid); $context = $badge->get_context(); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type)); // Make sure that no actions available for locked or active badges. if ($badge->is_active() || $badge->is_locked()) { redirect($return); } if ($badge->type == BADGE_TYPE_COURSE) { require_login($badge->courseid); $navurl = new moodle_url('/badges/index.php', array('type' => $badge->type, 'id' => $badge->courseid)); } $PAGE->set_context($context); $PAGE->set_url('/badges/criteria_action.php'); $PAGE->set_pagelayout('standard'); $PAGE->set_heading($badge->name); $PAGE->set_title($badge->name);
/** * Test badges assertion generated when a badge is issued. */ public function test_badges_assertion() { $this->preventResetByRollback(); // Messaging is not compatible with transactions. $badge = new badge($this->coursebadge); $this->assertFalse($badge->is_issued($this->user->id)); $criteria_overall = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_OVERALL, 'badgeid' => $badge->id)); $criteria_overall->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ANY)); $criteria_overall1 = award_criteria::build(array('criteriatype' => BADGE_CRITERIA_TYPE_PROFILE, 'badgeid' => $badge->id)); $criteria_overall1->save(array('agg' => BADGE_CRITERIA_AGGREGATION_ALL, 'field_address' => 'address')); $this->user->address = 'Test address'; $sink = $this->redirectEmails(); user_update_user($this->user, false); $this->assertCount(1, $sink->get_messages()); $sink->close(); // Check if badge is awarded. $this->assertDebuggingCalled('Error baking badge image!'); $awards = $badge->get_awards(); $this->assertCount(1, $awards); // Get assertion. $award = reset($awards); $assertion = new core_badges_assertion($award->uniquehash); $testassertion = $this->assertion; // Make sure JSON strings have the same structure. $this->assertStringMatchesFormat($testassertion->badge, json_encode($assertion->get_badge_assertion())); $this->assertStringMatchesFormat($testassertion->class, json_encode($assertion->get_badge_class())); $this->assertStringMatchesFormat($testassertion->issuer, json_encode($assertion->get_issuer())); }
public function print_criteria_actions(badge $badge) { $table = new html_table(); $table->attributes = array('class' => 'boxaligncenter', 'id' => 'badgeactions'); $table->colclasses = array('activatebadge'); $actions = array(); if (!$badge->is_active() && !$badge->is_locked()) { $accepted = $badge->get_accepted_criteria(); $potential = array_diff($accepted, array_keys($badge->criteria)); if (!empty($potential)) { foreach ($potential as $p) { if ($p != 0) { $select[$p] = get_string('criteria_' . $p, 'badges'); } } $actions[] = get_string('addbadgecriteria', 'badges'); $actions[] = $this->output->single_select(new moodle_url('/badges/criteria_settings.php', array('badgeid' => $badge->id, 'add' => true)), 'type', $select); } else { $actions[] = $this->output->box(get_string('nothingtoadd', 'badges'), 'clearfix'); } } $table->data[] = $actions; return html_writer::table($table); }
public function test_badge_awards() { $badge = new badge($this->badgeid); $user1 = $this->getDataGenerator()->create_user(); $badge->issue($user1->id, true); $this->assertTrue($badge->is_issued($user1->id)); $user2 = $this->getDataGenerator()->create_user(); $badge->issue($user2->id, true); $this->assertTrue($badge->is_issued($user2->id)); $this->assertCount(2, $badge->get_awards()); }