|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 00037 class quiz_access_manager { 00039 protected $quizobj; 00041 protected $timenow; 00043 protected $rules = array(); 00044 00053 public function __construct($quizobj, $timenow, $canignoretimelimits) { 00054 $this->quizobj = $quizobj; 00055 $this->timenow = $timenow; 00056 $this->rules = $this->make_rules($quizobj, $timenow, $canignoretimelimits); 00057 } 00058 00067 protected function make_rules($quizobj, $timenow, $canignoretimelimits) { 00068 00069 $rules = array(); 00070 foreach (self::get_rule_classes() as $ruleclass) { 00071 $rule = $ruleclass::make($quizobj, $timenow, $canignoretimelimits); 00072 if ($rule) { 00073 $rules[$ruleclass] = $rule; 00074 } 00075 } 00076 00077 $superceededrules = array(); 00078 foreach ($rules as $rule) { 00079 $superceededrules += $rule->get_superceded_rules(); 00080 } 00081 00082 foreach ($superceededrules as $superceededrule) { 00083 unset($rules['quizaccess_' . $superceededrule]); 00084 } 00085 00086 return $rules; 00087 } 00088 00092 protected static function get_rule_classes() { 00093 return get_plugin_list_with_class('quizaccess', '', 'rule.php'); 00094 } 00095 00105 public static function add_settings_form_fields( 00106 mod_quiz_mod_form $quizform, MoodleQuickForm $mform) { 00107 00108 foreach (self::get_rule_classes() as $rule) { 00109 $rule::add_settings_form_fields($quizform, $mform); 00110 } 00111 } 00112 00118 public static function get_browser_security_choices() { 00119 $options = array('-' => get_string('none', 'quiz')); 00120 foreach (self::get_rule_classes() as $rule) { 00121 $options += $rule::get_browser_security_choices(); 00122 } 00123 return $options; 00124 } 00125 00135 public static function save_settings($quiz) { 00136 00137 foreach (self::get_rule_classes() as $rule) { 00138 $rule::save_settings($quiz); 00139 } 00140 } 00141 00150 protected static function get_load_sql($quizid, $rules, $basefields) { 00151 $allfields = $basefields; 00152 $alljoins = '{quiz} quiz'; 00153 $allparams = array('quizid' => $quizid); 00154 00155 foreach ($rules as $rule) { 00156 list($fields, $joins, $params) = $rule::get_settings_sql($quizid); 00157 if ($fields) { 00158 if ($allfields) { 00159 $allfields .= ', '; 00160 } 00161 $allfields .= $fields; 00162 } 00163 if ($joins) { 00164 $alljoins .= ' ' . $joins; 00165 } 00166 if ($params) { 00167 $allparams += $params; 00168 } 00169 } 00170 00171 if ($allfields === '') { 00172 return array('', array()); 00173 } 00174 00175 return array("SELECT $allfields FROM $alljoins WHERE quiz.id = :quizid", $allparams); 00176 } 00177 00189 public static function load_settings($quizid) { 00190 global $DB; 00191 00192 $rules = self::get_rule_classes(); 00193 list($sql, $params) = self::get_load_sql($quizid, $rules, ''); 00194 00195 if ($sql) { 00196 $data = (array) $DB->get_record_sql($sql, $params); 00197 } else { 00198 $data = array(); 00199 } 00200 00201 foreach ($rules as $rule) { 00202 $data += $rule::get_extra_settings($quizid); 00203 } 00204 00205 return $data; 00206 } 00207 00218 public static function load_quiz_and_settings($quizid) { 00219 global $DB; 00220 00221 $rules = self::get_rule_classes(); 00222 list($sql, $params) = self::get_load_sql($quizid, $rules, 'quiz.*'); 00223 $quiz = $DB->get_record_sql($sql, $params, MUST_EXIST); 00224 00225 foreach ($rules as $rule) { 00226 foreach ($rule::get_extra_settings($quizid) as $name => $value) { 00227 $quiz->$name = $value; 00228 } 00229 } 00230 00231 return $quiz; 00232 } 00233 00238 public function get_active_rule_names() { 00239 $classnames = array(); 00240 foreach ($this->rules as $rule) { 00241 $classnames[] = get_class($rule); 00242 } 00243 return $classnames; 00244 } 00245 00252 protected function accumulate_messages($messages, $new) { 00253 if (is_array($new)) { 00254 $messages = array_merge($messages, $new); 00255 } else if (is_string($new) && $new) { 00256 $messages[] = $new; 00257 } 00258 return $messages; 00259 } 00260 00269 public function describe_rules() { 00270 $result = array(); 00271 foreach ($this->rules as $rule) { 00272 $result = $this->accumulate_messages($result, $rule->description()); 00273 } 00274 return $result; 00275 } 00276 00288 public function prevent_new_attempt($numprevattempts, $lastattempt) { 00289 $reasons = array(); 00290 foreach ($this->rules as $rule) { 00291 $reasons = $this->accumulate_messages($reasons, 00292 $rule->prevent_new_attempt($numprevattempts, $lastattempt)); 00293 } 00294 return $reasons; 00295 } 00296 00305 public function prevent_access() { 00306 $reasons = array(); 00307 foreach ($this->rules as $rule) { 00308 $reasons = $this->accumulate_messages($reasons, $rule->prevent_access()); 00309 } 00310 return $reasons; 00311 } 00312 00319 public function is_preflight_check_required($attemptid) { 00320 foreach ($this->rules as $rule) { 00321 if ($rule->is_preflight_check_required($attemptid)) { 00322 return true; 00323 } 00324 } 00325 return false; 00326 } 00327 00335 public function get_preflight_check_form(moodle_url $url, $attemptid) { 00336 return new mod_quiz_preflight_check_form($url->out_omit_querystring(), 00337 array('rules' => $this->rules, 'quizobj' => $this->quizobj, 00338 'attemptid' => $attemptid, 'hidden' => $url->params())); 00339 } 00340 00347 public function notify_preflight_check_passed($attemptid) { 00348 foreach ($this->rules as $rule) { 00349 $rule->notify_preflight_check_passed($attemptid); 00350 } 00351 } 00352 00357 public function current_attempt_finished() { 00358 foreach ($this->rules as $rule) { 00359 $rule->current_attempt_finished(); 00360 } 00361 } 00362 00373 public function is_finished($numprevattempts, $lastattempt) { 00374 foreach ($this->rules as $rule) { 00375 if ($rule->is_finished($numprevattempts, $lastattempt)) { 00376 return true; 00377 } 00378 } 00379 return false; 00380 } 00381 00388 public function setup_attempt_page($page) { 00389 foreach ($this->rules as $rule) { 00390 $rule->setup_attempt_page($page); 00391 } 00392 } 00393 00402 public function show_attempt_timer_if_needed($attempt, $timenow, $output) { 00403 00404 $timeleft = false; 00405 foreach ($this->rules as $rule) { 00406 $ruletimeleft = $rule->time_left($attempt, $timenow); 00407 if ($ruletimeleft !== false && ($timeleft === false || $ruletimeleft < $timeleft)) { 00408 $timeleft = $ruletimeleft; 00409 } 00410 } 00411 00412 if ($timeleft !== false) { 00413 // Make sure the timer starts just above zero. If $timeleft was <= 0, then 00414 // this will just have the effect of causing the quiz to be submitted immediately. 00415 $timerstartvalue = max($timeleft, 1); 00416 $output->initialise_timer($timerstartvalue); 00417 } 00418 } 00419 00423 public function attempt_must_be_in_popup() { 00424 foreach ($this->rules as $rule) { 00425 if ($rule->attempt_must_be_in_popup()) { 00426 return true; 00427 } 00428 } 00429 return false; 00430 } 00431 00436 public function get_popup_options() { 00437 $options = array(); 00438 foreach ($this->rules as $rule) { 00439 $options += $rule->get_popup_options(); 00440 } 00441 return $options; 00442 } 00443 00453 public function back_to_view_page($output, $message = '') { 00454 if ($this->attempt_must_be_in_popup()) { 00455 echo $output->close_attempt_popup($message, $this->quizobj->view_url()); 00456 die(); 00457 } else { 00458 redirect($this->quizobj->view_url(), $message); 00459 } 00460 } 00461 00470 public function make_review_link($attempt, $reviewoptions, $output) { 00471 00472 // If review of responses is not allowed, or the attempt is still open, don't link. 00473 if (!$attempt->timefinish) { 00474 return $output->no_review_message(''); 00475 } 00476 00477 $when = quiz_attempt_state($this->quizobj->get_quiz(), $attempt); 00478 $reviewoptions = mod_quiz_display_options::make_from_quiz( 00479 $this->quizobj->get_quiz(), $when); 00480 00481 if (!$reviewoptions->attempt) { 00482 return $output->no_review_message($this->quizobj->cannot_review_message($when, true)); 00483 00484 } else { 00485 return $output->review_link($this->quizobj->review_url($attempt->id), 00486 $this->attempt_must_be_in_popup(), $this->get_popup_options()); 00487 } 00488 } 00489 }