/* $Id: admin.php 173 2012-11-04 20:05:05Z azeckoski@gmail.com $ */ /** * Handles rendering the CSV which represents all clicker registrations in the system */ require_once '../../config.php'; global $CFG, $USER, $COURSE, $OUTPUT, $PAGE; require_once 'iclicker_service.php'; require_once 'controller.php'; $site = get_site(); require_login($site); // activate the controller $cntlr = new iclicker_controller(); $cntlr->processAdminCSV(); extract($cntlr->results); // set CSV headers header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private", false); header("Content-Transfer-Encoding: binary"); header("Content-type: text/csv"); header("Content-Disposition: attachment; filename=\"registrations.csv\";"); // begin rendering $regHeaderData = array('ClickerId', 'UserId', 'UserDisplayName', 'UserEmail', 'Activated', 'TimeCreated', 'TimeModified'); $row = iclicker_service::make_CSV_row($regHeaderData); echo $row; foreach ($registrations as $registration) { $regData = array($registration->clicker_id, $registration->owner_id, $registration->user_display_name, $registration->user_email, $registration->activated ? 1 : 0, $registration->timecreated, $registration->timemodified); $row = iclicker_service::make_CSV_row($regData); echo $row; }
} } ?> </div> <div class="nav_links"> <?php $reg_link = '<a class="nav_link" href="' . iclicker_service::block_url('registration.php') . '">' . iclicker_service::msg('reg.title') . '</a>'; $nav_links = $reg_link . PHP_EOL; // the other links $nav_links .= ' | <a class="nav_link current_nav_link" href="' . iclicker_service::block_url('instructor.php') . '">' . iclicker_service::msg('inst.title') . '</a>' . PHP_EOL; if (iclicker_service::$block_iclicker_sso_enabled) { $nav_links .= ' | <a class="nav_link" href="' . iclicker_service::block_url('instructor_sso.php') . '">' . iclicker_service::msg('inst.sso.title') . '</a>' . PHP_EOL; } if (iclicker_service::is_admin()) { $nav_links .= ' | <a class="nav_link" href="' . iclicker_service::block_url('admin.php') . '">' . iclicker_service::msg('admin.title') . '</a>' . PHP_EOL; } echo $nav_links; ?> </div> <div class="iclicker_version">Version <?php echo iclicker_service::VERSION; ?> (<?php echo iclicker_service::BLOCK_VERSION; ?> )</div> </div>
</div> </div> <script type="text/javascript"> jQuery(document).ready(function () { // date pickers jQuery(".iclicker .date_picker_marker").datepicker({ dateFormat: "yy-mm-dd", changeMonth: true, changeYear: true }); // purge confirmation jQuery("#purgeFormSubmit").click(function (e) { if (!confirm("<?php echo iclicker_service::msg('admin.search.purge.confirm', $total_count); ?> ")) { e.preventDefault(); return false; } else { // switch the form to POST for purge submission $(this).closest("form").attr("method", "POST"); } return true; }); }); </script> <?php echo $OUTPUT->footer();
function disabled_test_save_ws() { $result = iclicker_service::ws_get_students(); $this->assertNotNull($result); $clicker_reg = new stdClass(); $clicker_reg->owner_id = '101'; // student01 $clicker_reg->clicker_id = '11111111'; // NOTE: disable this to avoid putting test data into the real domain of systems /* $result = iclicker_service::ws_save_clicker($clicker_reg); $this->assertNotNull($result); */ $result = iclicker_service::ws_get_student('student01'); $this->assertNotNull($result); }
/** * @param string $sharedKey set and verify the shared key (if invalid, log a warning) */ public static function setSharedKey($sharedKey) { if ($sharedKey != null) { if (strlen($sharedKey) < 10) { error_log("i>clicker shared key ({$sharedKey}) is too short, must be at least 10 chars long. SSO shared key will be ignored until a longer key is entered."); } else { self::$block_iclicker_sso_enabled = true; self::$block_iclicker_sso_shared_key = $sharedKey; if (!self::$test_mode) { error_log("i>clicker plugin SSO handling enabled by shared key, note that this will disable normal username/password handling"); } } } }
/** * Add an i18n message based on a key * * @param string $key the KEY const * @param string $messageKey the i18n message key * @param object $args [OPTIONAL] args to include * @param string $extra [OPTIONAL] extra string to include hidden on the page with the message * @throws Exception if the key is invalid */ public function addMessage($key, $messageKey, $args = null, $extra = null) { if ($key == null) { throw new Exception("key (" . $key . ") must not be null"); } if ($messageKey) { $message = iclicker_service::msg($messageKey, $args); $this->addMessageStr($key, $message, $extra); } }
/** * Attempt to authenticate the current request based on request params and basic auth * @param iclicker_controller $cntlr the controller instance * @throws ClickerSecurityException if authentication is impossible given the request values * @throws ClickerSSLRequiredException if the auth request is bad (requires SSL but SSL not used) */ function iclicker_handle_authn($cntlr) { global $CFG; // extract the authn params $auth_username = optional_param(iclicker_controller::LOGIN, NULL, PARAM_NOTAGS); $auth_password = optional_param(iclicker_controller::PASSWORD, NULL, PARAM_NOTAGS); if (empty($auth_username) && isset($_SERVER['PHP_AUTH_USER'])) { // no username found in normal params so try to get basic auth $auth_username = $_SERVER['PHP_AUTH_USER']; $auth_password = $_SERVER['PHP_AUTH_PW']; if (empty($auth_username)) { // attempt to get it from the header as a final try list($auth_username, $auth_password) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6))); } } if (iclicker_service::$block_iclicker_sso_enabled && !empty($auth_password)) { // when SSO is enabled and the password is set it means this is not actually a user password so we can proceed without requiring SSL } else { // this is a user password so https must be used if the loginhttps option is enabled $ssl_request = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443; $ssl_required = isset($CFG->forcehttps) && $CFG->forcehttps == true || isset($CFG->loginhttps) && $CFG->loginhttps == true; if ($ssl_required && !$ssl_request) { throw new ClickerSSLRequiredException('SSL is required when performing a user login (and sending user passwords)'); } } //$session_id = optional_param(iclicker_controller::SESSION_ID, NULL, PARAM_NOTAGS); if (!empty($auth_username)) { $sso_key = optional_param(iclicker_controller::SSO_KEY, NULL, PARAM_NOTAGS); iclicker_service::authenticate_user($auth_username, $auth_password, $sso_key); // throws exception if fails //} else if ($session_id) { // $valid = FALSE; // validate the session key // if (! $valid) { // throw new SecurityException("Invalid "+iclicker_controller::SESSION_ID+" provided, session may have expired, send new login credentials"); // } } $current_user_id = iclicker_service::get_current_user_id(); if (isset($current_user_id)) { $cntlr->setHeader(iclicker_controller::SESSION_ID, sesskey()); $cntlr->setHeader('_userId', $current_user_id); } }
* ); * $settings->add( * new admin_setting_configtext('block_iclicker_webservices_username', * get_string('config_webservices_username', $block_name), * get_string('config_webservices_username_desc', $block_name), * '', //iclicker_service::NATIONAL_WS_URL, //50,200 * PARAM_TEXT, * 30 * ) * ); * $settings->add( * new admin_setting_configtext('block_iclicker_webservices_password', * get_string('config_webservices_password', $block_name), * get_string('config_webservices_password_desc', $block_name), * '', //iclicker_service::NATIONAL_WS_URL, //50,200 * PARAM_TEXT, * 30 * ) * ); *******************************************/ // SSO $headerDesc = get_string('config_sso_disabled', $block_name); $currentSSOkey = get_config($block_name, 'block_iclicker_sso_shared_key'); if (!empty($currentSSOkey)) { $headerDesc = get_string('config_sso_enabled', $block_name); $timestamp = time(); $headerDesc .= ' [Sample encoded key: ' . iclicker_service::makeEncodedKey($timestamp) . '|' . $timestamp . ']'; } $settings->add(new admin_setting_heading('block_iclicker_sso_heading', get_string('config_sso', $block_name), $headerDesc)); $settings->add(new admin_setting_configtext(iclicker_service::BLOCK_NAME . '/block_iclicker_sso_shared_key', get_string('config_shared_key', $block_name), get_string('config_shared_key_desc', $block_name), '', PARAM_TEXT, 50)); }
</div> </div> </div> <div class="nav_links"> <?php $reg_link = '<a class="nav_link current_nav_link" href="' . iclicker_service::block_url('registration.php') . '">' . iclicker_service::msg('reg.title') . '</a>'; $nav_links = $reg_link . PHP_EOL; // the other links if (iclicker_service::is_admin()) { $nav_links .= ' | <a class="nav_link" href="' . iclicker_service::block_url('admin.php') . '">' . iclicker_service::msg('admin.title') . '</a>' . PHP_EOL; } else { if (iclicker_service::is_instructor()) { $nav_links .= ' | <a class="nav_link" href="' . iclicker_service::block_url('instructor.php') . '">' . iclicker_service::msg('inst.title') . '</a>' . PHP_EOL; if (iclicker_service::$block_iclicker_sso_enabled) { $nav_links .= ' | <a class="nav_link" href="' . iclicker_service::block_url('instructor_sso.php') . '">' . iclicker_service::msg('inst.sso.title') . '</a>' . PHP_EOL; } } } echo $nav_links; ?> </div> <div class="iclicker_version">Version <?php echo iclicker_service::VERSION; ?> (<?php echo iclicker_service::BLOCK_VERSION; ?> )</div>
function test_save_grades() { global $DB; $this->resetAfterTest(true); // reset all changes automatically after this test $this->setUser($this->instructorid); $test_item_name1 = 'testing-iclicker-item1'; $test_item_name2 = 'testing-iclicker-item2'; $test_item_name3 = 'testing-iclicker-item3'; $gradebook = new stdClass(); // saving a gradebook with no course_id not allowed try { $result = iclicker_service::save_gradebook($gradebook); $this->fail("should have died"); } catch (Exception $e) { $this->assertNotNull($e); } $gradebook->course_id = $this->courseid; $gradebook->items = array(); // saving an empty gradebook not allowed try { $result = iclicker_service::save_gradebook($gradebook); $this->fail("should have died"); } catch (Exception $e) { $this->assertNotNull($e); } // saving one with one valid item $score = new stdClass(); $score->user_id = 1; $score->score = 75.0; $grade_item = new stdClass(); $grade_item->name = $test_item_name1; $grade_item->points_possible = 90; $grade_item->type = iclicker_service::GRADE_CATEGORY_NAME; $grade_item->scores = array(); $grade_item->scores[] = $score; $gradebook->items[] = $grade_item; $result = iclicker_service::save_gradebook($gradebook); $this->assertNotNull($result); $this->assertNotNull($result->course_id); $this->assertNotNull($result->course); $this->assertNotNull($result->default_category_id); $this->assertNotNull($result->items); $this->assertEquals($result->course_id, $this->courseid); $this->assertEquals(count($result->items), 1); $this->assertNotNull($result->items[0]); $this->assertNotNull($result->items[0]->id); $this->assertNotNull($result->items[0]->scores); $this->assertEquals(count($result->items[0]->scores), 1); $this->assertFalse(isset($result->items[0]->errors)); $this->assertEquals($result->items[0]->grademax, 90); $this->assertEquals($result->items[0]->iteminfo, iclicker_service::GRADE_CATEGORY_NAME); $this->assertNotNull($result->items[0]->categoryid); $this->assertEquals($result->items[0]->courseid, $result->course_id); $this->assertEquals($result->items[0]->itemname, $test_item_name1); $this->assertNotNull($result->items[0]->scores[0]); $this->assertFalse(isset($result->items[0]->scores[0]->error)); // saving one with multiple items, some invalid $grade_item->type = 'stuff'; // update category $score->score = 50; // SCORE_UPDATE_ERRORS $score1 = new stdClass(); $score1->user_id = 'xxxxxx'; // USER_DOES_NOT_EXIST_ERROR $score1->score = 80; $grade_item->scores[] = $score1; $score2 = new stdClass(); $score2->user_id = '2'; $score2->score = 101; // POINTS_POSSIBLE_UPDATE_ERRORS $grade_item->scores[] = $score2; $score3 = new stdClass(); $score3->user_id = '3'; $score3->score = 'XX'; // GENERAL_ERRORS $grade_item->scores[] = $score3; $result = iclicker_service::save_gradebook($gradebook); $this->assertNotNull($result); $this->assertNotNull($result->course_id); $this->assertNotNull($result->course); //$this->assertNotNull($result->default_category_id); $this->assertNotNull($result->items); $this->assertEquals($result->course_id, $this->courseid); $this->assertEquals(count($result->items), 1); $this->assertNotNull($result->items[0]); $this->assertNotNull($result->items[0]->id); $this->assertEquals($result->items[0]->iteminfo, 'stuff'); $this->assertNotNull($result->items[0]->scores); $this->assertEquals(count($result->items[0]->scores), 4); $this->assertTrue(isset($result->items[0]->errors)); $this->assertEquals(count($result->items[0]->errors), 4); $this->assertEquals($result->items[0]->grademax, 90); $this->assertNotNull($result->items[0]->categoryid); $this->assertEquals($result->items[0]->courseid, $result->course_id); $this->assertEquals($result->items[0]->itemname, $test_item_name1); $this->assertNotNull($result->items[0]->scores[0]); $this->assertTrue(isset($result->items[0]->scores[0]->error)); $this->assertEquals($result->items[0]->scores[0]->error, iclicker_service::SCORE_UPDATE_ERRORS); $this->assertNotNull($result->items[0]->scores[1]); $this->assertTrue(isset($result->items[0]->scores[1]->error)); $this->assertEquals($result->items[0]->scores[1]->error, iclicker_service::USER_DOES_NOT_EXIST_ERROR); $this->assertNotNull($result->items[0]->scores[2]); $this->assertTrue(isset($result->items[0]->scores[2]->error)); $this->assertEquals($result->items[0]->scores[2]->error, iclicker_service::POINTS_POSSIBLE_UPDATE_ERRORS); $this->assertNotNull($result->items[0]->scores[3]); $this->assertTrue(isset($result->items[0]->scores[3]->error)); $this->assertEquals($result->items[0]->scores[3]->error, 'SCORE_INVALID'); $xml = iclicker_service::encode_gradebook_results($result); $this->assertNotNull($xml); $this->assertTrue(stripos($xml, '<user ') > 0); $this->assertTrue(stripos($xml, '<lineitem ') > 0); $this->assertTrue(stripos($xml, '<error ') > 0); $this->assertTrue(stripos($xml, iclicker_service::SCORE_UPDATE_ERRORS) > 0); $this->assertTrue(stripos($xml, iclicker_service::USER_DOES_NOT_EXIST_ERROR) > 0); $this->assertTrue(stripos($xml, iclicker_service::POINTS_POSSIBLE_UPDATE_ERRORS) > 0); $this->assertTrue(stripos($xml, iclicker_service::GENERAL_ERRORS) > 0); //echo "<xmp>$xml</xmp>"; // Save 1 update and 2 new grades $score->score = 85; $score2->score = 50; $score3->score = 0; $grade_item->scores = array(); $grade_item->scores[] = $score; $grade_item->scores[] = $score2; $grade_item->scores[] = $score3; $result = iclicker_service::save_gradebook($gradebook); $this->assertNotNull($result); $this->assertNotNull($result->course_id); $this->assertNotNull($result->items); $this->assertEquals($result->course_id, $this->courseid); $this->assertEquals(count($result->items), 1); $this->assertNotNull($result->items[0]); $this->assertNotNull($result->items[0]->id); $this->assertNotNull($result->items[0]->scores); $this->assertEquals(count($result->items[0]->scores), 3); $this->assertFalse(isset($result->items[0]->errors)); $this->assertEquals($result->items[0]->grademax, 90); $this->assertNotNull($result->items[0]->scores[0]); $this->assertEquals($result->items[0]->scores[0]->rawgrade, 85); $this->assertNotNull($result->items[0]->scores[1]); $this->assertEquals($result->items[0]->scores[1]->rawgrade, 50); $this->assertNotNull($result->items[0]->scores[2]); $this->assertEquals($result->items[0]->scores[2]->rawgrade, 0); /* echo "<pre>"; var_export($result->items[0]); echo "</pre>"; */ $xml = iclicker_service::encode_gradebook_results($result); $this->assertNull($xml); // no errors // test saving multiple items at once $gradebook->course_id = $this->courseid; $gradebook->items = array(); $grade_item1 = new stdClass(); $grade_item1->name = $test_item_name2; $grade_item1->points_possible = 100; $grade_item1->type = null; // default $grade_item1->scores = array(); $gradebook->items[] = $grade_item1; $grade_item2 = new stdClass(); $grade_item2->name = $test_item_name3; $grade_item2->points_possible = 50; $grade_item2->type = 'stuff'; $grade_item2->scores = array(); $gradebook->items[] = $grade_item2; $score = new stdClass(); $score->user_id = 1; $score->score = 80.0; $grade_item1->scores[] = $score; $score = new stdClass(); $score->user_id = 2; $score->score = 90.0; $grade_item1->scores[] = $score; $score = new stdClass(); $score->user_id = 2; $score->score = 45.0; $grade_item2->scores[] = $score; $score = new stdClass(); $score->user_id = 3; $score->score = 40.0; $grade_item2->scores[] = $score; $result = iclicker_service::save_gradebook($gradebook); $this->assertNotNull($result); $this->assertNotNull($result->course_id); $this->assertNotNull($result->items); $this->assertNotNull($result->default_category_id); $this->assertEquals($result->course_id, $this->courseid); $this->assertEquals(count($result->items), 2); $this->assertNotNull($result->items[0]); $this->assertNotNull($result->items[0]->id); $this->assertNotNull($result->items[0]->scores); $this->assertEquals(count($result->items[0]->scores), 2); $this->assertFalse(isset($result->items[0]->errors)); $this->assertEquals($result->items[0]->grademax, 100); $this->assertNotNull($result->items[0]->scores[0]); $this->assertEquals($result->items[0]->scores[0]->rawgrade, 80); $this->assertNotNull($result->items[0]->scores[1]); $this->assertEquals($result->items[0]->scores[1]->rawgrade, 90); $this->assertNotNull($result->items[1]); $this->assertNotNull($result->items[1]->id); $this->assertNotNull($result->items[1]->scores); $this->assertEquals(count($result->items[1]->scores), 2); $this->assertFalse(isset($result->items[1]->errors)); $this->assertEquals($result->items[1]->grademax, 50); $this->assertNotNull($result->items[1]->scores[0]); $this->assertEquals($result->items[1]->scores[0]->rawgrade, 45); $this->assertNotNull($result->items[1]->scores[1]); $this->assertEquals($result->items[1]->scores[1]->rawgrade, 40); $xml = iclicker_service::encode_gradebook_results($result); $this->assertNull($xml); }
/** * Execute this method when the cron runs * * @return bool */ function cron() { $results = iclicker_service::ws_sync_all(); mtrace(' National WS sync...', ''); if (!$results) { mtrace(' DISABLED. '); } else { $error_num = count($results['errors']); mtrace(' completed syncing ' . $results['total'] . ' registrations (' . $results['national'] . ' national, ' . $results['local'] . ' local) with ' . $error_num . ' errors. '); if ($error_num > 0) { $count = 0; foreach ($results['errors'] as $error) { $count++; mtrace(' ' . $count . ': ' . $error); } } } return true; }