/* $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;
 }