From fcc20627b4689b76462c074938ecb7aa69eecbaf Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 10 Jan 2023 11:41:33 +0800 Subject: [PATCH 1/1] MDL-76614 phpcbf --- .../accessrule/delaybetweenattempts/rule.php | 13 +- mod/quiz/accessrule/numattempts/rule.php | 1 - mod/quiz/accessrule/offlineattempts/rule.php | 54 +- mod/quiz/accessrule/password/rule.php | 26 +- mod/quiz/accessrule/seb/rule.php | 72 ++- mod/quiz/accessrule/securewindow/rule.php | 18 +- mod/quiz/accessrule/timelimit/rule.php | 30 +- mod/quiz/classes/access_manager.php | 52 +- mod/quiz/classes/form/add_random_form.php | 59 +- mod/quiz/classes/form/edit_override_form.php | 115 +++- .../classes/form/preflight_check_form.php | 16 +- mod/quiz/classes/local/access_rule_base.php | 24 +- .../output/navigation_panel_attempt.php | 14 +- .../classes/output/navigation_panel_base.php | 19 +- .../output/navigation_panel_review.php | 12 +- .../output/navigation_question_button.php | 3 +- mod/quiz/classes/output/renderer.php | 601 ++++++++++++------ mod/quiz/classes/output/view_page.php | 10 +- mod/quiz/classes/quiz_attempt.php | 295 ++++++--- mod/quiz/classes/quiz_settings.php | 56 +- .../classes/task/update_overdue_attempts.php | 24 +- mod/quiz/deprecatedlib.php | 9 +- mod/quiz/tests/attempts_test.php | 12 +- 23 files changed, 1022 insertions(+), 513 deletions(-) diff --git a/mod/quiz/accessrule/delaybetweenattempts/rule.php b/mod/quiz/accessrule/delaybetweenattempts/rule.php index f2cf9d1f1f..3d60e8d53f 100644 --- a/mod/quiz/accessrule/delaybetweenattempts/rule.php +++ b/mod/quiz/accessrule/delaybetweenattempts/rule.php @@ -46,8 +46,11 @@ class quizaccess_delaybetweenattempts extends access_rule_base { $nextstarttime = $this->compute_next_start_time($numprevattempts, $lastattempt); if ($this->timenow < $nextstarttime) { if ($this->quiz->timeclose == 0 || $nextstarttime <= $this->quiz->timeclose) { - return get_string('youmustwait', 'quizaccess_delaybetweenattempts', - userdate($nextstarttime)); + return get_string( + 'youmustwait', + 'quizaccess_delaybetweenattempts', + userdate($nextstarttime) + ); } else { return get_string('youcannotwait', 'quizaccess_delaybetweenattempts'); } @@ -69,8 +72,10 @@ class quizaccess_delaybetweenattempts extends access_rule_base { $lastattemptfinish = $lastattempt->timefinish; if ($this->quiz->timelimit > 0) { - $lastattemptfinish = min($lastattemptfinish, - $lastattempt->timestart + $this->quiz->timelimit); + $lastattemptfinish = min( + $lastattemptfinish, + $lastattempt->timestart + $this->quiz->timelimit + ); } if ($numprevattempts == 1 && $this->quiz->delay1) { diff --git a/mod/quiz/accessrule/numattempts/rule.php b/mod/quiz/accessrule/numattempts/rule.php index 3c87006e4d..a5581c8c19 100644 --- a/mod/quiz/accessrule/numattempts/rule.php +++ b/mod/quiz/accessrule/numattempts/rule.php @@ -27,7 +27,6 @@ use mod_quiz\quiz_settings; class quizaccess_numattempts extends access_rule_base { public static function make(quiz_settings $quizobj, $timenow, $canignoretimelimits) { - if ($quizobj->get_num_attempts_allowed() == 0) { return null; } diff --git a/mod/quiz/accessrule/offlineattempts/rule.php b/mod/quiz/accessrule/offlineattempts/rule.php index aaa3fe0053..a12a09605d 100644 --- a/mod/quiz/accessrule/offlineattempts/rule.php +++ b/mod/quiz/accessrule/offlineattempts/rule.php @@ -44,7 +44,7 @@ class quizaccess_offlineattempts extends access_rule_base { // First, check if the user did something offline. if (!empty($attemptid)) { - $timemodifiedoffline = $DB->get_field('quiz_attempts', 'timemodifiedoffline', array('id' => $attemptid)); + $timemodifiedoffline = $DB->get_field('quiz_attempts', 'timemodifiedoffline', ['id' => $attemptid]); if (empty($timemodifiedoffline)) { return false; } @@ -55,22 +55,32 @@ class quizaccess_offlineattempts extends access_rule_base { } } - public function add_preflight_check_form_fields(preflight_check_form $quizform, - MoodleQuickForm $mform, $attemptid) { + public function add_preflight_check_form_fields( + preflight_check_form $quizform, + MoodleQuickForm $mform, + $attemptid + ) { global $DB; - $timemodifiedoffline = $DB->get_field('quiz_attempts', 'timemodifiedoffline', array('id' => $attemptid)); + $timemodifiedoffline = $DB->get_field('quiz_attempts', 'timemodifiedoffline', ['id' => $attemptid]); $lasttime = format_time(time() - $timemodifiedoffline); $mform->addElement('header', 'offlineattemptsheader', get_string('mobileapp', 'quizaccess_offlineattempts')); - $mform->addElement('static', 'offlinedatamessage', '', - get_string('offlinedatamessage', 'quizaccess_offlineattempts', $lasttime)); - $mform->addElement('advcheckbox', 'confirmdatasaved', null, - get_string('confirmdatasaved', 'quizaccess_offlineattempts')); + $mform->addElement( + 'static', + 'offlinedatamessage', + '', + get_string('offlinedatamessage', 'quizaccess_offlineattempts', $lasttime) + ); + $mform->addElement( + 'advcheckbox', + 'confirmdatasaved', + null, + get_string('confirmdatasaved', 'quizaccess_offlineattempts') + ); } public function validate_preflight_check($data, $files, $errors, $attemptid) { - // The user confirmed that he doesn't have unsaved work. if (!empty($data['confirmdatasaved'])) { return $errors; @@ -94,13 +104,18 @@ class quizaccess_offlineattempts extends access_rule_base { } public static function add_settings_form_fields( - mod_quiz_mod_form $quizform, MoodleQuickForm $mform) { + mod_quiz_mod_form $quizform, + MoodleQuickForm $mform + ) { global $CFG; // Allow to enable the access rule only if the Mobile services are enabled. if ($CFG->enablemobilewebservice) { - $mform->addElement('selectyesno', 'allowofflineattempts', - get_string('allowofflineattempts', 'quizaccess_offlineattempts')); + $mform->addElement( + 'selectyesno', + 'allowofflineattempts', + get_string('allowofflineattempts', 'quizaccess_offlineattempts') + ); $mform->addHelpButton('allowofflineattempts', 'allowofflineattempts', 'quizaccess_offlineattempts'); $mform->setDefault('allowofflineattempts', 0); $mform->setAdvanced('allowofflineattempts'); @@ -109,8 +124,12 @@ class quizaccess_offlineattempts extends access_rule_base { } } - public static function validate_settings_form_fields(array $errors, - array $data, $files, mod_quiz_mod_form $quizform) { + public static function validate_settings_form_fields( + array $errors, + array $data, + $files, + mod_quiz_mod_form $quizform + ) { global $CFG; if ($CFG->enablemobilewebservice) { @@ -118,10 +137,11 @@ class quizaccess_offlineattempts extends access_rule_base { // - The quiz uses a timer. // - The quiz is restricted by subnet. // - The question behaviour is not deferred feedback or deferred feedback with CBM. - if (!empty($data['allowofflineattempts']) and + if ( + !empty($data['allowofflineattempts']) and (!empty($data['timelimit']) or !empty($data['subnet']) or - ($data['preferredbehaviour'] != 'deferredfeedback' and $data['preferredbehaviour'] != 'deferredcbm'))) { - + ($data['preferredbehaviour'] != 'deferredfeedback' and $data['preferredbehaviour'] != 'deferredcbm')) + ) { $errors['allowofflineattempts'] = get_string('offlineattemptserror', 'quizaccess_offlineattempts'); } } diff --git a/mod/quiz/accessrule/password/rule.php b/mod/quiz/accessrule/password/rule.php index 956fc7b836..015374b6ab 100644 --- a/mod/quiz/accessrule/password/rule.php +++ b/mod/quiz/accessrule/password/rule.php @@ -44,25 +44,33 @@ class quizaccess_password extends access_rule_base { return empty($SESSION->passwordcheckedquizzes[$this->quiz->id]); } - public function add_preflight_check_form_fields(preflight_check_form $quizform, - MoodleQuickForm $mform, $attemptid) { - + public function add_preflight_check_form_fields( + preflight_check_form $quizform, + MoodleQuickForm $mform, + $attemptid + ) { $mform->addElement('header', 'passwordheader', get_string('password')); - $mform->addElement('static', 'passwordmessage', '', - get_string('requirepasswordmessage', 'quizaccess_password')); + $mform->addElement( + 'static', + 'passwordmessage', + '', + get_string('requirepasswordmessage', 'quizaccess_password') + ); // Don't use the 'proper' field name of 'password' since that get's // Firefox's password auto-complete over-excited. - $mform->addElement('password', 'quizpassword', - get_string('quizpassword', 'quizaccess_password'), array('autofocus' => 'true')); + $mform->addElement( + 'password', + 'quizpassword', + get_string('quizpassword', 'quizaccess_password'), + ['autofocus' => 'true'] + ); } public function validate_preflight_check($data, $files, $errors, $attemptid) { - $enteredpassword = $data['quizpassword']; if (strcmp($this->quiz->password, $enteredpassword) === 0) { return $errors; // Password is OK. - } else if (isset($this->quiz->extrapasswords)) { // Group overrides may have additional passwords. foreach ($this->quiz->extrapasswords as $password) { diff --git a/mod/quiz/accessrule/seb/rule.php b/mod/quiz/accessrule/seb/rule.php index 3c4e02aa7f..268d25e1a8 100644 --- a/mod/quiz/accessrule/seb/rule.php +++ b/mod/quiz/accessrule/seb/rule.php @@ -16,10 +16,10 @@ use mod_quiz\local\access_rule_base; use mod_quiz\quiz_attempt; +use quizaccess_seb\event\access_prevented; use quizaccess_seb\seb_access_manager; use quizaccess_seb\seb_quiz_settings; use quizaccess_seb\settings_provider; -use quizaccess_seb\event\access_prevented; /** * Implementation of the quizaccess_seb plugin. @@ -88,9 +88,12 @@ class quizaccess_seb extends access_rule_base { * @param mod_quiz_mod_form $quizform the quiz form object. * @return array $errors the updated $errors array. */ - public static function validate_settings_form_fields(array $errors, - array $data, $files, mod_quiz_mod_form $quizform) : array { - + public static function validate_settings_form_fields( + array $errors, + array $data, + $files, + mod_quiz_mod_form $quizform + ): array { $quizid = $data['instance']; $cmid = $data['coursemodule']; $context = $quizform->get_context(); @@ -235,9 +238,9 @@ class quizaccess_seb extends access_rule_base { * used named placeholders, and the placeholder names should start with the * plugin name, to avoid collisions. */ - public static function get_settings_sql($quizid) : array { + public static function get_settings_sql($quizid): array { return [ - 'seb.requiresafeexambrowser AS seb_requiresafeexambrowser, ' + 'seb.requiresafeexambrowser AS seb_requiresafeexambrowser, ' . 'seb.showsebtaskbar AS seb_showsebtaskbar, ' . 'seb.showwificontrol AS seb_showwificontrol, ' . 'seb.showreloadbutton AS seb_showreloadbutton, ' @@ -259,10 +262,8 @@ class quizaccess_seb extends access_rule_base { . 'seb.regexblocked AS seb_regexblocked, ' . 'seb.allowedbrowserexamkeys AS seb_allowedbrowserexamkeys, ' . 'seb.showsebdownloadlink AS seb_showsebdownloadlink, ' - . 'sebtemplate.id AS seb_templateid ' - , 'LEFT JOIN {quizaccess_seb_quizsettings} seb ON seb.quizid = quiz.id ' - . 'LEFT JOIN {quizaccess_seb_template} sebtemplate ON seb.templateid = sebtemplate.id ' - , [] + . 'sebtemplate.id AS seb_templateid ', 'LEFT JOIN {quizaccess_seb_quizsettings} seb ON seb.quizid = quiz.id ' + . 'LEFT JOIN {quizaccess_seb_template} sebtemplate ON seb.templateid = sebtemplate.id ', [], ]; } @@ -323,7 +324,7 @@ class quizaccess_seb extends access_rule_base { * * @return array */ - private function get_user_finished_attempts() : array { + private function get_user_finished_attempts(): array { global $USER; return quiz_get_user_attempts( @@ -361,7 +362,7 @@ class quizaccess_seb extends access_rule_base { * @param string $identifier Reason string identifier. * @return string */ - private function get_reason_text(string $identifier) : string { + private function get_reason_text(string $identifier): string { if (in_array($identifier, ['not_seb', 'invalid_config_key', 'invalid_browser_key'])) { return get_string($identifier, 'quizaccess_seb'); } @@ -374,7 +375,7 @@ class quizaccess_seb extends access_rule_base { * * @return string */ - private function get_invalid_key_error_message() : string { + private function get_invalid_key_error_message(): string { // Return error message with download link and links to get the seb config. return get_string('invalidkeys', 'quizaccess_seb') . $this->display_buttons($this->get_action_buttons()); @@ -385,7 +386,7 @@ class quizaccess_seb extends access_rule_base { * * @return string */ - private function get_require_seb_error_message() : string { + private function get_require_seb_error_message(): string { $message = get_string('clientrequiresseb', 'quizaccess_seb'); if ($this->should_display_download_seb_link()) { @@ -401,7 +402,7 @@ class quizaccess_seb extends access_rule_base { * * @return string empty or a button which has the configured seb quit link. */ - private function get_quit_button() : string { + private function get_quit_button(): string { $quitbutton = ''; if (empty($this->get_user_finished_attempts())) { @@ -428,7 +429,7 @@ class quizaccess_seb extends access_rule_base { * @return mixed a message, or array of messages, explaining the restriction * (may be '' if no message is appropriate). */ - public function description() : array { + public function description(): array { global $PAGE; $messages = [get_string('sebrequired', 'quizaccess_seb')]; @@ -442,8 +443,11 @@ class quizaccess_seb extends access_rule_base { if (!$this->prevent_access()) { $messages[] = $this->display_buttons($this->get_quit_button()); } else { - $PAGE->requires->js_call_amd('quizaccess_seb/validate_quiz_access', 'init', - [$this->quiz->cmid, (bool)get_config('quizaccess_seb', 'autoreconfigureseb')]); + $PAGE->requires->js_call_amd( + 'quizaccess_seb/validate_quiz_access', + 'init', + [$this->quiz->cmid, (bool) get_config('quizaccess_seb', 'autoreconfigureseb')] + ); } return $messages; @@ -478,7 +482,7 @@ class quizaccess_seb extends access_rule_base { * * @return string HTML code of the provided buttons. */ - private function display_buttons(string $buttonshtml, $class = '', array $attributes = null) : string { + private function display_buttons(string $buttonshtml, $class = '', array $attributes = null): string { $html = ''; if (!empty($buttonshtml)) { @@ -493,7 +497,7 @@ class quizaccess_seb extends access_rule_base { * * @return string Html block of all action buttons. */ - private function get_action_buttons() : string { + private function get_action_buttons(): string { $buttons = ''; if ($this->should_display_download_seb_link()) { @@ -522,7 +526,7 @@ class quizaccess_seb extends access_rule_base { * * @return string A link to download SafeExam Browser. */ - private function get_download_seb_button() : string { + private function get_download_seb_button(): string { global $OUTPUT; $button = ''; @@ -539,13 +543,16 @@ class quizaccess_seb extends access_rule_base { * * @return string A link to launch Safe Exam Browser. */ - private function get_launch_seb_button() : string { + private function get_launch_seb_button(): string { // Rendering as a href and not as button in a form to circumvent browser warnings for sending to URL with unknown protocol. $seblink = \quizaccess_seb\link_generator::get_link($this->quiz->cmid, true, is_https()); - $buttonlink = html_writer::start_tag('div', array('class' => 'singlebutton')); - $buttonlink .= html_writer::link($seblink, get_string('seblinkbutton', 'quizaccess_seb'), - ['class' => 'btn btn-secondary', 'title' => get_string('seblinkbutton', 'quizaccess_seb')]); + $buttonlink = html_writer::start_tag('div', ['class' => 'singlebutton']); + $buttonlink .= html_writer::link( + $seblink, + get_string('seblinkbutton', 'quizaccess_seb'), + ['class' => 'btn btn-secondary', 'title' => get_string('seblinkbutton', 'quizaccess_seb')] + ); $buttonlink .= html_writer::end_tag('div'); return $buttonlink; @@ -556,13 +563,16 @@ class quizaccess_seb extends access_rule_base { * * @return string A link to launch Safe Exam Browser. */ - private function get_download_config_button() : string { + private function get_download_config_button(): string { // Rendering as a href and not as button in a form to circumvent browser warnings for sending to URL with unknown protocol. $httplink = \quizaccess_seb\link_generator::get_link($this->quiz->cmid, false, is_https()); - $buttonlink = html_writer::start_tag('div', array('class' => 'singlebutton')); - $buttonlink .= html_writer::link($httplink, get_string('httplinkbutton', 'quizaccess_seb'), - ['class' => 'btn btn-secondary', 'title' => get_string('httplinkbutton', 'quizaccess_seb')]); + $buttonlink = html_writer::start_tag('div', ['class' => 'singlebutton']); + $buttonlink .= html_writer::link( + $httplink, + get_string('httplinkbutton', 'quizaccess_seb'), + ['class' => 'btn btn-secondary', 'title' => get_string('httplinkbutton', 'quizaccess_seb')] + ); $buttonlink .= html_writer::end_tag('div'); return $buttonlink; @@ -573,7 +583,7 @@ class quizaccess_seb extends access_rule_base { * * @return string */ - private function get_seb_download_url() : string { + private function get_seb_download_url(): string { return get_config('quizaccess_seb', 'downloadlink'); } @@ -582,7 +592,7 @@ class quizaccess_seb extends access_rule_base { * * @return bool */ - private function should_display_download_seb_link() : bool { + private function should_display_download_seb_link(): bool { return !empty($this->quiz->seb_showsebdownloadlink); } } diff --git a/mod/quiz/accessrule/securewindow/rule.php b/mod/quiz/accessrule/securewindow/rule.php index 6aa636b6b8..377028d084 100644 --- a/mod/quiz/accessrule/securewindow/rule.php +++ b/mod/quiz/accessrule/securewindow/rule.php @@ -27,7 +27,7 @@ use mod_quiz\quiz_settings; */ class quizaccess_securewindow extends access_rule_base { /** @var array options that should be used for opening the secure popup. */ - protected static $popupoptions = array( + protected static $popupoptions = [ 'left' => 0, 'top' => 0, 'fullscreen' => true, @@ -39,10 +39,9 @@ class quizaccess_securewindow extends access_rule_base { 'location' => false, 'status' => false, 'menubar' => false, - ); + ]; public static function make(quiz_settings $quizobj, $timenow, $canignoretimelimits) { - if ($quizobj->get_quiz()->browsersecurity !== 'securewindow') { return null; } @@ -68,8 +67,12 @@ class quizaccess_securewindow extends access_rule_base { } $page->add_body_class('quiz-secure-window'); - $page->requires->js_init_call('M.mod_quiz.secure_window.init', - null, false, quiz_get_js_module()); + $page->requires->js_init_call( + 'M.mod_quiz.secure_window.init', + null, + false, + quiz_get_js_module() + ); } /** @@ -77,7 +80,8 @@ class quizaccess_securewindow extends access_rule_base { * security settings menu. */ public static function get_browser_security_choices() { - return array('securewindow' => - get_string('popupwithjavascriptsupport', 'quizaccess_securewindow')); + return [ + 'securewindow' => get_string('popupwithjavascriptsupport', 'quizaccess_securewindow'), + ]; } } diff --git a/mod/quiz/accessrule/timelimit/rule.php b/mod/quiz/accessrule/timelimit/rule.php index 610c384a4a..78c8106ec5 100644 --- a/mod/quiz/accessrule/timelimit/rule.php +++ b/mod/quiz/accessrule/timelimit/rule.php @@ -31,7 +31,6 @@ use mod_quiz\quiz_settings; class quizaccess_timelimit extends access_rule_base { public static function make(quiz_settings $quizobj, $timenow, $canignoretimelimits) { - if (empty($quizobj->get_quiz()->timelimit) || $canignoretimelimits) { return null; } @@ -40,8 +39,11 @@ class quizaccess_timelimit extends access_rule_base { } public function description() { - return get_string('quiztimelimit', 'quizaccess_timelimit', - format_time($this->quiz->timelimit)); + return get_string( + 'quiztimelimit', + 'quizaccess_timelimit', + format_time($this->quiz->timelimit) + ); } public function end_time($attempt) { @@ -66,11 +68,21 @@ class quizaccess_timelimit extends access_rule_base { return $attemptid === null; } - public function add_preflight_check_form_fields(preflight_check_form $quizform, - MoodleQuickForm $mform, $attemptid) { - $mform->addElement('header', 'honestycheckheader', - get_string('confirmstartheader', 'quizaccess_timelimit')); - $mform->addElement('static', 'honestycheckmessage', '', - get_string('confirmstart', 'quizaccess_timelimit', format_time($this->quiz->timelimit))); + public function add_preflight_check_form_fields( + preflight_check_form $quizform, + MoodleQuickForm $mform, + $attemptid + ) { + $mform->addElement( + 'header', + 'honestycheckheader', + get_string('confirmstartheader', 'quizaccess_timelimit') + ); + $mform->addElement( + 'static', + 'honestycheckmessage', + '', + get_string('confirmstart', 'quizaccess_timelimit', format_time($this->quiz->timelimit)) + ); } } diff --git a/mod/quiz/classes/access_manager.php b/mod/quiz/classes/access_manager.php index 7e4ddb9e0a..246f01fad4 100644 --- a/mod/quiz/classes/access_manager.php +++ b/mod/quiz/classes/access_manager.php @@ -18,10 +18,9 @@ namespace mod_quiz; use core_component; use mod_quiz\form\preflight_check_form; -use mod_quiz\local\access_rule_base; +use mod_quiz\output\renderer; use mod_quiz\question\display_options; use mod_quiz_mod_form; -use mod_quiz\output\renderer; use moodle_page; use moodle_url; use MoodleQuickForm; @@ -73,7 +72,6 @@ class access_manager { * @return access_rule_base[] rules that apply to this quiz. */ protected function make_rules(quiz_settings $quizobj, int $timenow, bool $canignoretimelimits): array { - $rules = []; foreach (self::get_rule_classes() as $ruleclass) { $rule = $ruleclass::make($quizobj, $timenow, $canignoretimelimits); @@ -113,8 +111,9 @@ class access_manager { * @param MoodleQuickForm $mform the wrapped MoodleQuickForm. */ public static function add_settings_form_fields( - mod_quiz_mod_form $quizform, MoodleQuickForm $mform): void { - + mod_quiz_mod_form $quizform, + MoodleQuickForm $mform + ): void { foreach (self::get_rule_classes() as $rule) { $rule::add_settings_form_fields($quizform, $mform); } @@ -142,9 +141,12 @@ class access_manager { * @param mod_quiz_mod_form $quizform the quiz form object. * @return array $errors the updated $errors array. */ - public static function validate_settings_form_fields(array $errors, - array $data, array $files, mod_quiz_mod_form $quizform): array { - + public static function validate_settings_form_fields( + array $errors, + array $data, + array $files, + mod_quiz_mod_form $quizform + ): array { foreach (self::get_rule_classes() as $rule) { $errors = $rule::validate_settings_form_fields($errors, $data, $files, $quizform); } @@ -162,7 +164,6 @@ class access_manager { * which is the id of the quiz being saved. */ public static function save_settings(stdClass $quiz): void { - foreach (self::get_rule_classes() as $rule) { $rule::save_settings($quiz); } @@ -179,7 +180,6 @@ class access_manager { * @since Moodle 2.7.1, 2.6.4, 2.5.7 */ public static function delete_settings(stdClass $quiz): void { - foreach (self::get_rule_classes() as $rule) { $rule::delete_settings($quiz); } @@ -340,8 +340,10 @@ class access_manager { public function prevent_new_attempt(int $numprevattempts, $lastattempt): array { $reasons = []; foreach ($this->rules as $rule) { - $reasons = $this->accumulate_messages($reasons, - $rule->prevent_new_attempt($numprevattempts, $lastattempt)); + $reasons = $this->accumulate_messages( + $reasons, + $rule->prevent_new_attempt($numprevattempts, $lastattempt) + ); } return $reasons; } @@ -393,9 +395,16 @@ class access_manager { if (!empty($_GET['_qf__preflight_check_form'])) { $method = 'get'; } - return new preflight_check_form($url->out_omit_querystring(), - ['rules' => $this->rules, 'quizobj' => $this->quizobj, - 'attemptid' => $attemptid, 'hidden' => $url->params()], $method); + return new preflight_check_form( + $url->out_omit_querystring(), + [ + 'rules' => $this->rules, + 'quizobj' => $this->quizobj, + 'attemptid' => $attemptid, + 'hidden' => $url->params(), + ], + $method + ); } /** @@ -545,7 +554,6 @@ class access_manager { * link to the review page. */ public function make_review_link(stdClass $attempt, $nolongerused, renderer $output): string { - // If the attempt is still open, don't link. if (in_array($attempt->state, [quiz_attempt::IN_PROGRESS, quiz_attempt::OVERDUE])) { return $output->no_review_message(''); @@ -553,14 +561,18 @@ class access_manager { $when = quiz_attempt_state($this->quizobj->get_quiz(), $attempt); $reviewoptions = display_options::make_from_quiz( - $this->quizobj->get_quiz(), $when); + $this->quizobj->get_quiz(), + $when + ); if (!$reviewoptions->attempt) { return $output->no_review_message($this->quizobj->cannot_review_message($when, true)); - } else { - return $output->review_link($this->quizobj->review_url($attempt->id), - $this->attempt_must_be_in_popup(), $this->get_popup_options()); + return $output->review_link( + $this->quizobj->review_url($attempt->id), + $this->attempt_must_be_in_popup(), + $this->get_popup_options() + ); } } diff --git a/mod/quiz/classes/form/add_random_form.php b/mod/quiz/classes/form/add_random_form.php index 2498abb0e2..3eccaf750c 100644 --- a/mod/quiz/classes/form/add_random_form.php +++ b/mod/quiz/classes/form/add_random_form.php @@ -21,7 +21,7 @@ use moodleform; defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->libdir . '/formslib.php'); /** @@ -43,11 +43,18 @@ class add_random_form extends moodleform { $usablecontexts = $contexts->having_cap('moodle/question:useall'); // Random from existing category section. - $mform->addElement('header', 'existingcategoryheader', - get_string('randomfromexistingcategory', 'quiz')); - - $mform->addElement('questioncategory', 'category', get_string('category'), - array('contexts' => $usablecontexts, 'top' => true)); + $mform->addElement( + 'header', + 'existingcategoryheader', + get_string('randomfromexistingcategory', 'quiz') + ); + + $mform->addElement( + 'questioncategory', + 'category', + get_string('category'), + ['contexts' => $usablecontexts, 'top' => true] + ); $mform->setDefault('category', $this->_customdata['cat']); $mform->addElement('checkbox', 'includesubcategories', '', get_string('recurse', 'quiz')); @@ -56,15 +63,15 @@ class add_random_form extends moodleform { $mform->hideIf('includesubcategories', 'category', 'in', $tops); if ($CFG->usetags) { - $tagstrings = array(); + $tagstrings = []; $tags = core_tag_tag::get_tags_by_area_in_contexts('core_question', 'question', $usablecontexts); foreach ($tags as $tag) { $tagstrings["{$tag->id},{$tag->name}"] = $tag->name; } - $options = array( + $options = [ 'multiple' => true, 'noselectionstring' => get_string('anytags', 'quiz'), - ); + ]; $mform->addElement('autocomplete', 'fromtags', get_string('randomquestiontags', 'mod_quiz'), $tagstrings, $options); $mform->addHelpButton('fromtags', 'randomquestiontags', 'mod_quiz'); } @@ -74,8 +81,12 @@ class add_random_form extends moodleform { // only matched 9 questions (not already in the quiz), then the drop-down would // only offer choices 1..9. This nice UI hint got lost when the UI became Ajax-y. // We should add it back. - $mform->addElement('select', 'numbertoadd', get_string('randomnumber', 'quiz'), - $this->get_number_of_questions_to_add_choices()); + $mform->addElement( + 'select', + 'numbertoadd', + get_string('randomnumber', 'quiz'), + $this->get_number_of_questions_to_add_choices() + ); $previewhtml = $OUTPUT->render_from_template('mod_quiz/random_question_form_preview', []); $mform->addElement('html', $previewhtml); @@ -85,18 +96,28 @@ class add_random_form extends moodleform { // If the manage categories plugins is enabled, add the elements to create a new category in the form. if (\core\plugininfo\qbank::is_plugin_enabled(\qbank_managecategories\helper::PLUGINNAME)) { // Random from a new category section. - $mform->addElement('header', 'newcategoryheader', - get_string('randomquestionusinganewcategory', 'quiz')); + $mform->addElement( + 'header', + 'newcategoryheader', + get_string('randomquestionusinganewcategory', 'quiz') + ); $mform->addElement('text', 'name', get_string('name'), 'maxlength="254" size="50"'); $mform->setType('name', PARAM_TEXT); - $mform->addElement('questioncategory', 'parent', get_string('parentcategory', 'question'), - array('contexts' => $usablecontexts, 'top' => true)); + $mform->addElement( + 'questioncategory', + 'parent', + get_string('parentcategory', 'question'), + ['contexts' => $usablecontexts, 'top' => true] + ); $mform->addHelpButton('parent', 'parentcategory', 'question'); - $mform->addElement('submit', 'newcategory', - get_string('createcategoryandaddrandomquestion', 'quiz')); + $mform->addElement( + 'submit', + 'newcategory', + get_string('createcategoryandaddrandomquestion', 'quiz') + ); } // Cancel button. @@ -115,7 +136,7 @@ class add_random_form extends moodleform { $mform->getAttribute('id'), $contexts->lowest()->id, $tops, - $CFG->usetags + $CFG->usetags, ]); } @@ -136,7 +157,7 @@ class add_random_form extends moodleform { * @return array of integers [1, 2, ..., 100] (or to the smaller of $maxrand and 100.) */ private function get_number_of_questions_to_add_choices($maxrand = 100) { - $randomcount = array(); + $randomcount = []; for ($i = 1; $i <= min(100, $maxrand); $i++) { $randomcount[$i] = $i; } diff --git a/mod/quiz/classes/form/edit_override_form.php b/mod/quiz/classes/form/edit_override_form.php index b830ce73a4..7dce544e0f 100644 --- a/mod/quiz/classes/form/edit_override_form.php +++ b/mod/quiz/classes/form/edit_override_form.php @@ -17,7 +17,6 @@ namespace mod_quiz\form; use cm_info; -use context; use context_module; use mod_quiz_mod_form; use moodle_url; @@ -66,10 +65,14 @@ class edit_override_form extends moodleform { * @param bool $groupmode editing group override (true) or user override (false). * @param stdClass|null $override the override being edited, if it already exists. */ - public function __construct(moodle_url $submiturl, - cm_info $cm, stdClass $quiz, context_module $context, - bool $groupmode, ?stdClass $override) { - + public function __construct( + moodle_url $submiturl, + cm_info $cm, + stdClass $quiz, + context_module $context, + bool $groupmode, + ?stdClass $override + ) { $this->cm = $cm; $this->quiz = $quiz; $this->context = $context; @@ -97,8 +100,12 @@ class edit_override_form extends moodleform { // There is already a groupid, so freeze the selector. $groupchoices = []; $groupchoices[$this->groupid] = groups_get_group_name($this->groupid); - $mform->addElement('select', 'groupid', - get_string('overridegroup', 'quiz'), $groupchoices); + $mform->addElement( + 'select', + 'groupid', + get_string('overridegroup', 'quiz'), + $groupchoices + ); $mform->freeze('groupid'); } else { // Prepare the list of groups. @@ -120,8 +127,12 @@ class edit_override_form extends moodleform { $groupchoices[0] = get_string('none'); } - $mform->addElement('select', 'groupid', - get_string('overridegroup', 'quiz'), $groupchoices); + $mform->addElement( + 'select', + 'groupid', + get_string('overridegroup', 'quiz'), + $groupchoices + ); $mform->addRule('groupid', get_string('required'), 'required', null, 'client'); } } else { @@ -134,8 +145,12 @@ class edit_override_form extends moodleform { profile_load_custom_fields($user); $userchoices = []; $userchoices[$this->userid] = self::display_user_name($user, $extrauserfields); - $mform->addElement('select', 'userid', - get_string('overrideuser', 'quiz'), $userchoices); + $mform->addElement( + 'select', + 'userid', + get_string('overrideuser', 'quiz'), + $userchoices + ); $mform->freeze('userid'); } else { // Prepare the list of users. @@ -145,10 +160,19 @@ class edit_override_form extends moodleform { $groupids = array_keys($groups); } $enrolledjoin = get_enrolled_with_capabilities_join( - $this->context, '', 'mod/quiz:attempt', $groupids, true); + $this->context, + '', + 'mod/quiz:attempt', + $groupids, + true + ); $userfieldsql = $userfieldsapi->get_sql('u', true, '', '', false); - list($sort, $sortparams) = users_order_by_sql('u', null, - $this->context, $userfieldsql->mappings); + [$sort, $sortparams] = users_order_by_sql( + 'u', + null, + $this->context, + $userfieldsql->mappings + ); $users = $DB->get_records_sql(" SELECT $userfieldsql->selects @@ -178,8 +202,12 @@ class edit_override_form extends moodleform { } unset($users); - $mform->addElement('searchableselector', 'userid', - get_string('overrideuser', 'quiz'), $userchoices); + $mform->addElement( + 'searchableselector', + 'userid', + get_string('overrideuser', 'quiz'), + $userchoices + ); $mform->addRule('userid', get_string('required'), 'required', null, 'client'); } } @@ -193,17 +221,29 @@ class edit_override_form extends moodleform { $mform->setDefault('password', $this->quiz->password); // Open and close dates. - $mform->addElement('date_time_selector', 'timeopen', - get_string('quizopen', 'quiz'), mod_quiz_mod_form::$datefieldoptions); + $mform->addElement( + 'date_time_selector', + 'timeopen', + get_string('quizopen', 'quiz'), + mod_quiz_mod_form::$datefieldoptions + ); $mform->setDefault('timeopen', $this->quiz->timeopen); - $mform->addElement('date_time_selector', 'timeclose', - get_string('quizclose', 'quiz'), mod_quiz_mod_form::$datefieldoptions); + $mform->addElement( + 'date_time_selector', + 'timeclose', + get_string('quizclose', 'quiz'), + mod_quiz_mod_form::$datefieldoptions + ); $mform->setDefault('timeclose', $this->quiz->timeclose); // Time limit. - $mform->addElement('duration', 'timelimit', - get_string('timelimit', 'quiz'), ['optional' => true]); + $mform->addElement( + 'duration', + 'timelimit', + get_string('timelimit', 'quiz'), + ['optional' => true] + ); $mform->addHelpButton('timelimit', 'timelimit', 'quiz'); $mform->setDefault('timelimit', $this->quiz->timelimit); @@ -212,20 +252,33 @@ class edit_override_form extends moodleform { for ($i = 1; $i <= QUIZ_MAX_ATTEMPT_OPTION; $i++) { $attemptoptions[$i] = $i; } - $mform->addElement('select', 'attempts', - get_string('attemptsallowed', 'quiz'), $attemptoptions); + $mform->addElement( + 'select', + 'attempts', + get_string('attemptsallowed', 'quiz'), + $attemptoptions + ); $mform->addHelpButton('attempts', 'attempts', 'quiz'); $mform->setDefault('attempts', $this->quiz->attempts); // Submit buttons. - $mform->addElement('submit', 'resetbutton', - get_string('reverttodefaults', 'quiz')); + $mform->addElement( + 'submit', + 'resetbutton', + get_string('reverttodefaults', 'quiz') + ); $buttonarray = []; - $buttonarray[] = $mform->createElement('submit', 'submitbutton', - get_string('save', 'quiz')); - $buttonarray[] = $mform->createElement('submit', 'againbutton', - get_string('saveoverrideandstay', 'quiz')); + $buttonarray[] = $mform->createElement( + 'submit', + 'submitbutton', + get_string('save', 'quiz') + ); + $buttonarray[] = $mform->createElement( + 'submit', + 'againbutton', + get_string('saveoverrideandstay', 'quiz') + ); $buttonarray[] = $mform->createElement('cancel'); $mform->addGroup($buttonarray, 'buttonbar', '', [' '], false); @@ -278,7 +331,7 @@ class edit_override_form extends moodleform { // Ensure that the dates make sense. if (!empty($data['timeopen']) && !empty($data['timeclose'])) { - if ($data['timeclose'] < $data['timeopen'] ) { + if ($data['timeclose'] < $data['timeopen']) { $errors['timeclose'] = get_string('closebeforeopen', 'quiz'); } } diff --git a/mod/quiz/classes/form/preflight_check_form.php b/mod/quiz/classes/form/preflight_check_form.php index a734d137fe..e03000c46f 100644 --- a/mod/quiz/classes/form/preflight_check_form.php +++ b/mod/quiz/classes/form/preflight_check_form.php @@ -20,7 +20,7 @@ use moodleform; defined('MOODLE_INTERNAL') || die(); -require_once($CFG->libdir.'/formslib.php'); +require_once($CFG->libdir . '/formslib.php'); /** * A form that limits student's access to attempt a quiz. @@ -33,7 +33,7 @@ class preflight_check_form extends moodleform { protected function definition() { $mform = $this->_form; - $this->_form->updateAttributes(array('id' => 'mod_quiz_preflight_form')); + $this->_form->updateAttributes(['id' => 'mod_quiz_preflight_form']); foreach ($this->_customdata['hidden'] as $name => $value) { if ($name === 'sesskey') { @@ -45,8 +45,11 @@ class preflight_check_form extends moodleform { foreach ($this->_customdata['rules'] as $rule) { if ($rule->is_preflight_check_required($this->_customdata['attemptid'])) { - $rule->add_preflight_check_form_fields($this, $mform, - $this->_customdata['attemptid']); + $rule->add_preflight_check_form_fields( + $this, + $mform, + $this->_customdata['attemptid'] + ); } } @@ -59,6 +62,9 @@ class preflight_check_form extends moodleform { $errors = parent::validation($data, $files); $accessmanager = $this->_customdata['quizobj']->get_access_manager(time()); return array_merge($errors, $accessmanager->validate_preflight_check( - $data, $files, $this->_customdata['attemptid'])); + $data, + $files, + $this->_customdata['attemptid'] + )); } } diff --git a/mod/quiz/classes/local/access_rule_base.php b/mod/quiz/classes/local/access_rule_base.php index 9ab7b85c92..5c9361b5ff 100644 --- a/mod/quiz/classes/local/access_rule_base.php +++ b/mod/quiz/classes/local/access_rule_base.php @@ -17,11 +17,9 @@ namespace mod_quiz\local; use mod_quiz\form\preflight_check_form; +use mod_quiz\quiz_settings; use mod_quiz_mod_form; -use moodle_page; use MoodleQuickForm; -use mod_quiz\quiz_settings; -use stdClass; defined('MOODLE_INTERNAL') || die(); @@ -121,8 +119,11 @@ abstract class access_rule_base { * @param int|null $attemptid the id of the current attempt, if there is one, * otherwise null. */ - public function add_preflight_check_form_fields(preflight_check_form $quizform, - MoodleQuickForm $mform, $attemptid) { + public function add_preflight_check_form_fields( + preflight_check_form $quizform, + MoodleQuickForm $mform, + $attemptid + ) { // Do nothing by default. } @@ -270,7 +271,9 @@ abstract class access_rule_base { * @param MoodleQuickForm $mform the wrapped MoodleQuickForm. */ public static function add_settings_form_fields( - mod_quiz_mod_form $quizform, MoodleQuickForm $mform) { + mod_quiz_mod_form $quizform, + MoodleQuickForm $mform + ) { // By default do nothing. } @@ -282,9 +285,12 @@ abstract class access_rule_base { * @param mod_quiz_mod_form $quizform the quiz form object. * @return array $errors the updated $errors array. */ - public static function validate_settings_form_fields(array $errors, - array $data, $files, mod_quiz_mod_form $quizform) { - + public static function validate_settings_form_fields( + array $errors, + array $data, + $files, + mod_quiz_mod_form $quizform + ) { return $errors; } diff --git a/mod/quiz/classes/output/navigation_panel_attempt.php b/mod/quiz/classes/output/navigation_panel_attempt.php index 1fd6fbfc80..359ce64e3c 100644 --- a/mod/quiz/classes/output/navigation_panel_attempt.php +++ b/mod/quiz/classes/output/navigation_panel_attempt.php @@ -39,8 +39,11 @@ class navigation_panel_attempt extends navigation_panel_base { } public function render_before_button_bits(renderer $output) { - return html_writer::tag('div', get_string('navnojswarning', 'quiz'), - array('id' => 'quiznojswarning')); + return html_writer::tag( + 'div', + get_string('navnojswarning', 'quiz'), + ['id' => 'quiznojswarning'] + ); } public function render_end_bits(renderer $output) { @@ -48,8 +51,11 @@ class navigation_panel_attempt extends navigation_panel_base { // Don't link from the summary page to itself. return ''; } - return html_writer::link($this->attemptobj->summary_url(), - get_string('endtest', 'quiz'), array('class' => 'endtestlink aalink')) . + return html_writer::link( + $this->attemptobj->summary_url(), + get_string('endtest', 'quiz'), + ['class' => 'endtestlink aalink'] + ) . $this->render_restart_preview_link($output); } } diff --git a/mod/quiz/classes/output/navigation_panel_base.php b/mod/quiz/classes/output/navigation_panel_base.php index 6de96a68b1..d775171bb7 100644 --- a/mod/quiz/classes/output/navigation_panel_base.php +++ b/mod/quiz/classes/output/navigation_panel_base.php @@ -21,7 +21,6 @@ use moodle_url; use question_attempt; use question_display_options; use question_state; -use renderable; use user_picture; /** @@ -53,8 +52,12 @@ abstract class navigation_panel_base { * @param int $page which page of the quiz attempt is being shown, -1 if all. * @param bool $showall whether all pages are being shown at once. */ - public function __construct(quiz_attempt $attemptobj, - question_display_options $options, $page, $showall) { + public function __construct( + quiz_attempt $attemptobj, + question_display_options $options, + $page, + $showall + ) { $this->attemptobj = $attemptobj; $this->options = $options; $this->page = $page; @@ -64,10 +67,10 @@ abstract class navigation_panel_base { /** * Get the buttons and section headings to go in the quiz navigation block. * - * @return renderable[] the buttons, possibly interleaved with section headings. + * @return \renderable[] the buttons, possibly interleaved with section headings. */ public function get_question_buttons() { - $buttons = array(); + $buttons = []; foreach ($this->attemptobj->get_slots() as $slot) { $heading = $this->attemptobj->get_heading_before_slot($slot); if (!is_null($heading)) { @@ -153,7 +156,9 @@ abstract class navigation_panel_base { return ''; } return $output->restart_preview_button(new moodle_url( - $this->attemptobj->start_attempt_url(), array('forcenew' => true))); + $this->attemptobj->start_attempt_url(), + ['forcenew' => true] + )); } /** @@ -174,7 +179,7 @@ abstract class navigation_panel_base { if ($this->attemptobj->get_quiz()->showuserpicture == QUIZ_SHOWIMAGE_NONE) { return null; } - $user = $DB->get_record('user', array('id' => $this->attemptobj->get_userid())); + $user = $DB->get_record('user', ['id' => $this->attemptobj->get_userid()]); $userpicture = new user_picture($user); $userpicture->courseid = $this->attemptobj->get_courseid(); if ($this->attemptobj->get_quiz()->showuserpicture == QUIZ_SHOWIMAGE_LARGE) { diff --git a/mod/quiz/classes/output/navigation_panel_review.php b/mod/quiz/classes/output/navigation_panel_review.php index d07de8e417..3979ca8b87 100644 --- a/mod/quiz/classes/output/navigation_panel_review.php +++ b/mod/quiz/classes/output/navigation_panel_review.php @@ -38,11 +38,15 @@ class navigation_panel_review extends navigation_panel_base { $html = ''; if ($this->attemptobj->get_num_pages() > 1) { if ($this->showall) { - $html .= html_writer::link($this->attemptobj->review_url(null, 0, false), - get_string('showeachpage', 'quiz')); + $html .= html_writer::link( + $this->attemptobj->review_url(null, 0, false), + get_string('showeachpage', 'quiz') + ); } else { - $html .= html_writer::link($this->attemptobj->review_url(null, 0, true), - get_string('showall', 'quiz')); + $html .= html_writer::link( + $this->attemptobj->review_url(null, 0, true), + get_string('showall', 'quiz') + ); } } $html .= $output->finish_review_link($this->attemptobj); diff --git a/mod/quiz/classes/output/navigation_question_button.php b/mod/quiz/classes/output/navigation_question_button.php index e07a23d73d..acd43a3de8 100644 --- a/mod/quiz/classes/output/navigation_question_button.php +++ b/mod/quiz/classes/output/navigation_question_button.php @@ -16,7 +16,6 @@ namespace mod_quiz\output; -use moodle_url; use renderable; /** @@ -42,7 +41,7 @@ class navigation_question_button implements renderable { public $currentpage; /** @var bool true if this question has been flagged. */ public $flagged; - /** @var moodle_url the link this button goes to, or null if there should not be a link. */ + /** @var \moodle_url the link this button goes to, or null if there should not be a link. */ public $url; /** @var int QUIZ_NAVMETHOD_FREE or QUIZ_NAVMETHOD_SEQ. */ public $navmethod; diff --git a/mod/quiz/classes/output/renderer.php b/mod/quiz/classes/output/renderer.php index d5a06c8187..3662d23ba5 100644 --- a/mod/quiz/classes/output/renderer.php +++ b/mod/quiz/classes/output/renderer.php @@ -16,22 +16,18 @@ namespace mod_quiz\output; -use cm_info; use coding_exception; -use context; -use context_module; use html_table; use html_table_cell; use html_writer; -use mod_quiz\access_manager; use mod_quiz\form\preflight_check_form; use mod_quiz\question\display_options; use mod_quiz\quiz_attempt; +use mod_quiz\quiz_settings; use moodle_url; use plugin_renderer_base; use popup_action; use question_display_options; -use mod_quiz\quiz_settings; use renderable; use single_button; use stdClass; @@ -57,15 +53,25 @@ class renderer extends plugin_renderer_base { * @param array $summarydata contains all table data * @return string HTML to display. */ - public function review_page(quiz_attempt $attemptobj, $slots, $page, $showall, - $lastpage, display_options $displayoptions, $summarydata) { - + public function review_page( + quiz_attempt $attemptobj, + $slots, + $page, + $showall, + $lastpage, + display_options $displayoptions, + $summarydata + ) { $output = ''; $output .= $this->header(); $output .= $this->review_summary_table($summarydata, $page); - $output .= $this->review_form($page, $showall, $displayoptions, - $this->questions($attemptobj, true, $slots, $page, $showall, $displayoptions), - $attemptobj); + $output .= $this->review_form( + $page, + $showall, + $displayoptions, + $this->questions($attemptobj, true, $slots, $page, $showall, $displayoptions), + $attemptobj + ); $output .= $this->review_next_navigation($attemptobj, $page, $lastpage, $showall); $output .= $this->footer(); @@ -82,9 +88,13 @@ class renderer extends plugin_renderer_base { * @param array $summarydata contains all table data * @return string HTML to display. */ - public function review_question_page(quiz_attempt $attemptobj, $slot, $seq, - display_options $displayoptions, $summarydata) { - + public function review_question_page( + quiz_attempt $attemptobj, + $slot, + $seq, + display_options $displayoptions, + $summarydata + ) { $output = ''; $output .= $this->header(); $output .= $this->review_summary_table($summarydata, 0); @@ -110,8 +120,11 @@ class renderer extends plugin_renderer_base { public function review_question_not_allowed(quiz_attempt $attemptobj, $message) { $output = ''; $output .= $this->header(); - $output .= $this->heading(format_string($attemptobj->get_quiz_name(), true, - ["context" => $attemptobj->get_quizobj()->get_context()])); + $output .= $this->heading(format_string( + $attemptobj->get_quiz_name(), + true, + ["context" => $attemptobj->get_quizobj()->get_context()] + )); $output .= $this->notification($message); $output .= $this->close_window_button(); $output .= $this->footer(); @@ -155,7 +168,8 @@ class renderer extends plugin_renderer_base { $output = ''; $output .= html_writer::start_tag('table', [ - 'class' => 'generaltable generalbox quizreviewsummary']); + 'class' => 'generaltable generalbox quizreviewsummary', + ]); $output .= html_writer::start_tag('tbody'); foreach ($summarydata as $rowdata) { if ($rowdata['title'] instanceof renderable) { @@ -170,8 +184,9 @@ class renderer extends plugin_renderer_base { $content = $rowdata['content']; } - $output .= html_writer::tag('tr', - html_writer::tag('th', $title, ['class' => 'cell', 'scope' => 'row']) . + $output .= html_writer::tag( + 'tr', + html_writer::tag('th', $title, ['class' => 'cell', 'scope' => 'row']) . html_writer::tag('td', $content, ['class' => 'cell']) ); } @@ -191,12 +206,22 @@ class renderer extends plugin_renderer_base { * @param bool $showall if true shows attempt on single page * @param display_options $displayoptions instance of display_options */ - public function questions(quiz_attempt $attemptobj, $reviewing, $slots, $page, $showall, - display_options $displayoptions) { + public function questions( + quiz_attempt $attemptobj, + $reviewing, + $slots, + $page, + $showall, + display_options $displayoptions + ) { $output = ''; foreach ($slots as $slot) { - $output .= $attemptobj->render_question($slot, $reviewing, $this, - $attemptobj->review_url($slot, $page, $showall)); + $output .= $attemptobj->render_question( + $slot, + $reviewing, + $this, + $attemptobj->review_url($slot, $page, $showall) + ); } return $output; } @@ -216,20 +241,37 @@ class renderer extends plugin_renderer_base { return $content; } - $this->page->requires->js_init_call('M.mod_quiz.init_review_form', null, false, - quiz_get_js_module()); + $this->page->requires->js_init_call( + 'M.mod_quiz.init_review_form', + null, + false, + quiz_get_js_module() + ); $output = ''; - $output .= html_writer::start_tag('form', ['action' => $attemptobj->review_url(null, - $page, $showall), 'method' => 'post', 'class' => 'questionflagsaveform']); + $output .= html_writer::start_tag('form', [ + 'action' => $attemptobj->review_url( + null, + $page, + $showall + ), + 'method' => 'post', + 'class' => 'questionflagsaveform', + ]); $output .= html_writer::start_tag('div'); $output .= $content; - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey', - 'value' => sesskey()]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'sesskey', + 'value' => sesskey(), + ]); $output .= html_writer::start_tag('div', ['class' => 'submitbtns']); - $output .= html_writer::empty_tag('input', ['type' => 'submit', - 'class' => 'questionflagsavebutton btn btn-secondary', 'name' => 'savingflags', - 'value' => get_string('saveflags', 'question')]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'submit', + 'class' => 'questionflagsavebutton btn btn-secondary', + 'name' => 'savingflags', + 'value' => get_string('saveflags', 'question'), + ]); $output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('div'); $output .= html_writer::end_tag('form'); @@ -246,16 +288,24 @@ class renderer extends plugin_renderer_base { $url = $attemptobj->view_url(); if ($attemptobj->get_access_manager(time())->attempt_must_be_in_popup()) { - $this->page->requires->js_init_call('M.mod_quiz.secure_window.init_close_button', - [$url], false, quiz_get_js_module()); - return html_writer::empty_tag('input', ['type' => 'button', - 'value' => get_string('finishreview', 'quiz'), - 'id' => 'secureclosebutton', - 'class' => 'mod_quiz-next-nav btn btn-primary']); - + $this->page->requires->js_init_call( + 'M.mod_quiz.secure_window.init_close_button', + [$url], + false, + quiz_get_js_module() + ); + return html_writer::empty_tag('input', [ + 'type' => 'button', + 'value' => get_string('finishreview', 'quiz'), + 'id' => 'secureclosebutton', + 'class' => 'mod_quiz-next-nav btn btn-primary', + ]); } else { - return html_writer::link($url, get_string('finishreview', 'quiz'), - ['class' => 'mod_quiz-next-nav']); + return html_writer::link( + $url, + get_string('finishreview', 'quiz'), + ['class' => 'mod_quiz-next-nav'] + ); } } @@ -276,14 +326,22 @@ class renderer extends plugin_renderer_base { public function review_next_navigation(quiz_attempt $attemptobj, $page, $lastpage, $showall = null) { $nav = ''; if ($page > 0) { - $nav .= link_arrow_left(get_string('navigateprevious', 'quiz'), - $attemptobj->review_url(null, $page - 1, $showall), false, 'mod_quiz-prev-nav'); + $nav .= link_arrow_left( + get_string('navigateprevious', 'quiz'), + $attemptobj->review_url(null, $page - 1, $showall), + false, + 'mod_quiz-prev-nav' + ); } if ($lastpage) { $nav .= $this->finish_review_link($attemptobj); } else { - $nav .= link_arrow_right(get_string('navigatenext', 'quiz'), - $attemptobj->review_url(null, $page + 1, $showall), false, 'mod_quiz-next-nav'); + $nav .= link_arrow_right( + get_string('navigatenext', 'quiz'), + $attemptobj->review_url(null, $page + 1, $showall), + false, + 'mod_quiz-next-nav' + ); } return html_writer::tag('div', $nav, ['class' => 'submitbtns']); } @@ -296,7 +354,6 @@ class renderer extends plugin_renderer_base { * @return string HTML content. */ public function countdown_timer(quiz_attempt $attemptobj, $timenow) { - $timeleft = $attemptobj->get_time_left_display($timenow); if ($timeleft !== false) { $ispreview = $attemptobj->is_preview(); @@ -327,7 +384,6 @@ class renderer extends plugin_renderer_base { * @param navigation_panel_base $panel */ public function navigation_panel(navigation_panel_base $panel) { - $output = ''; $userpicture = $panel->user_picture(); if ($userpicture) { @@ -335,8 +391,11 @@ class renderer extends plugin_renderer_base { if ($userpicture->size) { $fullname = html_writer::div($fullname); } - $output .= html_writer::tag('div', $this->render($userpicture) . $fullname, - ['id' => 'user-picture', 'class' => 'clearfix']); + $output .= html_writer::tag( + 'div', + $this->render($userpicture) . $fullname, + ['id' => 'user-picture', 'class' => 'clearfix'] + ); } $output .= $panel->render_before_button_bits($this); @@ -347,11 +406,18 @@ class renderer extends plugin_renderer_base { } $output .= html_writer::end_tag('div'); - $output .= html_writer::tag('div', $panel->render_end_bits($this), - ['class' => 'othernav']); + $output .= html_writer::tag( + 'div', + $panel->render_end_bits($this), + ['class' => 'othernav'] + ); - $this->page->requires->js_init_call('M.mod_quiz.nav.init', null, false, - quiz_get_js_module()); + $this->page->requires->js_init_call( + 'M.mod_quiz.nav.init', + null, + false, + quiz_get_js_module() + ); return $output; } @@ -392,8 +458,12 @@ class renderer extends plugin_renderer_base { $tagcontents = html_writer::tag('span', '', ['class' => 'thispageholder']) . html_writer::tag('span', '', ['class' => 'trafficlight']) . get_string($qnostring, 'quiz', $a); - $tagattributes = ['class' => implode(' ', $classes), 'id' => $button->id, - 'title' => $button->statestring, 'data-quiz-page' => $button->page]; + $tagattributes = [ + 'class' => implode(' ', $classes), + 'id' => $button->id, + 'title' => $button->statestring, + 'data-quiz-page' => $button->page, + ]; if ($button->url) { return html_writer::link($button->url, $tagcontents, $tagattributes); @@ -426,7 +496,8 @@ class renderer extends plugin_renderer_base { * @return string HTML fragment. */ protected function render_links_to_other_attempts( - links_to_other_attempts $links) { + links_to_other_attempts $links + ) { $attemptlinks = []; foreach ($links->links as $attempt => $url) { if (!$url) { @@ -456,8 +527,11 @@ class renderer extends plugin_renderer_base { $output = ''; $output .= $this->header(); $output .= $this->during_attempt_tertiary_nav($quizobj->view_url()); - $output .= $this->heading(format_string($quizobj->get_quiz_name(), true, - ["context" => $quizobj->get_context()])); + $output .= $this->heading(format_string( + $quizobj->get_quiz_name(), + true, + ["context" => $quizobj->get_context()] + )); $output .= $this->quiz_intro($quizobj->get_quiz(), $quizobj->get_cm()); $output .= $mform->render(); $output .= $this->footer(); @@ -476,8 +550,15 @@ class renderer extends plugin_renderer_base { * @param int $nextpage The number of the next page * @return string HTML to output. */ - public function attempt_page($attemptobj, $page, $accessmanager, $messages, $slots, $id, - $nextpage) { + public function attempt_page( + $attemptobj, + $page, + $accessmanager, + $messages, + $slots, + $id, + $nextpage + ) { $output = ''; $output .= $this->header(); $output .= $this->during_attempt_tertiary_nav($attemptobj->view_url()); @@ -499,8 +580,11 @@ class renderer extends plugin_renderer_base { $output .= html_writer::start_div('container-fluid tertiary-navigation'); $output .= html_writer::start_div('row'); $output .= html_writer::start_div('navitem'); - $output .= html_writer::link($quizviewurl, get_string('back'), - ['class' => 'btn btn-secondary']); + $output .= html_writer::link( + $quizviewurl, + get_string('back'), + ['class' => 'btn btn-secondary'] + ); $output .= html_writer::end_div(); $output .= html_writer::end_div(); $output .= html_writer::end_div(); @@ -517,9 +601,9 @@ class renderer extends plugin_renderer_base { return ''; } return $this->notification( - html_writer::tag('p', get_string('accessnoticesheader', 'quiz')) . $this->access_messages($messages), - 'warning', - false + html_writer::tag('p', get_string('accessnoticesheader', 'quiz')) . $this->access_messages($messages), + 'warning', + false ); } @@ -536,41 +620,77 @@ class renderer extends plugin_renderer_base { $output = ''; // Start the form. - $output .= html_writer::start_tag('form', - ['action' => new moodle_url($attemptobj->processattempt_url(), - ['cmid' => $attemptobj->get_cmid()]), 'method' => 'post', - 'enctype' => 'multipart/form-data', 'accept-charset' => 'utf-8', - 'id' => 'responseform']); + $output .= html_writer::start_tag( + 'form', + [ + 'action' => new moodle_url( + $attemptobj->processattempt_url(), + ['cmid' => $attemptobj->get_cmid()] + ), + 'method' => 'post', + 'enctype' => 'multipart/form-data', + 'accept-charset' => 'utf-8', + 'id' => 'responseform', + ] + ); $output .= html_writer::start_tag('div'); // Print all the questions. foreach ($slots as $slot) { - $output .= $attemptobj->render_question($slot, false, $this, - $attemptobj->attempt_url($slot, $page)); + $output .= $attemptobj->render_question( + $slot, + false, + $this, + $attemptobj->attempt_url($slot, $page) + ); } $navmethod = $attemptobj->get_quiz()->navmethod; $output .= $this->attempt_navigation_buttons($page, $attemptobj->is_last_page($page), $navmethod); // Some hidden fields to track what is going on. - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'attempt', - 'value' => $attemptobj->get_attemptid()]); - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'thispage', - 'value' => $page, 'id' => 'followingpage']); - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'nextpage', - 'value' => $nextpage]); - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'timeup', - 'value' => '0', 'id' => 'timeup']); - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'sesskey', - 'value' => sesskey()]); - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'scrollpos', - 'value' => '', 'id' => 'scrollpos']); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'attempt', + 'value' => $attemptobj->get_attemptid(), + ]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'thispage', + 'value' => $page, + 'id' => 'followingpage', + ]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'nextpage', + 'value' => $nextpage, + ]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'timeup', + 'value' => '0', + 'id' => 'timeup', + ]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'sesskey', + 'value' => sesskey(), + ]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'scrollpos', + 'value' => '', + 'id' => 'scrollpos', + ]); // Add a hidden field with questionids. Do this at the end of the form, so // if you navigate before the form has finished loading, it does not wipe all // the student's answers. - $output .= html_writer::empty_tag('input', ['type' => 'hidden', 'name' => 'slots', - 'value' => implode(',', $attemptobj->get_active_slots($page))]); + $output .= html_writer::empty_tag('input', [ + 'type' => 'hidden', + 'name' => 'slots', + 'value' => implode(',', $attemptobj->get_active_slots($page)), + ]); // Finish the form. $output .= html_writer::end_tag('div'); @@ -594,9 +714,13 @@ class renderer extends plugin_renderer_base { $output .= html_writer::start_tag('div', ['class' => 'submitbtns']); if ($page > 0 && $navmethod == 'free') { - $output .= html_writer::empty_tag('input', ['type' => 'submit', 'name' => 'previous', - 'value' => get_string('navigateprevious', 'quiz'), 'class' => 'mod_quiz-prev-nav btn btn-secondary', - 'id' => 'mod_quiz-prev-nav']); + $output .= html_writer::empty_tag('input', [ + 'type' => 'submit', + 'name' => 'previous', + 'value' => get_string('navigateprevious', 'quiz'), + 'class' => 'mod_quiz-prev-nav btn btn-secondary', + 'id' => 'mod_quiz-prev-nav', + ]); $this->page->requires->js_call_amd('core_form/submit', 'init', ['mod_quiz-prev-nav']); } if ($lastpage) { @@ -604,8 +728,13 @@ class renderer extends plugin_renderer_base { } else { $nextlabel = get_string('navigatenext', 'quiz'); } - $output .= html_writer::empty_tag('input', ['type' => 'submit', 'name' => 'next', - 'value' => $nextlabel, 'class' => 'mod_quiz-next-nav btn btn-primary', 'id' => 'mod_quiz-next-nav']); + $output .= html_writer::empty_tag('input', [ + 'type' => 'submit', + 'name' => 'next', + 'value' => $nextlabel, + 'class' => 'mod_quiz-next-nav btn btn-primary', + 'id' => 'mod_quiz-next-nav', + ]); $output .= html_writer::end_tag('div'); $this->page->requires->js_call_amd('core_form/submit', 'init', ['mod_quiz-next-nav']); @@ -620,9 +749,12 @@ class renderer extends plugin_renderer_base { * @return string HTML fragment. */ public function redo_question_button($slot, $disabled) { - $attributes = ['type' => 'submit', 'name' => 'redoslot' . $slot, - 'value' => get_string('redoquestion', 'quiz'), - 'class' => 'mod_quiz-redo_question_button btn btn-secondary']; + $attributes = [ + 'type' => 'submit', + 'name' => 'redoslot' . $slot, + 'value' => get_string('redoquestion', 'quiz'), + 'class' => 'mod_quiz-redo_question_button btn btn-secondary', + ]; if ($disabled) { $attributes['disabled'] = 'disabled'; } @@ -661,8 +793,12 @@ class renderer extends plugin_renderer_base { $output .= html_writer::tag('p', get_string('pleaseclose', 'quiz')); $delay = 0; } - $this->page->requires->js_init_call('M.mod_quiz.secure_window.close', - [$url, $delay], false, quiz_get_js_module()); + $this->page->requires->js_init_call( + 'M.mod_quiz.secure_window.close', + [$url, $delay], + false, + quiz_get_js_module() + ); $output .= $this->box_end(); $output .= $this->footer(); @@ -760,23 +896,32 @@ class renderer extends plugin_renderer_base { $flag = ''; if ($attemptobj->is_question_flagged($slot)) { // Quiz has custom JS manipulating these image tags - so we can't use the pix_icon method here. - $flag = html_writer::empty_tag('img', ['src' => $this->image_url('i/flagged'), - 'alt' => get_string('flagged', 'question'), 'class' => 'questionflag icon-post']); + $flag = html_writer::empty_tag('img', [ + 'src' => $this->image_url('i/flagged'), + 'alt' => get_string('flagged', 'question'), + 'class' => 'questionflag icon-post', + ]); } if ($attemptobj->can_navigate_to($slot)) { - $row = [html_writer::link($attemptobj->attempt_url($slot), - $attemptobj->get_question_number($slot) . $flag), - $attemptobj->get_question_status($slot, $displayoptions->correctness)]; + $row = [html_writer::link( + $attemptobj->attempt_url($slot), + $attemptobj->get_question_number($slot) . $flag + ), + $attemptobj->get_question_status($slot, $displayoptions->correctness), + ]; } else { $row = [$attemptobj->get_question_number($slot) . $flag, - $attemptobj->get_question_status($slot, $displayoptions->correctness)]; + $attemptobj->get_question_status($slot, $displayoptions->correctness), + ]; } if ($markscolumn) { $row[] = $attemptobj->get_question_mark($slot); } $table->data[] = $row; $table->rowclasses[] = 'quizsummary' . $slot . ' ' . $attemptobj->get_question_state_class( - $slot, $displayoptions->correctness); + $slot, + $displayoptions->correctness + ); } // Print the summary table. @@ -794,25 +939,29 @@ class renderer extends plugin_renderer_base { // Return to place button. if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) { $button = new single_button( - new moodle_url($attemptobj->attempt_url(null, $attemptobj->get_currentpage())), - get_string('returnattempt', 'quiz')); - $output .= $this->container($this->container($this->render($button), - 'controls'), 'submitbtns mdl-align'); + new moodle_url($attemptobj->attempt_url(null, $attemptobj->get_currentpage())), + get_string('returnattempt', 'quiz') + ); + $output .= $this->container($this->container( + $this->render($button), + 'controls' + ), 'submitbtns mdl-align'); } // Finish attempt button. $options = [ - 'attempt' => $attemptobj->get_attemptid(), - 'finishattempt' => 1, - 'timeup' => 0, - 'slots' => '', - 'cmid' => $attemptobj->get_cmid(), - 'sesskey' => sesskey(), + 'attempt' => $attemptobj->get_attemptid(), + 'finishattempt' => 1, + 'timeup' => 0, + 'slots' => '', + 'cmid' => $attemptobj->get_cmid(), + 'sesskey' => sesskey(), ]; $button = new single_button( - new moodle_url($attemptobj->processattempt_url(), $options), - get_string('submitallandfinish', 'quiz')); + new moodle_url($attemptobj->processattempt_url(), $options), + get_string('submitallandfinish', 'quiz') + ); $button->class = 'btn-finishattempt'; $button->formid = 'frm-finishattempt'; if ($attemptobj->get_state() == quiz_attempt::IN_PROGRESS) { @@ -829,7 +978,6 @@ class renderer extends plugin_renderer_base { $message = ''; if ($attemptobj->get_state() == quiz_attempt::OVERDUE) { $message = get_string('overduemustbesubmittedby', 'quiz', userdate($duedate)); - } else { if ($duedate) { $message = get_string('mustbesubmittedby', 'quiz', userdate($duedate)); @@ -838,7 +986,9 @@ class renderer extends plugin_renderer_base { $output .= $this->countdown_timer($attemptobj, time()); $output .= $this->container($message . $this->container( - $this->render($button), 'controls'), 'submitbtns mdl-align'); + $this->render($button), + 'controls' + ), 'submitbtns mdl-align'); return $output; } @@ -852,7 +1002,7 @@ class renderer extends plugin_renderer_base { * @param stdClass $course the course settings row from the database. * @param stdClass $quiz the quiz settings row from the database. * @param stdClass $cm the course_module settings row from the database. - * @param context_module $context the quiz context. + * @param \context_module $context the quiz context. * @param view_page $viewobj * @return string HTML to display */ @@ -877,15 +1027,22 @@ class renderer extends plugin_renderer_base { $content = ''; if ($viewobj->buttontext) { - $attemptbtn = $this->start_attempt_button($viewobj->buttontext, - $viewobj->startattempturl, $viewobj->preflightcheckform, - $viewobj->popuprequired, $viewobj->popupoptions); + $attemptbtn = $this->start_attempt_button( + $viewobj->buttontext, + $viewobj->startattempturl, + $viewobj->preflightcheckform, + $viewobj->popuprequired, + $viewobj->popupoptions + ); $content .= $attemptbtn; } if ($viewobj->canedit && !$viewobj->quizhasquestions) { - $content .= html_writer::link($viewobj->editurl, get_string('addquestion', 'quiz'), - ['class' => 'btn btn-secondary']); + $content .= html_writer::link( + $viewobj->editurl, + get_string('addquestion', 'quiz'), + ['class' => 'btn btn-secondary'] + ); } if ($content) { @@ -907,15 +1064,19 @@ class renderer extends plugin_renderer_base { if (!$viewobj->quizhasquestions) { $output .= html_writer::div( - $this->notification(get_string('noquestions', 'quiz'), 'warning', false), - 'text-left mb-3'); + $this->notification(get_string('noquestions', 'quiz'), 'warning', false), + 'text-left mb-3' + ); } $output .= $this->access_messages($viewobj->preventmessages); if ($viewobj->showbacktocourse) { - $output .= $this->single_button($viewobj->backtocourseurl, - get_string('backtocourse', 'quiz'), 'get', - ['class' => 'continuebutton']); + $output .= $this->single_button( + $viewobj->backtocourseurl, + get_string('backtocourse', 'quiz'), + 'get', + ['class' => 'continuebutton'] + ); } return $output; @@ -931,10 +1092,13 @@ class renderer extends plugin_renderer_base { * @param array $popupoptions the options to use if we are opening a popup. * @return string HTML fragment. */ - public function start_attempt_button($buttontext, moodle_url $url, - preflight_check_form $preflightcheckform = null, - $popuprequired = false, $popupoptions = null) { - + public function start_attempt_button( + $buttontext, + moodle_url $url, + preflight_check_form $preflightcheckform = null, + $popuprequired = false, + $popupoptions = null + ) { $button = new single_button($url, $buttontext, 'post', true); $button->class .= ' quizstartbuttondiv'; if ($popuprequired) { @@ -947,9 +1111,14 @@ class renderer extends plugin_renderer_base { $popupjsoptions = $action->get_js_options(); } - $this->page->requires->js_call_amd('mod_quiz/preflightcheck', 'init', - ['.quizstartbuttondiv [type=submit]', get_string('startattempt', 'quiz'), - '#mod_quiz_preflight_form', $popupjsoptions]); + $this->page->requires->js_call_amd( + 'mod_quiz/preflightcheck', + 'init', + ['.quizstartbuttondiv [type=submit]', get_string('startattempt', 'quiz'), + '#mod_quiz_preflight_form', + $popupjsoptions, + ] + ); return $this->render($button) . ($preflightcheckform ? $preflightcheckform->render() : ''); } @@ -986,7 +1155,7 @@ class renderer extends plugin_renderer_base { * @param stdClass $course the course settings row from the database. * @param stdClass $quiz the quiz settings row from the database. * @param stdClass $cm the course_module settings row from the database. - * @param context_module $context the quiz context. + * @param \context_module $context the quiz context. * @param array $messages Array containing any messages * @param view_page $viewobj */ @@ -1007,7 +1176,7 @@ class renderer extends plugin_renderer_base { * @param stdClass $course the course settings row from the database. * @param stdClass $quiz the quiz settings row from the database. * @param stdClass $cm the course_module settings row from the database. - * @param context_module $context the quiz context. + * @param \context_module $context the quiz context. * @param array $messages Array containing any messages * @param view_page $viewobj */ @@ -1017,8 +1186,10 @@ class renderer extends plugin_renderer_base { $output .= $this->view_page_tertiary_nav($viewobj); $output .= $this->view_information($quiz, $cm, $context, $messages); $youneedtoenrol = html_writer::tag('p', get_string('youneedtoenrol', 'quiz')); - $button = html_writer::tag('p', - $this->continue_button($CFG->wwwroot . '/course/view.php?id=' . $course->id)); + $button = html_writer::tag( + 'p', + $this->continue_button($CFG->wwwroot . '/course/view.php?id=' . $course->id) + ); $output .= $this->box($youneedtoenrol . "\n\n" . $button . "\n", 'generalbox', 'notice'); return $output; } @@ -1028,7 +1199,7 @@ class renderer extends plugin_renderer_base { * * @param object $quiz the quiz settings. * @param object $cm the course_module object. - * @param context $context the quiz context. + * @param \context $context the quiz context. * @param array $messages any access messages that should be described. * @param bool $quizhasquestions does quiz has questions added. * @return string HTML to output. @@ -1043,10 +1214,18 @@ class renderer extends plugin_renderer_base { // Show number of attempts summary to those who can view reports. if (has_capability('mod/quiz:viewreports', $context)) { - if ($strattemptnum = $this->quiz_attempt_summary_link_to_reports($quiz, $cm, - $context)) { - $output .= html_writer::tag('div', $strattemptnum, - ['class' => 'quizattemptcounts']); + if ( + $strattemptnum = $this->quiz_attempt_summary_link_to_reports( + $quiz, + $cm, + $context + ) + ) { + $output .= html_writer::tag( + 'div', + $strattemptnum, + ['class' => 'quizattemptcounts'] + ); } } @@ -1085,7 +1264,7 @@ class renderer extends plugin_renderer_base { * Generates the table of data * * @param stdClass $quiz the quiz settings. - * @param context_module $context the quiz context. + * @param \context_module $context the quiz context. * @param view_page $viewobj */ public function view_table($quiz, $context, $viewobj) { @@ -1147,8 +1326,10 @@ class renderer extends plugin_renderer_base { $row[] = $this->attempt_state($attemptobj); if ($viewobj->markcolumn) { - if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX && - $attemptobj->is_finished()) { + if ( + $attemptoptions->marks >= question_display_options::MARK_AND_MAX && + $attemptobj->is_finished() + ) { $row[] = quiz_format_grade($quiz, $attemptobj->get_sum_marks()); } else { $row[] = ''; @@ -1159,15 +1340,18 @@ class renderer extends plugin_renderer_base { $attemptgrade = quiz_rescale_grade($attemptobj->get_sum_marks(), $quiz, false); if ($viewobj->gradecolumn) { - if ($attemptoptions->marks >= question_display_options::MARK_AND_MAX && - $attemptobj->is_finished()) { - + if ( + $attemptoptions->marks >= question_display_options::MARK_AND_MAX && + $attemptobj->is_finished() + ) { // Highlight the highest grade if appropriate. - if ($viewobj->overallstats && !$attemptobj->is_preview() + if ( + $viewobj->overallstats && !$attemptobj->is_preview() && $viewobj->numattempts > 1 && !is_null($viewobj->mygrade) && $attemptobj->get_state() == quiz_attempt::FINISHED && $attemptgrade == $viewobj->mygrade - && $quiz->grademethod == QUIZ_GRADEHIGHEST) { + && $quiz->grademethod == QUIZ_GRADEHIGHEST + ) { $table->rowclasses[$attemptobj->get_attempt_number()] = 'bestrow'; } @@ -1178,8 +1362,11 @@ class renderer extends plugin_renderer_base { } if ($viewobj->canreviewmine) { - $row[] = $viewobj->accessmanager->make_review_link($attemptobj->get_attempt(), - $attemptoptions, $this); + $row[] = $viewobj->accessmanager->make_review_link( + $attemptobj->get_attempt(), + $attemptoptions, + $this + ); } if ($viewobj->feedbackcolumn && $attemptobj->is_finished()) { @@ -1215,16 +1402,26 @@ class renderer extends plugin_renderer_base { return get_string('stateinprogress', 'quiz'); case quiz_attempt::OVERDUE: - return get_string('stateoverdue', 'quiz') . html_writer::tag('span', - get_string('stateoverduedetails', 'quiz', - userdate($attemptobj->get_due_date())), - ['class' => 'statedetails']); + return get_string('stateoverdue', 'quiz') . html_writer::tag( + 'span', + get_string( + 'stateoverduedetails', + 'quiz', + userdate($attemptobj->get_due_date()) + ), + ['class' => 'statedetails'] + ); case quiz_attempt::FINISHED: - return get_string('statefinished', 'quiz') . html_writer::tag('span', - get_string('statefinisheddetails', 'quiz', - userdate($attemptobj->get_submitted_date())), - ['class' => 'statedetails']); + return get_string('statefinished', 'quiz') . html_writer::tag( + 'span', + get_string( + 'statefinisheddetails', + 'quiz', + userdate($attemptobj->get_submitted_date()) + ), + ['class' => 'statedetails'] + ); case quiz_attempt::ABANDONED: return get_string('stateabandoned', 'quiz'); @@ -1238,7 +1435,7 @@ class renderer extends plugin_renderer_base { * Generates data pertaining to quiz results * * @param stdClass $quiz Array containing quiz data - * @param context_module $context The quiz context. + * @param \context_module $context The quiz context. * @param stdClass|cm_info $cm The course module information. * @param view_page $viewobj * @return string HTML to display. @@ -1267,9 +1464,11 @@ class renderer extends plugin_renderer_base { } if ($viewobj->mygradeoverridden) { - - $resultinfo .= html_writer::tag('p', get_string('overriddennotice', 'grades'), - ['class' => 'overriddennotice']) . "\n"; + $resultinfo .= html_writer::tag( + 'p', + get_string('overriddennotice', 'grades'), + ['class' => 'overriddennotice'] + ) . "\n"; } if ($viewobj->gradebookfeedback) { $resultinfo .= $this->heading(get_string('comment', 'quiz'), 3); @@ -1278,8 +1477,9 @@ class renderer extends plugin_renderer_base { if ($viewobj->feedbackcolumn) { $resultinfo .= $this->heading(get_string('overallfeedback', 'quiz'), 3); $resultinfo .= html_writer::div( - quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context), - 'quizgradefeedback') . "\n"; + quiz_feedback_for_grade($viewobj->mygrade, $quiz, $context), + 'quizgradefeedback' + ) . "\n"; } if ($resultinfo) { @@ -1302,10 +1502,12 @@ class renderer extends plugin_renderer_base { $button = new single_button($url, get_string('review', 'quiz')); $button->add_action(new popup_action('click', $url, 'quizpopup', $popupoptions)); return $this->render($button); - } else { - return html_writer::link($url, get_string('review', 'quiz'), - ['title' => get_string('reviewthisattempt', 'quiz')]); + return html_writer::link( + $url, + get_string('review', 'quiz'), + ['title' => get_string('reviewthisattempt', 'quiz')] + ); } } @@ -1317,8 +1519,11 @@ class renderer extends plugin_renderer_base { * @return string HTML to output. */ public function no_review_message($message) { - return html_writer::nonempty_tag('span', $message, - ['class' => 'noreviewmessage']); + return html_writer::nonempty_tag( + 'span', + $message, + ['class' => 'noreviewmessage'] + ); } /** @@ -1327,15 +1532,20 @@ class renderer extends plugin_renderer_base { * @param stdClass $quiz the quiz object. Only $quiz->id is used at the moment. * @param stdClass $cm the cm object. Only $cm->course, $cm->groupmode and $cm->groupingid * fields are used at the moment. - * @param context $context the quiz context. + * @param \context $context the quiz context. * @param bool $returnzero if false (default), when no attempts have been made '' is returned * instead of 'Attempts: 0'. * @param int $currentgroup if there is a concept of current group where this method is being * called (e.g. a report) pass it in here. Default 0 which means no current group. * @return string HTML fragment for the link. */ - public function quiz_attempt_summary_link_to_reports($quiz, $cm, $context, - $returnzero = false, $currentgroup = 0) { + public function quiz_attempt_summary_link_to_reports( + $quiz, + $cm, + $context, + $returnzero = false, + $currentgroup = 0 + ) { global $CFG; $summary = quiz_num_attempt_summary($quiz, $cm, $returnzero, $currentgroup); if (!$summary) { @@ -1344,7 +1554,9 @@ class renderer extends plugin_renderer_base { require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php'); $url = new moodle_url('/mod/quiz/report.php', [ - 'id' => $cm->id, 'mode' => quiz_report_default_report($context)]); + 'id' => $cm->id, + 'mode' => quiz_report_default_report($context), + ]); return html_writer::link($url, $summary); } @@ -1357,18 +1569,21 @@ class renderer extends plugin_renderer_base { * @return string HTML fragment for the link. */ public function quiz_override_summary_links(stdClass $quiz, stdClass $cm, $currentgroup = 0): string { - $baseurl = new moodle_url('/mod/quiz/overrides.php', ['cmid' => $cm->id]); $counts = quiz_override_summary($quiz, $cm, $currentgroup); $links = []; if ($counts['group']) { - $links[] = html_writer::link(new moodle_url($baseurl, ['mode' => 'group']), - get_string('overridessummarygroup', 'quiz', $counts['group'])); + $links[] = html_writer::link( + new moodle_url($baseurl, ['mode' => 'group']), + get_string('overridessummarygroup', 'quiz', $counts['group']) + ); } if ($counts['user']) { - $links[] = html_writer::link(new moodle_url($baseurl, ['mode' => 'user']), - get_string('overridessummaryuser', 'quiz', $counts['user'])); + $links[] = html_writer::link( + new moodle_url($baseurl, ['mode' => 'user']), + get_string('overridessummaryuser', 'quiz', $counts['user']) + ); } if (!$links) { @@ -1400,8 +1615,11 @@ class renderer extends plugin_renderer_base { * @return string HTML of the graph. */ public function chart(\core\chart_base $chart, $title, $attrs = []) { - return $this->heading($title, 3) . html_writer::tag('div', - $this->render($chart), array_merge(['class' => 'graph'], $attrs)); + return $this->heading($title, 3) . html_writer::tag( + 'div', + $this->render($chart), + array_merge(['class' => 'graph'], $attrs) + ); } /** @@ -1425,9 +1643,18 @@ class renderer extends plugin_renderer_base { $options = ['filter' => false, 'newlines' => false]; $warning = format_text(get_string('connectionerror', 'quiz'), FORMAT_MARKDOWN, $options); $ok = format_text(get_string('connectionok', 'quiz'), FORMAT_MARKDOWN, $options); - return html_writer::tag('div', $warning, - ['id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert']) . - html_writer::tag('div', $ok, ['id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert']); + $warningtag = html_writer::tag( + 'div', + $warning, + ['id' => 'connection-error', 'style' => 'display: none;', 'role' => 'alert'] + ); + $okaytag = html_writer::tag( + 'div', + $ok, + ['id' => 'connection-ok', 'style' => 'display: none;', 'role' => 'alert'] + ); + + return $warningtag . $okaytag; } /** diff --git a/mod/quiz/classes/output/view_page.php b/mod/quiz/classes/output/view_page.php index ec437bfafa..275ca98db7 100644 --- a/mod/quiz/classes/output/view_page.php +++ b/mod/quiz/classes/output/view_page.php @@ -16,10 +16,6 @@ namespace mod_quiz\output; -use mod_quiz\access_manager; -use mod_quiz\form\preflight_check_form; -use mod_quiz\quiz_attempt; -use moodle_url; /** * This class captures all the various information to render the front page of the quiz activity. @@ -46,7 +42,7 @@ class view_page { public $canreviewmine; /** @var bool $canedit whether the current user has the capability to edit the quiz. */ public $canedit; - /** @var moodle_url $editurl the URL for editing this quiz. */ + /** @var \moodle_url $editurl the URL for editing this quiz. */ public $editurl; /** @var int $attemptcolumn contains the number of attempts done. */ public $attemptcolumn; @@ -80,12 +76,12 @@ class view_page { /** @var string $buttontext caption for the start attempt button. If this is null, show no * button, or if it is '' show a back to the course button. */ public $buttontext; - /** @var moodle_url $startattempturl URL to start an attempt. */ + /** @var \moodle_url $startattempturl URL to start an attempt. */ public $startattempturl; /** @var preflight_check_form|null $preflightcheckform confirmation form that must be * submitted before an attempt is started, if required. */ public $preflightcheckform; - /** @var moodle_url $startattempturl URL for any Back to the course button. */ + /** @var \moodle_url $startattempturl URL for any Back to the course button. */ public $backtocourseurl; /** @var bool $showbacktocourse should we show a back to the course button? */ public $showbacktocourse; diff --git a/mod/quiz/classes/quiz_attempt.php b/mod/quiz/classes/quiz_attempt.php index ff91e24750..dc4dfffedb 100644 --- a/mod/quiz/classes/quiz_attempt.php +++ b/mod/quiz/classes/quiz_attempt.php @@ -18,7 +18,6 @@ namespace mod_quiz; use action_link; use block_contents; -use cm_info; use coding_exception; use context_module; use Exception; @@ -37,7 +36,6 @@ use question_display_options; use question_engine; use question_out_of_sequence_exception; use question_state; -use question_usage_by_activity; use stdClass; /** @@ -67,7 +65,7 @@ class quiz_attempt { /** @var stdClass the quiz_attempts row. */ protected $attempt; - /** @var question_usage_by_activity the question usage for this quiz attempt. */ + /** @var \question_usage_by_activity the question usage for this quiz attempt. */ protected $quba; /** @@ -100,7 +98,7 @@ class quiz_attempt { * * @param stdClass $attempt the row of the quiz_attempts table. * @param stdClass $quiz the quiz object for this attempt and user. - * @param stdClass|cm_info $cm the course_module object for this quiz. + * @param stdClass|\cm_info $cm the course_module object for this quiz. * @param stdClass $course the row from the course table for the course we belong to. * @param bool $loadquestions (optional) if true, the default, load all the details * of the state of each question. Else just set up the basic details of the attempt. @@ -175,10 +173,17 @@ class quiz_attempt { } $this->quba = question_engine::load_questions_usage_by_activity($this->attempt->uniqueid); - $this->slots = $DB->get_records('quiz_slots', - ['quizid' => $this->get_quizid()], 'slot', 'slot, id, requireprevious, displaynumber'); - $this->sections = array_values($DB->get_records('quiz_sections', - ['quizid' => $this->get_quizid()], 'firstslot')); + $this->slots = $DB->get_records( + 'quiz_slots', + ['quizid' => $this->get_quizid()], + 'slot', + 'slot, id, requireprevious, displaynumber' + ); + $this->sections = array_values($DB->get_records( + 'quiz_sections', + ['quizid' => $this->get_quizid()], + 'firstslot' + )); $this->link_sections_and_slots(); $this->determine_layout(); @@ -212,7 +217,6 @@ class quiz_attempt { * Parse attempt->layout to populate the other arrays that represent the layout. */ protected function determine_layout() { - // Break up the layout string into pages. $pagelayouts = explode(',0', $this->attempt->layout); @@ -348,7 +352,7 @@ class quiz_attempt { /** * Get the course_module for this quiz. * - * @return stdClass|cm_info the course_module object. + * @return stdClass|\cm_info the course_module object. */ public function get_cm() { return $this->quizobj->get_cm(); @@ -524,15 +528,20 @@ class quiz_attempt { } $cm = $this->get_cm(); - if ($this->has_capability('moodle/site:accessallgroups') || - groups_get_activity_groupmode($cm) != SEPARATEGROUPS) { + if ( + $this->has_capability('moodle/site:accessallgroups') || + groups_get_activity_groupmode($cm) != SEPARATEGROUPS + ) { return true; } // Check the users have at least one group in common. $teachersgroups = groups_get_activity_allowed_groups($cm); $studentsgroups = groups_get_all_groups( - $cm->course, $this->attempt->userid, $cm->groupingid); + $cm->course, + $this->attempt->userid, + $cm->groupingid + ); return $teachersgroups && $studentsgroups && array_intersect(array_keys($teachersgroups), array_keys($studentsgroups)); } @@ -594,8 +603,11 @@ class quiz_attempt { * @return string the feedback. */ public function get_overall_feedback($grade) { - return quiz_feedback_for_grade($grade, $this->get_quiz(), - $this->quizobj->get_context()); + return quiz_feedback_for_grade( + $grade, + $this->get_quiz(), + $this->quizobj->get_context() + ); } /** @@ -641,8 +653,10 @@ class quiz_attempt { return; } - if ($this->has_capability('mod/quiz:viewreports') || - $this->has_capability('mod/quiz:preview')) { + if ( + $this->has_capability('mod/quiz:viewreports') || + $this->has_capability('mod/quiz:preview') + ) { // User has the permission that lets teachers review. Fine. return; } @@ -689,8 +703,11 @@ class quiz_attempt { public function get_display_options($reviewing) { if ($reviewing) { if (is_null($this->reviewoptions)) { - $this->reviewoptions = quiz_get_review_options($this->get_quiz(), - $this->attempt, $this->quizobj->get_context()); + $this->reviewoptions = quiz_get_review_options( + $this->get_quiz(), + $this->attempt, + $this->quizobj->get_context() + ); if ($this->is_own_preview()) { // It should always be possible for a teacher to review their // own preview irrespective of the review options settings. @@ -698,10 +715,11 @@ class quiz_attempt { } } return $this->reviewoptions; - } else { - $options = display_options::make_from_quiz($this->get_quiz(), - display_options::DURING); + $options = display_options::make_from_quiz( + $this->get_quiz(), + display_options::DURING + ); $options->flags = quiz_get_flag_option($this->attempt, $this->quizobj->get_context()); return $options; } @@ -790,7 +808,7 @@ class quiz_attempt { /** * Helper method for unit tests. Get the underlying question usage object. * - * @return question_usage_by_activity the usage. + * @return \question_usage_by_activity the usage. */ public function get_question_usage() { if (!(PHPUNIT_TEST || defined('BEHAT_TEST'))) { @@ -1103,7 +1121,7 @@ class quiz_attempt { * @param int $page the page number (starting with 0) in the attempt. * @return string attempt page title. */ - public function attempt_page_title(int $page) : string { + public function attempt_page_title(int $page): string { if ($this->get_num_pages() > 1) { $a = new stdClass(); $a->name = $this->get_quiz_name(); @@ -1136,7 +1154,7 @@ class quiz_attempt { * * @return string summary page title. */ - public function summary_page_title() : string { + public function summary_page_title(): string { return get_string('attemptsummarytitle', 'quiz', $this->get_quiz_name()); } @@ -1165,7 +1183,7 @@ class quiz_attempt { * @param bool $showall whether the review page contains the entire attempt on one page. * @return string title of the review page. */ - public function review_page_title(int $page, bool $showall = false) : string { + public function review_page_title(int $page, bool $showall = false): string { if (!$showall && $this->get_num_pages() > 1) { $a = new stdClass(); $a->name = $this->get_quiz_name(); @@ -1216,7 +1234,9 @@ class quiz_attempt { */ public function cannot_review_message($short = false) { return $this->quizobj->cannot_review_message( - $this->get_attempt_state(), $short); + $this->get_attempt_state(), + $short + ); } /** @@ -1258,9 +1278,13 @@ class quiz_attempt { public function restart_preview_button() { global $OUTPUT; if ($this->is_preview() && $this->is_preview_user()) { - return $OUTPUT->single_button(new moodle_url( - $this->start_attempt_url(), ['forcenew' => true]), - get_string('startnewpreview', 'quiz')); + return $OUTPUT->single_button( + new moodle_url( + $this->start_attempt_url(), + ['forcenew' => true] + ), + get_string('startnewpreview', 'quiz') + ); } else { return ''; } @@ -1285,9 +1309,13 @@ class quiz_attempt { $displayoptions->history = question_display_options::HIDDEN; $displayoptions->readonly = true; - return html_writer::div($placeholderqa->render($displayoptions, - $this->get_question_number($this->get_original_slot($slot))), - 'mod_quiz-blocked_question_warning'); + return html_writer::div( + $placeholderqa->render( + $displayoptions, + $this->get_question_number($this->get_original_slot($slot)) + ), + 'mod_quiz-blocked_question_warning' + ); } return $this->render_question_helper($slot, $reviewing, $thispageurl, $renderer, null); @@ -1303,8 +1331,13 @@ class quiz_attempt { * @param int|null $seq the seq number of the past state to display. * @return string HTML fragment. */ - protected function render_question_helper($slot, $reviewing, $thispageurl, - renderer $renderer, $seq) { + protected function render_question_helper( + $slot, + $reviewing, + $thispageurl, + renderer $renderer, + $seq + ) { $originalslot = $this->get_original_slot($slot); $number = $this->get_question_number($originalslot); $displayoptions = $this->get_display_options_with_edit_link($reviewing, $slot, $thispageurl); @@ -1316,14 +1349,18 @@ class quiz_attempt { if ($this->can_question_be_redone_now($slot)) { $displayoptions->extrainfocontent = $renderer->redo_question_button( - $slot, $displayoptions->readonly); + $slot, + $displayoptions->readonly + ); } if ($displayoptions->history && $displayoptions->questionreviewlink) { $links = $this->links_to_other_redos($slot, $displayoptions->questionreviewlink); if ($links) { - $displayoptions->extrahistorycontent = html_writer::tag('p', - get_string('redoesofthisquestion', 'quiz', $renderer->render($links))); + $displayoptions->extrahistorycontent = html_writer::tag( + 'p', + get_string('redoesofthisquestion', 'quiz', $renderer->render($links)) + ); } } @@ -1370,8 +1407,12 @@ class quiz_attempt { $question->createdby = null; $question->modifiedby = null; - $placeholderqa = new question_attempt($question, $this->quba->get_id(), - null, $this->quba->get_question_max_mark($slot)); + $placeholderqa = new question_attempt( + $question, + $this->quba->get_id(), + null, + $this->quba->get_question_max_mark($slot) + ); $placeholderqa->set_slot($slot); $placeholderqa->start($this->get_quiz()->preferredbehaviour, 1); $placeholderqa->set_flagged($this->is_question_flagged($slot)); @@ -1389,8 +1430,13 @@ class quiz_attempt { * @param moodle_url $thispageurl the URL of the page this question is being printed on. * @return string HTML for the question in its current state. */ - public function render_question_at_step($slot, $seq, $reviewing, - renderer $renderer, $thispageurl = null) { + public function render_question_at_step( + $slot, + $seq, + $reviewing, + renderer $renderer, + $thispageurl = null + ) { return $this->render_question_helper($slot, $reviewing, $thispageurl, $renderer, $seq); } @@ -1404,8 +1450,11 @@ class quiz_attempt { $options = $this->get_display_options(true); $options->generalfeedback = question_display_options::HIDDEN; $options->manualcomment = question_display_options::EDITABLE; - return $this->quba->render_question($slot, $options, - $this->get_question_number($slot)); + return $this->quba->render_question( + $slot, + $options, + $this->get_question_number($slot) + ); } /** @@ -1420,8 +1469,15 @@ class quiz_attempt { * @param bool $forcedownload whether to force download. * @return bool true if the file can be accessed. */ - public function check_file_access($slot, $reviewing, $contextid, $component, - $filearea, $args, $forcedownload) { + public function check_file_access( + $slot, + $reviewing, + $contextid, + $component, + $filearea, + $args, + $forcedownload + ) { $options = $this->get_display_options($reviewing); // Check permissions - warning there is similar code in review.php and @@ -1434,8 +1490,14 @@ class quiz_attempt { return false; } - return $this->quba->check_file_access($slot, $options, - $component, $filearea, $args, $forcedownload); + return $this->quba->check_file_access( + $slot, + $options, + $component, + $filearea, + $args, + $forcedownload + ); } /** @@ -1447,8 +1509,12 @@ class quiz_attempt { * @param bool $showall whether we are showing the whole quiz on one page. (Used by review.php.) * @return block_contents the requested object. */ - public function get_navigation_panel(renderer $output, - $panelclass, $page, $showall = false) { + public function get_navigation_panel( + renderer $output, + $panelclass, + $page, + $showall = false + ) { $panel = new $panelclass($this, $this->get_display_options(true), $page, $showall); $bc = new block_contents(); @@ -1522,10 +1588,17 @@ class quiz_attempt { $links->links[$index] = null; } else { $url = new moodle_url($baseurl, ['slot' => $qa->get_slot()]); - $links->links[$index] = new action_link($url, $index, - new popup_action('click', $url, 'reviewquestion', - ['width' => 450, 'height' => 650]), - ['title' => get_string('reviewresponse', 'question')]); + $links->links[$index] = new action_link( + $url, + $index, + new popup_action( + 'click', + $url, + 'reviewquestion', + ['width' => 450, 'height' => 650] + ), + ['title' => get_string('reviewresponse', 'question')] + ); } $index++; } @@ -1541,7 +1614,6 @@ class quiz_attempt { * @param bool $studentisonline is the student currently interacting with Moodle? */ public function handle_if_time_expired($timestamp, $studentisonline) { - $timeclose = $this->get_access_manager($timestamp)->get_end_time($this->attempt); if ($timeclose === false || $this->is_preview()) { @@ -1658,13 +1730,21 @@ class quiz_attempt { } $qubaids = new \mod_quiz\question\qubaids_for_users_attempts( - $this->get_quizid(), $this->get_userid(), 'all', true); + $this->get_quizid(), + $this->get_userid(), + 'all', + true + ); $transaction = $DB->start_delegated_transaction(); // Add the question to the usage. It is important we do this before we choose a variant. - $newquestionid = qbank_helper::choose_question_for_redo($this->get_quizid(), - $this->get_quizobj()->get_context(), $this->slots[$slot]->id, $qubaids); + $newquestionid = qbank_helper::choose_question_for_redo( + $this->get_quizid(), + $this->get_quizobj()->get_context(), + $this->slots[$slot]->id, + $qubaids + ); $newquestion = question_bank::load_question($newquestionid, $this->get_quiz()->shuffleanswers); $newslot = $this->quba->add_question_in_place_of_other($slot, $newquestion); @@ -1673,9 +1753,13 @@ class quiz_attempt { $variant = 1; } else { $variantstrategy = new \core_question\engine\variants\least_used_strategy( - $this->quba, $qubaids); - $variant = $variantstrategy->choose_variant($newquestion->get_num_variants(), - $newquestion->get_variants_selection_seed()); + $this->quba, + $qubaids + ); + $variant = $variantstrategy->choose_variant( + $newquestion->get_num_variants(), + $newquestion->get_variants_selection_seed() + ); } // Start the question. @@ -1752,9 +1836,14 @@ class quiz_attempt { $this->attempt->timecheckstate = null; $this->attempt->gradednotificationsenttime = null; - if (!$this->requires_manual_grading() || - !has_capability('mod/quiz:emailnotifyattemptgraded', $this->get_quizobj()->get_context(), - $this->get_userid())) { + if ( + !$this->requires_manual_grading() || + !has_capability( + 'mod/quiz:emailnotifyattemptgraded', + $this->get_quizobj()->get_context(), + $this->get_userid() + ) + ) { $this->attempt->gradednotificationsenttime = $this->attempt->timefinish; } @@ -1848,8 +1937,8 @@ class quiz_attempt { 'other' => [ 'submitterid' => CLI_SCRIPT ? null : $USER->id, 'quizid' => $quizrecord->id, - 'studentisonline' => $studentisonline - ] + 'studentisonline' => $studentisonline, + ], ]; $event = $eventclass::create($params); $event->add_record_snapshot('quiz', $this->get_quiz()); @@ -1875,7 +1964,6 @@ class quiz_attempt { * @return moodle_url The requested URL. */ protected function page_and_question_url($script, $slot, $page, $showall, $thispage) { - $defaultshowall = $this->get_default_show_all($script); if ($showall === null && ($page == 0 || $page == -1)) { $showall = $defaultshowall; @@ -1910,10 +1998,11 @@ class quiz_attempt { // Work out the correct start to the URL. if ($thispage == $page) { return new moodle_url($fragment); - } else { - $url = new moodle_url('/mod/quiz/' . $script . '.php' . $fragment, - ['attempt' => $this->attempt->id, 'cmid' => $this->get_cmid()]); + $url = new moodle_url( + '/mod/quiz/' . $script . '.php' . $fragment, + ['attempt' => $this->attempt->id, 'cmid' => $this->get_cmid()] + ); if ($page == 0 && $showall != $defaultshowall) { $url->param('showall', (int) $showall); } else if ($page > 0) { @@ -1990,9 +2079,11 @@ class quiz_attempt { $this->process_submitted_actions($timenow, $becomingoverdue); $this->fire_attempt_updated_event(); } catch (question_out_of_sequence_exception $e) { - throw new moodle_exception('submissionoutofsequencefriendlymessage', 'question', - $this->attempt_url(null, $thispage)); - + throw new moodle_exception( + 'submissionoutofsequencefriendlymessage', + 'question', + $this->attempt_url(null, $thispage) + ); } catch (Exception $e) { // This sucks, if we display our own custom error message, there is no way // to display the original stack trace. @@ -2000,8 +2091,13 @@ class quiz_attempt { if (!empty($e->debuginfo)) { $debuginfo = $e->debuginfo; } - throw new moodle_exception('errorprocessingresponses', 'question', - $this->attempt_url(null, $thispage), $e->getMessage(), $debuginfo); + throw new moodle_exception( + 'errorprocessingresponses', + 'question', + $this->attempt_url(null, $thispage), + $e->getMessage(), + $debuginfo + ); } if (!$becomingoverdue) { @@ -2011,7 +2107,6 @@ class quiz_attempt { } } } - } else { // The student is too late. $this->process_going_overdue($timenow, true); @@ -2037,11 +2132,12 @@ class quiz_attempt { } $this->process_finish($timenow, !$toolate, $finishtime, true); } - } catch (question_out_of_sequence_exception $e) { - throw new moodle_exception('submissionoutofsequencefriendlymessage', 'question', - $this->attempt_url(null, $thispage)); - + throw new moodle_exception( + 'submissionoutofsequencefriendlymessage', + 'question', + $this->attempt_url(null, $thispage) + ); } catch (Exception $e) { // This sucks, if we display our own custom error message, there is no way // to display the original stack trace. @@ -2049,8 +2145,13 @@ class quiz_attempt { if (!empty($e->debuginfo)) { $debuginfo = $e->debuginfo; } - throw new moodle_exception('errorprocessingresponses', 'question', - $this->attempt_url(null, $thispage), $e->getMessage(), $debuginfo); + throw new moodle_exception( + 'errorprocessingresponses', + 'question', + $this->attempt_url(null, $thispage), + $e->getMessage(), + $debuginfo + ); } // Send the user to the review page. @@ -2111,8 +2212,8 @@ class quiz_attempt { 'context' => context_module::instance($this->get_cmid()), 'other' => [ 'quizid' => $this->get_quizid(), - 'page' => $this->get_currentpage() - ] + 'page' => $this->get_currentpage(), + ], ]; $event = \mod_quiz\event\attempt_viewed::create($params); $event->add_record_snapshot('quiz_attempts', $this->get_attempt()); @@ -2132,8 +2233,8 @@ class quiz_attempt { 'context' => context_module::instance($this->get_cmid()), 'other' => [ 'quizid' => $this->get_quizid(), - 'page' => $this->get_currentpage() - ] + 'page' => $this->get_currentpage(), + ], ]; $event = \mod_quiz\event\attempt_updated::create($params); $event->add_record_snapshot('quiz_attempts', $this->get_attempt()); @@ -2153,8 +2254,8 @@ class quiz_attempt { 'context' => context_module::instance($this->get_cmid()), 'other' => [ 'quizid' => $this->get_quizid(), - 'page' => $this->get_currentpage() - ] + 'page' => $this->get_currentpage(), + ], ]; $event = \mod_quiz\event\attempt_autosaved::create($params); $event->add_record_snapshot('quiz_attempts', $this->get_attempt()); @@ -2178,8 +2279,8 @@ class quiz_attempt { 'quizid' => $this->get_quizid(), 'page' => $this->get_currentpage(), 'slot' => $slot, - 'newquestionid' => $newquestionid - ] + 'newquestionid' => $newquestionid, + ], ]; $event = \mod_quiz\event\attempt_question_restarted::create($params); $event->add_record_snapshot('quiz_attempts', $this->get_attempt()); @@ -2192,15 +2293,14 @@ class quiz_attempt { * @since Moodle 3.1 */ public function fire_attempt_summary_viewed_event() { - $params = [ 'objectid' => $this->get_attemptid(), 'relateduserid' => $this->get_userid(), 'courseid' => $this->get_courseid(), 'context' => context_module::instance($this->get_cmid()), 'other' => [ - 'quizid' => $this->get_quizid() - ] + 'quizid' => $this->get_quizid(), + ], ]; $event = \mod_quiz\event\attempt_summary_viewed::create($params); $event->add_record_snapshot('quiz_attempts', $this->get_attempt()); @@ -2213,15 +2313,14 @@ class quiz_attempt { * @since Moodle 3.1 */ public function fire_attempt_reviewed_event() { - $params = [ 'objectid' => $this->get_attemptid(), 'relateduserid' => $this->get_userid(), 'courseid' => $this->get_courseid(), 'context' => context_module::instance($this->get_cmid()), 'other' => [ - 'quizid' => $this->get_quizid() - ] + 'quizid' => $this->get_quizid(), + ], ]; $event = \mod_quiz\event\attempt_reviewed::create($params); $event->add_record_snapshot('quiz_attempts', $this->get_attempt()); @@ -2238,8 +2337,8 @@ class quiz_attempt { 'courseid' => $this->get_courseid(), 'context' => context_module::instance($this->get_cmid()), 'other' => [ - 'quizid' => $this->get_quizid() - ] + 'quizid' => $this->get_quizid(), + ], ]; $event = \mod_quiz\event\attempt_manual_grading_completed::create($params); diff --git a/mod/quiz/classes/quiz_settings.php b/mod/quiz/classes/quiz_settings.php index de053228c9..f147571a14 100644 --- a/mod/quiz/classes/quiz_settings.php +++ b/mod/quiz/classes/quiz_settings.php @@ -17,14 +17,12 @@ namespace mod_quiz; use coding_exception; -use context; use context_module; use mod_quiz\question\bank\qbank_helper; use mod_quiz\question\display_options; use moodle_exception; use moodle_url; use question_bank; -use stdClass; /** * A class encapsulating the settings for a quiz. @@ -41,22 +39,22 @@ use stdClass; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class quiz_settings { - /** @var stdClass the course settings from the database. */ + /** @var \stdClass the course settings from the database. */ protected $course; - /** @var stdClass the course_module settings from the database. */ + /** @var \stdClass the course_module settings from the database. */ protected $cm; - /** @var stdClass the quiz settings from the database. */ + /** @var \stdClass the quiz settings from the database. */ protected $quiz; - /** @var context the quiz context. */ + /** @var \context the quiz context. */ protected $context; /** - * @var stdClass[] of questions augmented with slot information. For non-random + * @var \stdClass[] of questions augmented with slot information. For non-random * questions, the array key is question id. For random quesions it is 's' . $slotid. * probalby best to use ->questionid field of the object instead. */ protected $questions = null; - /** @var stdClass[] of quiz_section rows. */ + /** @var \stdClass[] of quiz_section rows. */ protected $sections = null; /** @var access_manager the access manager for this quiz. */ protected $accessmanager = null; @@ -194,7 +192,7 @@ class quiz_settings { /** * Get the quiz settings object. * - * @return stdClass the row of the quiz table. + * @return \stdClass the row of the quiz table. */ public function get_quiz() { return $this->quiz; @@ -248,7 +246,7 @@ class quiz_settings { /** * Get the quiz context. * - * @return context_module the module context for this quiz. + * @return \context_module the module context for this quiz. */ public function get_context() { return $this->context; @@ -301,7 +299,7 @@ class quiz_settings { * Get a particular question in this quiz, by its id. * * @param int $id the question id. - * @return stdClass the question object with that id. + * @return \stdClass the question object with that id. */ public function get_question($id) { return $this->questions[$id]; @@ -311,7 +309,7 @@ class quiz_settings { * Get some of the question in this quiz. * * @param array|null $questionids question ids of the questions to load. null for all. - * @return stdClass[] the question data objects. + * @return \stdClass[] the question data objects. */ public function get_questions($questionids = null) { if (is_null($questionids)) { @@ -336,8 +334,11 @@ class quiz_settings { public function get_sections() { global $DB; if ($this->sections === null) { - $this->sections = array_values($DB->get_records('quiz_sections', - ['quizid' => $this->get_quizid()], 'firstslot')); + $this->sections = array_values($DB->get_records( + 'quiz_sections', + ['quizid' => $this->get_quizid()], + 'firstslot' + )); } return $this->sections; } @@ -352,8 +353,11 @@ class quiz_settings { */ public function get_access_manager($timenow) { if (is_null($this->accessmanager)) { - $this->accessmanager = new access_manager($this, $timenow, - has_capability('mod/quiz:ignoretimelimits', $this->context, null, false)); + $this->accessmanager = new access_manager( + $this, + $timenow, + has_capability('mod/quiz:ignoretimelimits', $this->context, null, false) + ); } return $this->accessmanager; } @@ -462,7 +466,6 @@ class quiz_settings { * @return string an appropraite message. */ public function cannot_review_message($when, $short = false) { - if ($short) { $langstrsuffix = 'short'; $dateformat = get_string('strftimedatetimeshort', 'langconfig'); @@ -471,14 +474,21 @@ class quiz_settings { $dateformat = ''; } - if ($when == display_options::DURING || - $when == display_options::IMMEDIATELY_AFTER) { + if ( + $when == display_options::DURING || + $when == display_options::IMMEDIATELY_AFTER + ) { return ''; } else { - if ($when == display_options::LATER_WHILE_OPEN && $this->quiz->timeclose && - $this->quiz->reviewattempt & display_options::AFTER_CLOSE) { - return get_string('noreviewuntil' . $langstrsuffix, 'quiz', - userdate($this->quiz->timeclose, $dateformat)); + if ( + $when == display_options::LATER_WHILE_OPEN && $this->quiz->timeclose && + $this->quiz->reviewattempt & display_options::AFTER_CLOSE + ) { + return get_string( + 'noreviewuntil' . $langstrsuffix, + 'quiz', + userdate($this->quiz->timeclose, $dateformat) + ); } else { return get_string('noreview' . $langstrsuffix, 'quiz'); } diff --git a/mod/quiz/classes/task/update_overdue_attempts.php b/mod/quiz/classes/task/update_overdue_attempts.php index e83c08f344..2426c5fd06 100644 --- a/mod/quiz/classes/task/update_overdue_attempts.php +++ b/mod/quiz/classes/task/update_overdue_attempts.php @@ -57,7 +57,7 @@ class update_overdue_attempts extends \core\task\scheduled_task { mtrace(' Looking for quiz overdue quiz attempts...'); - list($count, $quizcount) = $this->update_all_overdue_attempts($timenow, $processto); + [$count, $quizcount] = $this->update_all_overdue_attempts($timenow, $processto); mtrace(' Considered ' . $count . ' attempts in ' . $quizcount . ' quizzes.'); } @@ -82,17 +82,16 @@ class update_overdue_attempts extends \core\task\scheduled_task { $quizcount = 0; foreach ($attemptstoprocess as $attempt) { try { - // If we have moved on to a different quiz, fetch the new data. if (!$quiz || $attempt->quiz != $quiz->id) { - $quiz = $DB->get_record('quiz', array('id' => $attempt->quiz), '*', MUST_EXIST); + $quiz = $DB->get_record('quiz', ['id' => $attempt->quiz], '*', MUST_EXIST); $cm = get_coursemodule_from_instance('quiz', $attempt->quiz); $quizcount += 1; } // If we have moved on to a different course, fetch the new data. if (!$course || $course->id != $quiz->course) { - $course = $DB->get_record('course', array('id' => $quiz->course), '*', MUST_EXIST); + $course = $DB->get_record('course', ['id' => $quiz->course], '*', MUST_EXIST); } // Make a specialised version of the quiz settings, with the relevant overrides. @@ -104,7 +103,6 @@ class update_overdue_attempts extends \core\task\scheduled_task { $attemptobj = new quiz_attempt($attempt, $quizforuser, $cm, $course); $attemptobj->handle_if_time_expired($timenow, false); $count += 1; - } catch (moodle_exception $e) { // If an error occurs while processing one attempt, don't let that kill cron. mtrace("Error while processing attempt $attempt->id at $attempt->quiz quiz:"); @@ -117,27 +115,27 @@ class update_overdue_attempts extends \core\task\scheduled_task { } $attemptstoprocess->close(); - return array($count, $quizcount); + return [$count, $quizcount]; } /** * Get a recordset of all the attempts that need to be processed now. * - * (Only public to allow unit testing. Do not use!) - * * @param int $processto timestamp to process up to. * @return moodle_recordset of quiz_attempts that need to be processed because time has * passed, sorted by courseid then quizid. */ - public function get_list_of_overdue_attempts(int $processto): moodle_recordset { + protected function get_list_of_overdue_attempts(int $processto): moodle_recordset { global $DB; // SQL to compute timeclose and timelimit for each attempt. $quizausersql = quiz_get_attempt_usertime_sql( - "iquiza.state IN ('inprogress', 'overdue') AND iquiza.timecheckstate <= :iprocessto"); + "iquiza.state IN ('inprogress', 'overdue') AND iquiza.timecheckstate <= :iprocessto" + ); // This query should have all the quiz_attempts columns. - return $DB->get_recordset_sql(" + return $DB->get_recordset_sql( + " SELECT quiza.*, quizauser.usertimeclose, quizauser.usertimelimit @@ -149,7 +147,7 @@ class update_overdue_attempts extends \core\task\scheduled_task { WHERE quiza.state IN ('inprogress', 'overdue') AND quiza.timecheckstate <= :processto ORDER BY quiz.course, quiza.quiz", - - array('processto' => $processto, 'iprocessto' => $processto)); + ['processto' => $processto, 'iprocessto' => $processto] + ); } } diff --git a/mod/quiz/deprecatedlib.php b/mod/quiz/deprecatedlib.php index 69982742a7..be21e05bfe 100644 --- a/mod/quiz/deprecatedlib.php +++ b/mod/quiz/deprecatedlib.php @@ -157,10 +157,11 @@ class mod_quiz_overdue_attempt_updater { /** * @deprecated since Moodle 4.2. Code moved to mod_quiz\task\update_overdue_attempts. */ - public function get_list_of_overdue_attempts($processto) { - debugging('mod_quiz_overdue_attempt_updater has been deprecated. The code wsa moved to ' . - 'mod_quiz\task\update_overdue_attempts.'); - return (new update_overdue_attempts())->get_list_of_overdue_attempts((int) $processto); + public function get_list_of_overdue_attempts() { + throw new \coding_exception( + 'mod_quiz_overdue_attempt_updater has been deprecated. ' . + 'The code was moved to mod_quiz\task\update_overdue_attempts and should be called using the Task API.' + ); } } diff --git a/mod/quiz/tests/attempts_test.php b/mod/quiz/tests/attempts_test.php index 1de3efb873..f6601e8c34 100644 --- a/mod/quiz/tests/attempts_test.php +++ b/mod/quiz/tests/attempts_test.php @@ -40,6 +40,9 @@ class attempts_test extends \advanced_testcase { /** * Test the functions quiz_update_open_attempts(), get_list_of_overdue_attempts() and * update_overdue_attempts(). + * + * @covers \mod_quiz\task\update_overdue_attempts::get_list_of_overdue_attempts + * @covers ::quiz_update_open_attempts */ public function test_bulk_update_functions() { global $DB; @@ -389,8 +392,12 @@ class attempts_test extends \advanced_testcase { // $overduehander = new update_overdue_attempts(); + $rc = new \ReflectionClass($overduehander); + $rcm = $rc->getMethod('get_list_of_overdue_attempts'); + $rcm->setAccessible(true); - $attempts = $overduehander->get_list_of_overdue_attempts(100000); // way in the future + // Fetch attempts for way into the future. + $attempts = $rcm->invoke($overduehander, 100000); $count = 0; foreach ($attempts as $attempt) { $this->assertTrue(isset($usertimes[$attempt->id])); @@ -403,7 +410,8 @@ class attempts_test extends \advanced_testcase { $attempts->close(); $this->assertEquals($DB->count_records_select('quiz_attempts', 'timecheckstate IS NOT NULL'), $count); - $attempts = $overduehander->get_list_of_overdue_attempts(0); // before all attempts + // Fetch attempts before all attempts. + $attempts = $rcm->invoke($overduehander, 0); $count = 0; foreach ($attempts as $attempt) { $count++; -- 2.39.0