diff --git a/drawchart.php b/drawchart.php index ab50fe83..3a7d9f31 100644 --- a/drawchart.php +++ b/drawchart.php @@ -64,6 +64,7 @@ function draw_chart($feedbacktype, $labels, $groupname, // We do not have labels other than global in this feedback type. if ($feedbacktype == 'global') { + $globallabel = (string) $globallabel; $labels = array($globallabel); } diff --git a/lang/en/questionnaire.php b/lang/en/questionnaire.php index e28d9352..d9cd756c 100644 --- a/lang/en/questionnaire.php +++ b/lang/en/questionnaire.php @@ -709,3 +709,13 @@ $string['crontask'] = 'Questionnaire cleanup job'; $string['nopermissions'] = 'Sorry, but you do not currently have permissions to view this page or perform this action.'; $string['unanswered'] = 'Unanswered'; + +// Expanded Exception messages. +$string['groupaccessdenied'] = 'You do not belong to a group allowed to view these responses.'; +$string['noresponsesavailable'] = 'There are no responses available to view at this time.'; +$string['cannotviewduetorestrictions'] = 'You cannot view responses due to questionnaire restrictions or required completion.'; +$string['questionnaireneotopen'] = 'This questionnaire will open on {$a}.'; +$string['questionnaireclosed'] = 'This questionnaire closed on {$a}.'; +$string['mustcompletebeforeviewing'] = 'You must complete this questionnaire before viewing any responses.'; +$string['missingcapability'] = 'You do not have the required capability (mod/questionnaire:readallresponses) to view these responses.'; +$string['privateorTemplateError'] = 'This questionnaire is private or a template and cannot be accessed for responses.'; diff --git a/lib.php b/lib.php index 8b2c5fc8..89a74147 100644 --- a/lib.php +++ b/lib.php @@ -718,8 +718,8 @@ function questionnaire_extend_settings_navigation(settings_navigation $settings, // If questionnaire is set to separate groups, prevent user who is not member of any group // and is not a non-editing teacher to view All responses. - if ($questionnaire->can_view_all_responses($usernumresp)) { - + $viewallresponses = $questionnaire->can_view_all_responses($usernumresp); + if (!empty($viewallresponses) && $viewallresponses->allowed) { $url = '/mod/questionnaire/report.php'; $node = navigation_node::create(get_string('viewallresponses', 'questionnaire'), new moodle_url($url, array('instance' => $questionnaire->id, 'action' => 'vall')), diff --git a/questionnaire.class.php b/questionnaire.class.php index 5fd3bebe..fc4ab4a2 100644 --- a/questionnaire.class.php +++ b/questionnaire.class.php @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +use core_reportbuilder\external\columns\sort\get; use mod_questionnaire\feedback\section; defined('MOODLE_INTERNAL') || die(); @@ -712,37 +713,99 @@ public function can_view_response($rid) { * * @param null|int $usernumresp * @param bool $isviewreport - * @return bool + * @return object + * @throws \coding_exception + * @throws \dml_exception */ public function can_view_all_responses($usernumresp = null, $isviewreport = false) { global $USER, $SESSION; $owner = $this->is_survey_owner(); $numresp = $this->count_submissions(); + if ($usernumresp === null) { $usernumresp = $this->count_submissions($USER->id); } - // Number of Responses in currently selected group (or all participants etc.). + // If the user has not submitted any responses, then they cannot view responses. if (isset($SESSION->questionnaire->numselectedresps)) { $numselectedresps = $SESSION->questionnaire->numselectedresps; } else { $numselectedresps = $numresp; } - // If questionnaire is set to separate groups, prevent user who is not member of any group - // to view All responses. - $canviewgroups = true; - $canviewallgroups = has_capability('moodle/site:accessallgroups', $this->context); + // Verify that the user belongs to a group that can view the questionnaire. $groupmode = groups_get_activity_groupmode($this->cm, $this->course); - if ($groupmode == 1) { + $canviewallgroups = has_capability('moodle/site:accessallgroups', $this->context); + $canviewgroups = true; + + // If the questionnaire is not owned by the course, then we cannot view responses. + if ($groupmode == SEPARATEGROUPS) { $canviewgroups = groups_has_membership($this->cm, $USER->id); + if (!$canviewgroups && !$canviewallgroups) { + return (object)[ + 'allowed' => false, + 'reason' => get_string('groupaccessdenied', 'mod_questionnaire'), + ]; + } + } + + // If the questionnaire is not open yet, or has been closed, then we cannot view responses. + if (empty($this->is_open())) { + return (object)[ + 'allowed' => false, + 'reason' => get_string('questionnaireneotopen', 'mod_questionnaire', userdate($this->open)) + ]; + } + if (!empty($this->is_closed())) { + return (object)[ + 'allowed' => false, + 'reason' => get_string('questionnaireclosed', 'mod_questionnaire', userdate($this->close)) + ]; + } + + // Verify that the user has the capability to read all responses. + if ($this->resume == 1 && $usernumresp == 0) { + return (object)[ + 'allowed' => false, + 'reason' => get_string('mustcompletebeforeviewing', 'mod_questionnaire') + ]; + } + + // Verify that the user has the capability to read all responses. + if (!has_capability('mod/questionnaire:readallresponses', $this->context)) { + return (object)[ + 'allowed' => false, + 'reason' => get_string('missingcapability', 'mod_questionnaire') + ]; + } + + // Verify that there are responses to view. + if (($numresp <= 0 || $numselectedresps <= 0) && !$isviewreport) { + return (object)[ + 'allowed' => false, + 'reason' => get_string('noresponsesavailable', 'mod_questionnaire') + ]; } $grouplogic = $canviewgroups || $canviewallgroups; - $respslogic = ($numresp > 0) && ($numselectedresps > 0) || $isviewreport; - return $this->can_view_all_responses_anytime($grouplogic, $respslogic) || - $this->can_view_all_responses_with_restrictions($usernumresp, $grouplogic, $respslogic); + $respslogic = ($numresp > 0 && $numselectedresps > 0) || $isviewreport; + + // If the user can view all responses any time, then they can view them. + if ($this->can_view_all_responses_anytime($grouplogic, $respslogic)) { + return (object)['allowed' => true]; + } + + // If the user can't view all responses with restrictions. + if (!$this->can_view_all_responses_with_restrictions($usernumresp, $grouplogic, $respslogic)) { + return (object)[ + 'allowed' => false, + 'reason' => get_string('cannotviewduetorestrictions', 'mod_questionnaire') + ]; + } + + // If we got here, then the user can view the responses. + return (object)['allowed' => true]; } /** diff --git a/report.php b/report.php index 5c81c84a..d7727ac5 100755 --- a/report.php +++ b/report.php @@ -88,9 +88,16 @@ // If you can't view the questionnaire, or can't view a specified response, error out. $context = context_module::instance($cm->id); -if (!$questionnaire->can_view_all_responses(null, true) && !$individualresponse) { +$viewallresponses = $questionnaire->can_view_all_responses(null, true); +if (!$viewallresponses->allowed && !$individualresponse) { // Should never happen, unless called directly by a snoop... - throw new \moodle_exception('nopermissions', 'mod_questionnaire'); + throw new \moodle_exception( + 'nopermissions', + 'mod_questionnaire', + $CFG->wwwroot.'/mod/questionnaire/view.php?id='.$cm->id, + $viewallresponses->reason ?? get_string('viewallresponses', 'mod_questionnaire'), + 'mod/questionnaire:readallresponses' + ); } $questionnaire->canviewallgroups = has_capability('moodle/site:accessallgroups', $context); diff --git a/version.php b/version.php index 43f382ac..ffa48dfa 100644 --- a/version.php +++ b/version.php @@ -25,10 +25,9 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2022121601.01; // The current module version (Date: YYYYMMDDXX). -$plugin->requires = 2024042200.00; // Moodle version (4.4.0). +$plugin->version = 2022121601.02; // The current module version (Date: YYYYMMDDXX). +$plugin->requires = 2024042200.00; // Moodle version (4.4.0). $plugin->component = 'mod_questionnaire'; - -$plugin->release = '4.4.0 (Build - 2024082900)'; +$plugin->release = '4.5.0 (Build - 2024082901)'; $plugin->maturity = MATURITY_BETA; diff --git a/view.php b/view.php index c0181ce5..df0e95ff 100644 --- a/view.php +++ b/view.php @@ -142,7 +142,8 @@ '" class="btn btn-primary">' . $titletext . ''); } -if ($questionnaire->can_view_all_responses($usernumresp)) { +$viewallresponses = $questionnaire->can_view_all_responses($usernumresp); +if ($viewallresponses->allowed) { $argstr = 'instance='.$questionnaire->id.'&group='.$currentgroupid; $questionnaire->page->add_to_page('allresponses', ''.