diff --git a/classes/output/renderer.php b/classes/output/renderer.php index 5bc029b3..698ffc33 100755 --- a/classes/output/renderer.php +++ b/classes/output/renderer.php @@ -563,4 +563,22 @@ public function download_dataformat_selector($label, $base, $name = 'dataformat' return $this->render_from_template('mod_questionnaire/dataformat_selector', $data); } + + /** + * @param $urlroot + * @param $options + * @param $userview + * @return string + * @throws \coding_exception + * @throws \moodle_exception + */ + public function viewresponse_print_menu($urlroot, $options, $userview) { + if (!$urlroot instanceof \moodle_url) { + $urlroot = new \moodle_url($urlroot); + } + $select = new \single_select($urlroot, 'responsestats', $options, $userview, null); + $select->label = get_string('view'); + $output = $this->render($select); + return $output; + } } diff --git a/classes/responsetype/date.php b/classes/responsetype/date.php index befc5cba..6fbd2188 100644 --- a/classes/responsetype/date.php +++ b/classes/responsetype/date.php @@ -205,7 +205,7 @@ public function get_results_tags($weights, $participants, $respondents, $showtot if ($showtotals == 1) { $pagetags->total = new \stdClass(); - $pagetags->total->total = "$numresps/$participants"; + $pagetags->total->total = "($respondents)"; } } diff --git a/classes/responsetype/rank.php b/classes/responsetype/rank.php index 3d5552bc..c2c47287 100644 --- a/classes/responsetype/rank.php +++ b/classes/responsetype/rank.php @@ -888,7 +888,7 @@ private function mkrescount($rids, $rows, $sort) { $nbna = $this->counts[$content]->nbna; // TOTAL number of responses for this possible answer. $total = $this->counts[$content]->num; - $nbresp = ''.$total.''; + $nbresp = '('.$total.')'; if ($osgood) { // Ensure there are two bits of content. list($content, $contentright) = array_merge(preg_split('/[|]/', $content), array(' ')); diff --git a/classes/responsetype/responsetype.php b/classes/responsetype/responsetype.php index 59e3715d..60e9ef79 100644 --- a/classes/responsetype/responsetype.php +++ b/classes/responsetype/responsetype.php @@ -198,7 +198,7 @@ public function get_results_tags($weights, $participants, $respondents, $showtot if ($showtotals) { $pagetags->total = new \stdClass(); if ($respondents > 0) { - $percent = round((float)$respondents / (float)$participants * 100.0); + $percent = 100; } else { $percent = 0; } @@ -220,7 +220,7 @@ public function get_results_tags($weights, $participants, $respondents, $showtot $pagetags->total->width2 = $percent * 1.4; $pagetags->total->image2 = $imageurl . 'thbar.gif'; $pagetags->total->percent = sprintf(' %.'.$precision.'f%%', $percent); - $pagetags->total->total = "$respondents/$participants"; + $pagetags->total->total = "($respondents)"; $pagetags->total->evencolor = $evencolor; } } diff --git a/classes/responsetype/single.php b/classes/responsetype/single.php index d8dc2f7c..17bde4af 100644 --- a/classes/responsetype/single.php +++ b/classes/responsetype/single.php @@ -237,10 +237,18 @@ public function display_results($rids=false, $sort='', $anonymous=false) { } $numresps = count($rids); + $rsql = ''; + if (!empty($rids)) { + list($rsql, $params) = $DB->get_in_or_equal($rids); + $rsql = ' AND response_id ' . $rsql; + } + $responsecountsql = 'SELECT COUNT(DISTINCT r.response_id) ' . - 'FROM {' . $this->response_table() . '} r ' . - 'WHERE r.question_id = ? '; - $numrespondents = $DB->count_records_sql($responsecountsql, [$this->question->id]); + 'FROM {' . $this->response_table() . '} r, ' . + '{questionnaire_response} qr ' . + 'WHERE question_id = ' . $this->question->id . $rsql . + ' AND r.response_id = qr.id '; + $numrespondents = $DB->count_records_sql($responsecountsql, $params); if ($rows) { $counts = []; diff --git a/classes/responsetype/text.php b/classes/responsetype/text.php index b03b7d47..e10ba715 100644 --- a/classes/responsetype/text.php +++ b/classes/responsetype/text.php @@ -210,7 +210,7 @@ public function get_results_tags($weights, $participants, $respondents, $showtot if ($showtotals == 1) { $pagetags->total = new \stdClass(); - $pagetags->total->total = "$respondents/$participants"; + $pagetags->total->total = "($respondents)"; } } else { $nbresponses = 0; @@ -250,7 +250,7 @@ public function get_results_tags($weights, $participants, $respondents, $showtot if ($showtotals == 1) { $pagetags->total = new \stdClass(); - $pagetags->total->total = "$respondents/$participants"; + $pagetags->total->total = "($respondents)"; $pagetags->total->evencolor = $evencolor; } } diff --git a/lang/en/questionnaire.php b/lang/en/questionnaire.php index f6e35b11..d0305c9e 100644 --- a/lang/en/questionnaire.php +++ b/lang/en/questionnaire.php @@ -41,6 +41,7 @@ $string['allnameddegrees'] = 'Named degrees'; $string['allnameddegrees_help'] = 'Specify text to display for rate values instead of the number. Leave a value blank to not use.'; $string['alreadyfilled'] = 'You have already filled out this questionnaire for us{$a}. Thank you.'; +$string['allresponses'] = 'All responses'; $string['andaveragevalues'] = 'and average values'; $string['anonymous'] = 'Anonymous'; $string['answergiven'] = 'This answer given'; @@ -250,6 +251,7 @@ $string['firstrespondent'] = 'First Respondent'; $string['formateditor'] = 'HTML editor'; $string['formatplain'] = 'Plain text'; +$string['fullsubmissions'] = 'Full submissions'; $string['grade'] = 'Submission grade'; $string['gradesdeleted'] = 'Questionnaire grades deleted'; $string['headingtext'] = 'Heading text'; @@ -527,6 +529,7 @@ $string['remove'] = 'Delete'; $string['removenotinuse'] = 'This questionnaire used to depend on a Public questionnaire which has been deleted. It can no longer be used and should be deleted.'; +$string['responsesnotsubmitted'] = 'Responses not submitted'; $string['required'] = 'Response is required'; $string['required_help'] = 'If you select ***Yes***, response to this question will be required, i.e. the respondent will not be able to submit the questionnaire @@ -608,6 +611,7 @@ $string['submitpreview'] = 'Submit preview'; $string['submitpreviewcorrect'] = 'This submission would be accepted as correctly filled in.'; $string['submitsurvey'] = 'Submit questionnaire'; +$string['submissions'] = 'Submissions'; $string['submitted'] = 'Submitted on:'; $string['subtitle'] = 'Subtitle'; $string['subtitle_help'] = 'Subtitle of this questionnaire. Appears below the title on the first page only.'; diff --git a/questionnaire.class.php b/questionnaire.class.php index e366f70b..efdc7b12 100644 --- a/questionnaire.class.php +++ b/questionnaire.class.php @@ -713,10 +713,12 @@ public function can_view_response($rid) { /** * True if the user can view the responses to this questionnaire, and there are valid responses. + * * @param null|int $usernumresp + * @param bool $isviewreport * @return bool */ - public function can_view_all_responses($usernumresp = null) { + public function can_view_all_responses($usernumresp = null, $isviewreport = false) { global $USER, $SESSION; $owner = $this->is_survey_owner(); @@ -742,7 +744,7 @@ public function can_view_all_responses($usernumresp = null) { } $grouplogic = $canviewgroups || $canviewallgroups; - $respslogic = ($numresp > 0) && ($numselectedresps > 0); + $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); } @@ -855,15 +857,20 @@ public function get_responses($userid=false, $groupid=0) { $sql = 'SELECT r.* ' . 'FROM {questionnaire_response} r ' . $groupsql . - 'WHERE r.questionnaireid = :questionnaireid AND r.complete = :status' . $groupcnd; + 'WHERE r.questionnaireid = :questionnaireid' . $groupcnd; $params['questionnaireid'] = $this->id; - $params['status'] = 'y'; } if ($userid) { $sql .= ' AND r.userid = :userid'; $params['userid'] = $userid; } + $status = optional_param('responsestats', '0', PARAM_ALPHANUM); + if ($status) { + $status = ($status === 'n') ? 'n' : 'y'; + $sql .= ' AND r.complete = :status'; + $params['status'] = $status; + } $sql .= ' ORDER BY r.id'; return $DB->get_records_sql($sql, $params) ?? []; } @@ -2862,6 +2869,7 @@ public function survey_results($rid = '', $uid=false, $pdf = false, $currentgrou $numresps = 1; } else { $navbar = false; + $userview = optional_param('responsestats', 0, PARAM_ALPHA); if ($uid !== false) { // One participant only. $rows = $this->get_responses($uid); // All participants or all members of a group. @@ -2878,8 +2886,12 @@ public function survey_results($rid = '', $uid=false, $pdf = false, $currentgrou return; } $numresps = count($rows); + $respondentstring = get_string('responses', 'questionnaire'); + if ($userview === 'y') { + $respondentstring = get_string('submissions', 'questionnaire'); + } $this->page->add_to_page('respondentinfo', - ' '.get_string('responses', 'questionnaire').': '.$numresps.''); + ' ' . $respondentstring . ': ' . $numresps . ''); if (empty($rows)) { $errmsg = get_string('erroropening', 'questionnaire') .' '. get_string('noresponsedata', 'questionnaire'); return($errmsg); diff --git a/report.php b/report.php index e66b3555..abc36f5a 100755 --- a/report.php +++ b/report.php @@ -36,6 +36,7 @@ $currentgroupid = optional_param('group', 0, PARAM_INT); // Groupid. $user = optional_param('user', '', PARAM_INT); $outputtarget = optional_param('target', 'html', PARAM_ALPHA); // Default 'html'. Could be 'pdf'. +$userview = optional_param('responsestats', '0', PARAM_ALPHANUM); $userid = $USER->id; switch ($action) { @@ -87,7 +88,7 @@ // 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() && !$individualresponse) { +if (!$questionnaire->can_view_all_responses(null, true) && !$individualresponse) { // Should never happen, unless called directly by a snoop... throw new \moodle_exception('nopermissions', 'mod_questionnaire'); } @@ -205,6 +206,14 @@ } } +$responsestatus = [ + 'y' => get_string('fullsubmissions', 'questionnaire'), + '0' => get_string('allresponses', 'questionnaire'), + 'n' => get_string('responsesnotsubmitted', 'questionnaire'), +]; +// Set default userview to all responses. +$userview = array_key_exists($userview, $responsestatus) ? $userview : '0'; + switch ($action) { case 'dresp': // Delete individual response? Ask for confirmation. @@ -588,7 +597,7 @@ if ($currentgroupid > 0) { $groupname = get_string('group').': '.groups_get_group_name($currentgroupid).''; } else { - $groupname = ''.get_string('allparticipants').''; + $groupname = ''.$responsestatus[$userview].''; } // Available group modes (0 = no groups; 1 = separate groups; 2 = visible groups). @@ -633,9 +642,9 @@ if ($currentgroupid > 0) { $groupname = get_string('group') . ': ' . groups_get_group_name($currentgroupid) . ''; } else { - $groupname = '' . get_string('allparticipants') . ''; + $groupname = '' . $responsestatus[$userview] . ''; } - $respinfo = get_string('viewallresponses', 'questionnaire') . '. ' . $groupname . '. '; + $respinfo = get_string('view') . ' ' . $groupname; $strsort = get_string('order_' . $sort, 'questionnaire'); $respinfo .= $strsort; $questionnaire->page->add_to_page('respondentinfo', $respinfo); @@ -656,13 +665,15 @@ if ($outputtarget != 'print') { $linkname = get_string('downloadpdf', 'mod_questionnaire'); $link = new moodle_url('/mod/questionnaire/report.php', - ['action' => 'vall', 'instance' => $instance, 'group' => $currentgroupid, 'target' => 'pdf']); + ['action' => 'vall', 'instance' => $instance, 'group' => $currentgroupid, 'target' => 'pdf', + 'responsestats' => $userview]); $downpdficon = new pix_icon('f/pdf', $linkname); $respinfo .= $questionnaire->renderer->action_link($link, null, null, null, $downpdficon); $linkname = get_string('print', 'mod_questionnaire'); $link = new \moodle_url('/mod/questionnaire/report.php', - ['action' => 'vall', 'instance' => $instance, 'group' => $currentgroupid, 'target' => 'print']); + ['action' => 'vall', 'instance' => $instance, 'group' => $currentgroupid, 'target' => 'print', + 'responsestats' => $userview]); $htmlicon = new pix_icon('t/print', $linkname); $options = ['menubar' => true, 'location' => false, 'scrollbars' => true, 'resizable' => true, 'height' => 600, 'width' => 800, 'title' => $linkname]; @@ -672,7 +683,7 @@ $respinfo .= $questionnaire->renderer->action_link($link, null, $action, ['class' => $class, 'title' => $linkname], $htmlicon) . ' '; - $respinfo .= get_string('viewallresponses', 'questionnaire') . '. ' . $groupname . '. '; + $respinfo .= $questionnaire->renderer->viewresponse_print_menu($url->out(), $responsestatus, $userview); $strsort = get_string('order_' . $sort, 'questionnaire'); $respinfo .= $strsort; $respinfo .= $questionnaire->renderer->help_icon('orderresponses', 'questionnaire'); @@ -769,7 +780,7 @@ if ($currentgroupid > 0) { $groupname = get_string('group') . ': ' . groups_get_group_name($currentgroupid) . ''; } else { - $groupname = '' . get_string('allparticipants') . ''; + $groupname = '' . $responsestatus[$userview] . ''; } if (!$byresponse) { // Show respondents individual responses. $questionnaire->view_response($rid, '', $resps, true, true, false, $currentgroupid, $outputtarget); @@ -803,7 +814,7 @@ $groupname = get_string('group').': '.groups_get_group_name($currentgroupid).''; if ($currentgroupid == 0 ) { - $groupname = get_string('allparticipants'); + $groupname = $responsestatus[$userview]; } if ($byresponse) { $respinfo = ''; diff --git a/tests/behat/check_responses.feature b/tests/behat/check_responses.feature index 46065874..36991e22 100644 --- a/tests/behat/check_responses.feature +++ b/tests/behat/check_responses.feature @@ -34,47 +34,43 @@ Feature: Review responses And I follow "Test questionnaire" Then I should see "View all responses" And I navigate to "View all responses" in current page administration - Then I should see "View all responses." - And I should see "All participants." And I should see "View Default order" - And I should see "Responses: 6" + And I should see "Responses: 7" + And I set the field "View" to "Full submissions" + And I should see "Submissions: 6" + And I set the field "View" to "Responses not submitted" + And I should see "Responses: 1" And I follow "Ascending order" - Then I should see "View all responses." - And I should see "All participants." And I should see "Ascending order" - And I should see "Responses: 6" + And I should see "Responses: 7" And I follow "Descending order" - Then I should see "View all responses." - And I should see "All participants." And I should see "Descending order" - And I should see "Responses: 6" + And I should see "Responses: 7" And I follow "List of responses" - Then I should see "Individual responses : All participants" + Then I should see "Individual responses : All responses" And I follow "Admin User" - Then I should see "1 / 6" + Then I should see "1 / 7" And I should see "Respondent:" And I should see "Admin User" And I should see "Submitted on:" # And I should see "Thursday, 14 January 2016, 9:22 pm" And I should see "Test questionnaire" And I follow "Next" - Then I should see "2 / 6" + Then I should see "2 / 7" # And I should see "Thursday, 14 January 2016, 8:53 pm" And I follow "Last Respondent" - Then I should see "6 / 6" + Then I should see "7 / 7" # And I should see "Friday, 19 December 2014, 5:58 pm" And I follow "Delete this Response" Then I should see "Are you sure you want to delete the response" # And I should see "Friday, 19 December 2014, 5:58 pm" And I press "Delete" - Then I should see "Individual responses : All participants" + Then I should see "Individual responses : All responses" And I follow "Admin User" - Then I should see "1 / 5" + Then I should see "1 / 6" And I follow "Summary" - Then I should see "View all responses." - And I should see "All participants." And I should see "View Default order" - And I should see "Responses: 5" + And I should see "Responses: 6" And I follow "Delete ALL Responses" Then I should see "Are you sure you want to delete ALL the responses in this questionnaire?" And I press "Delete" diff --git a/tests/behat/check_responses_capabilities.feature b/tests/behat/check_responses_capabilities.feature index 821ed6d7..1593013a 100644 --- a/tests/behat/check_responses_capabilities.feature +++ b/tests/behat/check_responses_capabilities.feature @@ -31,10 +31,9 @@ Feature: Review responses with different capabilities And I follow "Test questionnaire" Then I should see "View all responses" And I navigate to "View all responses" in current page administration - Then I should see "View all responses." - And I should see "All participants." + Then I should see "All responses" And I should see "View Default order" - And I should see "Responses: 6" + And I should see "Responses: 7" And I log out @javascript