diff --git a/mod/feedback/analysis.php b/mod/feedback/analysis.php
index bed8b63eb02..ed57ac5809a 100644
--- a/mod/feedback/analysis.php
+++ b/mod/feedback/analysis.php
@@ -59,14 +59,6 @@ require('tabs.php');
$mygroupid = groups_get_activity_group($cm, true);
groups_print_activity_menu($cm, $url);
-if ( has_capability('mod/feedback:viewreports', $context) ) {
- //button "export to excel"
- echo $OUTPUT->container_start('form-buttons');
- $aurl = new moodle_url('analysis_to_excel.php', array('sesskey'=>sesskey(), 'id'=>$id));
- echo $OUTPUT->single_button($aurl, get_string('export_to_excel', 'feedback'));
- echo $OUTPUT->container_end();
-}
-
// Show the summary.
$summary = new mod_feedback\output\summary($feedbackstructure, $mygroupid);
echo $OUTPUT->render_from_template('mod_feedback/summary', $summary->export_for_template($OUTPUT));
diff --git a/mod/feedback/analysis_course.php b/mod/feedback/analysis_course.php
index 2a195b165bb..2765baa7beb 100644
--- a/mod/feedback/analysis_course.php
+++ b/mod/feedback/analysis_course.php
@@ -30,7 +30,6 @@ $current_tab = 'analysis';
$id = required_param('id', PARAM_INT); //the POST dominated the GET
$courseitemfilter = optional_param('courseitemfilter', '0', PARAM_INT);
$courseitemfiltertyp = optional_param('courseitemfiltertyp', '0', PARAM_ALPHANUM);
-$searchcourse = optional_param('searchcourse', '', PARAM_RAW);
$courseid = optional_param('courseid', false, PARAM_INT);
$url = new moodle_url('/mod/feedback/analysis_course.php', array('id'=>$id));
@@ -44,9 +43,6 @@ if ($courseitemfilter !== '0') {
if ($courseitemfiltertyp !== '0') {
$url->param('courseitemfiltertyp', $courseitemfiltertyp);
}
-if ($searchcourse !== '') {
- $url->param('searchcourse', $searchcourse);
-}
$PAGE->set_url($url);
list($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
@@ -62,6 +58,12 @@ if (!($feedback->publish_stats OR has_capability('mod/feedback:viewreports', $co
$feedbackstructure = new mod_feedback_structure($feedback, $PAGE->cm, $courseid);
+// Process course select form.
+$courseselectform = new mod_feedback_course_select_form($url, $feedbackstructure);
+if ($data = $courseselectform->get_data()) {
+ redirect(new moodle_url($url, ['courseid' => $data->courseid]));
+}
+
/// Print the page header
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
@@ -74,21 +76,12 @@ echo $OUTPUT->heading(format_string($feedback->name));
/// print the tabs
require('tabs.php');
-//print the analysed items
-
-if (has_capability('mod/feedback:viewreports', $context)) {
- //button "export to excel"
- echo $OUTPUT->container_start('form-buttons');
- $aurl = new moodle_url('analysis_to_excel.php', array('sesskey' => sesskey(), 'id' => $id,
- 'coursefilter' => $courseid));
- echo $OUTPUT->single_button($aurl, get_string('export_to_excel', 'feedback'));
- echo $OUTPUT->container_end();
-}
-
//get the groupid
//lstgroupid is the choosen id
$mygroupid = false;
+$courseselectform->display();
+
// Show the summary.
$summary = new mod_feedback\output\summary($feedbackstructure);
echo $OUTPUT->render_from_template('mod_feedback/summary', $summary->export_for_template($OUTPUT));
@@ -131,43 +124,6 @@ if ($courseitemfilter > 0) {
echo '
';
} else {
- echo '';
-
// Print the items in an analysed form.
foreach ($items as $item) {
echo '';
diff --git a/mod/feedback/analysis_to_excel.php b/mod/feedback/analysis_to_excel.php
deleted file mode 100644
index 83029a18b2e..00000000000
--- a/mod/feedback/analysis_to_excel.php
+++ /dev/null
@@ -1,313 +0,0 @@
-.
-
-/**
- * prints an analysed excel-spreadsheet of the feedback
- *
- * @author Andreas Grabs
- * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
- * @package mod_feedback
- */
-
-require_once("../../config.php");
-require_once("lib.php");
-require_once("$CFG->libdir/excellib.class.php");
-
-feedback_load_feedback_items();
-
-$id = required_param('id', PARAM_INT); //the POST dominated the GET
-$coursefilter = optional_param('coursefilter', '0', PARAM_INT);
-
-$url = new moodle_url('/mod/feedback/analysis_to_excel.php', array('id'=>$id));
-if ($coursefilter !== '0') {
- $url->param('coursefilter', $coursefilter);
-}
-$PAGE->set_url($url);
-
-$formdata = data_submitted();
-
-if (! $cm = get_coursemodule_from_id('feedback', $id)) {
- print_error('invalidcoursemodule');
-}
-
-if (! $course = $DB->get_record("course", array("id"=>$cm->course))) {
- print_error('coursemisconf');
-}
-
-if (! $feedback = $DB->get_record("feedback", array("id"=>$cm->instance))) {
- print_error('invalidcoursemodule');
-}
-
-$context = context_module::instance($cm->id);
-
-require_login($course, true, $cm);
-$feedbackstructure = new mod_feedback_structure($feedback, $PAGE->cm, $coursefilter);
-
-require_capability('mod/feedback:viewreports', $context);
-
-//buffering any output
-//this prevents some output before the excel-header will be send
-ob_start();
-$fstring = new stdClass();
-$fstring->bold = get_string('bold', 'feedback');
-$fstring->page = get_string('page', 'feedback');
-$fstring->of = get_string('of', 'feedback');
-$fstring->modulenameplural = get_string('modulenameplural', 'feedback');
-$fstring->questions = get_string('questions', 'feedback');
-$fstring->itemlabel = get_string('item_label', 'feedback');
-$fstring->question = get_string('question', 'feedback');
-$fstring->responses = get_string('responses', 'feedback');
-$fstring->idnumber = get_string('idnumber');
-$fstring->username = get_string('username');
-$fstring->fullname = get_string('fullnameuser');
-$fstring->courseid = get_string('courseid', 'feedback');
-$fstring->course = get_string('course');
-$fstring->anonymous_user = get_string('anonymous_user', 'feedback');
-ob_end_clean();
-
-//get the questions (item-names)
-$items = $feedbackstructure->get_items(true);
-if (!$items) {
- print_error('no_items_available_yet',
- 'feedback',
- $CFG->wwwroot.'/mod/feedback/view.php?id='.$id);
- exit;
-}
-
-$filename = "feedback.xls";
-
-$mygroupid = groups_get_activity_group($cm);
-
-// Creating a workbook
-$workbook = new MoodleExcelWorkbook('-');
-$workbook->send($filename);
-
-//creating the needed formats
-$xls_formats = new stdClass();
-$xls_formats->head1 = $workbook->add_format(array(
- 'bold'=>1,
- 'size'=>12));
-
-$xls_formats->head2 = $workbook->add_format(array(
- 'align'=>'left',
- 'bold'=>1,
- 'bottum'=>2));
-
-$xls_formats->default = $workbook->add_format(array(
- 'align'=>'left',
- 'v_align'=>'top'));
-
-$xls_formats->value_bold = $workbook->add_format(array(
- 'align'=>'left',
- 'bold'=>1,
- 'v_align'=>'top'));
-
-$xls_formats->procent = $workbook->add_format(array(
- 'align'=>'left',
- 'bold'=>1,
- 'v_align'=>'top',
- 'num_format'=>'#,##0.00%'));
-
-// Creating the worksheets
-$sheetname = clean_param($feedback->name, PARAM_ALPHANUM);
-error_reporting(0);
-$worksheet1 = $workbook->add_worksheet(substr($sheetname, 0, 31));
-$worksheet2 = $workbook->add_worksheet('detailed');
-error_reporting($CFG->debug);
-$worksheet1->hide_gridlines();
-$worksheet1->set_column(0, 0, 10);
-$worksheet1->set_column(1, 1, 30);
-$worksheet1->set_column(2, 20, 15);
-
-//writing the table header
-$row_offset1 = 0;
-$worksheet1->write_string($row_offset1, 0, userdate(time()), $xls_formats->head1);
-
-////////////////////////////////////////////////////////////////////////
-//print the analysed sheet
-////////////////////////////////////////////////////////////////////////
-//get the completeds
-$completedscount = $feedbackstructure->count_completed_responses($mygroupid);
-if ($completedscount > 0) {
- //write the count of completeds
- $row_offset1++;
- $worksheet1->write_string($row_offset1,
- 0,
- $fstring->modulenameplural.': '.strval($completedscount),
- $xls_formats->head1);
-}
-
-if (is_array($items)) {
- $row_offset1++;
- $worksheet1->write_string($row_offset1,
- 0,
- $fstring->questions.': '. strval(count($items)),
- $xls_formats->head1);
-}
-
-$row_offset1 += 2;
-$worksheet1->write_string($row_offset1, 0, $fstring->itemlabel, $xls_formats->head1);
-$worksheet1->write_string($row_offset1, 1, $fstring->question, $xls_formats->head1);
-$worksheet1->write_string($row_offset1, 2, $fstring->responses, $xls_formats->head1);
-$row_offset1++;
-
-if (empty($items)) {
- $items=array();
-}
-foreach ($items as $item) {
- //get the class of item-typ
- $itemobj = feedback_get_item_class($item->typ);
- $row_offset1 = $itemobj->excelprint_item($worksheet1,
- $row_offset1,
- $xls_formats,
- $item,
- $mygroupid,
- $coursefilter);
-}
-
-////////////////////////////////////////////////////////////////////////
-//print the detailed sheet
-////////////////////////////////////////////////////////////////////////
-//get the completeds
-
-$completeds = feedback_get_completeds_group($feedback, $mygroupid, $coursefilter);
-//important: for each completed you have to print each item, even if it is not filled out!!!
-//therefor for each completed we have to iterate over all items of the feedback
-//this is done by feedback_excelprint_detailed_items
-
-$row_offset2 = 0;
-//first we print the table-header
-$row_offset2 = feedback_excelprint_detailed_head($worksheet2, $xls_formats, $items, $row_offset2);
-
-
-if (is_array($completeds)) {
- foreach ($completeds as $completed) {
- $row_offset2 = feedback_excelprint_detailed_items($worksheet2,
- $xls_formats,
- $completed,
- $items,
- $row_offset2);
- }
-}
-
-
-$workbook->close();
-exit;
-////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-//functions
-////////////////////////////////////////////////////////////////////////////////
-
-
-function feedback_excelprint_detailed_head(&$worksheet, $xls_formats, $items, $row_offset) {
- global $fstring, $feedback;
-
- if (!$items) {
- return;
- }
- $col_offset = 0;
-
- $worksheet->write_string($row_offset + 1, $col_offset, $fstring->idnumber, $xls_formats->head2);
- $col_offset++;
-
- $worksheet->write_string($row_offset + 1, $col_offset, $fstring->username, $xls_formats->head2);
- $col_offset++;
-
- $worksheet->write_string($row_offset + 1, $col_offset, $fstring->fullname, $xls_formats->head2);
- $col_offset++;
-
- foreach ($items as $item) {
- $worksheet->write_string($row_offset, $col_offset, $item->name, $xls_formats->head2);
- $worksheet->write_string($row_offset + 1, $col_offset, $item->label, $xls_formats->head2);
- $col_offset++;
- }
-
- $worksheet->write_string($row_offset + 1, $col_offset, $fstring->courseid, $xls_formats->head2);
- $col_offset++;
-
- $worksheet->write_string($row_offset + 1, $col_offset, $fstring->course, $xls_formats->head2);
- $col_offset++;
-
- return $row_offset + 2;
-}
-
-function feedback_excelprint_detailed_items(&$worksheet, $xls_formats,
- $completed, $items, $row_offset) {
- global $DB, $fstring;
-
- if (!$items) {
- return;
- }
- $col_offset = 0;
- $courseid = 0;
-
- $feedback = $DB->get_record('feedback', array('id'=>$completed->feedback));
- //get the username
- //anonymous users are separated automatically because the userid in the completed is "0"
- if ($user = $DB->get_record('user', array('id'=>$completed->userid))) {
- if ($completed->anonymous_response == FEEDBACK_ANONYMOUS_NO) {
- $worksheet->write_string($row_offset, $col_offset, $user->idnumber, $xls_formats->head2);
- $col_offset++;
- $userfullname = fullname($user);
- $worksheet->write_string($row_offset, $col_offset, $user->username, $xls_formats->head2);
- $col_offset++;
- } else {
- $userfullname = $fstring->anonymous_user;
- $worksheet->write_string($row_offset, $col_offset, '-', $xls_formats->head2);
- $col_offset++;
- $worksheet->write_string($row_offset, $col_offset, '-', $xls_formats->head2);
- $col_offset++;
- }
- } else {
- $userfullname = $fstring->anonymous_user;
- $worksheet->write_string($row_offset, $col_offset, '-', $xls_formats->head2);
- $col_offset++;
- $worksheet->write_string($row_offset, $col_offset, '-', $xls_formats->head2);
- $col_offset++;
- }
-
- $worksheet->write_string($row_offset, $col_offset, $userfullname, $xls_formats->head2);
-
- $col_offset++;
- foreach ($items as $item) {
- $params = array('item' => $item->id, 'completed' => $completed->id);
- $value = $DB->get_record('feedback_value', $params);
-
- $itemobj = feedback_get_item_class($item->typ);
- $printval = $itemobj->get_printval($item, $value);
- $printval = trim($printval);
-
- if (is_numeric($printval)) {
- $worksheet->write_number($row_offset, $col_offset, $printval, $xls_formats->default);
- } else if ($printval != '') {
- $worksheet->write_string($row_offset, $col_offset, $printval, $xls_formats->default);
- }
- $printval = '';
- $col_offset++;
- $courseid = isset($value->course_id) ? $value->course_id : 0;
- if ($courseid == 0) {
- $courseid = $feedback->course;
- }
- }
- $worksheet->write_number($row_offset, $col_offset, $courseid, $xls_formats->default);
- $col_offset++;
- if (isset($courseid) AND $course = $DB->get_record('course', array('id' => $courseid))) {
- $coursecontext = context_course::instance($courseid);
- $shortname = format_string($course->shortname, true, array('context' => $coursecontext));
- $worksheet->write_string($row_offset, $col_offset, $shortname, $xls_formats->default);
- }
- return $row_offset + 1;
-}
diff --git a/mod/feedback/classes/course_select_form.php b/mod/feedback/classes/course_select_form.php
new file mode 100644
index 00000000000..9c644efa325
--- /dev/null
+++ b/mod/feedback/classes/course_select_form.php
@@ -0,0 +1,83 @@
+.
+
+/**
+ * Contains class mod_feedback_course_map_form
+ *
+ * @package mod_feedback
+ * @copyright 2016 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Form for mapping courses to the feedback
+ *
+ * @package mod_feedback
+ * @copyright 2016 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class mod_feedback_course_select_form extends moodleform {
+ /** @var moodle_url */
+ protected $action;
+ /** @var mod_feedback_structure $feedbackstructure */
+ protected $feedbackstructure;
+
+ /**
+ * Constructor
+ *
+ * @param string|moodle_url $action the action attribute for the form
+ * @param mod_feedback_structure $feedbackstructure
+ * @param bool $editable
+ */
+ public function __construct($action, mod_feedback_structure $feedbackstructure, $editable = true) {
+ $this->action = new moodle_url($action, ['courseid' => null]);
+ $this->feedbackstructure = $feedbackstructure;
+ parent::__construct($action, null, 'post', '', ['id' => 'feedback_course_filter'], $editable);
+ }
+
+ /**
+ * Definition of the form
+ */
+ public function definition() {
+ $mform = $this->_form;
+ $feedbackstructure = $this->feedbackstructure;
+
+ $mform->addElement('hidden', 'id');
+ $mform->setType('id', PARAM_INT);
+
+ if (!$this->_form->_freezeAll && ($courses = $feedbackstructure->get_completed_courses()) && count($courses) > 1) {
+ $elements = [];
+ $elements[] = $mform->createElement('autocomplete', 'courseid', get_string('filter_by_course', 'feedback'),
+ ['' => get_string('fulllistofcourses')] + $courses);
+ $elements[] = $mform->createElement('submit', 'submitbutton', get_string('filter'));
+ if ($feedbackstructure->get_courseid()) {
+ $elements[] = $mform->createElement('static', 'showall', '',
+ html_writer::link($this->action, get_string('show_all', 'feedback')));
+ }
+ if (defined('BEHAT_SITE_RUNNING')) {
+ // TODO MDL-53734 remove this - behat does not recognise autocomplete element inside a group.
+ foreach ($elements as $element) {
+ $mform->addElement($element);
+ }
+ } else {
+ $mform->addGroup($elements, 'coursefilter', get_string('filter_by_course', 'feedback'), array(' '), false);
+ }
+ }
+
+ $this->set_data(['courseid' => $feedbackstructure->get_courseid(), 'id' => $feedbackstructure->get_cm()->id]);
+ }
+}
diff --git a/mod/feedback/classes/responses_anon_table.php b/mod/feedback/classes/responses_anon_table.php
index 20964b26bb5..204bddb94d8 100644
--- a/mod/feedback/classes/responses_anon_table.php
+++ b/mod/feedback/classes/responses_anon_table.php
@@ -36,48 +36,56 @@ class mod_feedback_responses_anon_table extends mod_feedback_responses_table {
/** @var string */
protected $showallparamname = 'ashowall';
+ /** @var string */
+ protected $downloadparamname = 'adownload';
+
/**
* Initialises table
*/
public function init() {
- $this->uniqueid = 'feedback-showentry-anon-list-' . $this->cm->instance;
+ $cm = $this->feedbackstructure->get_cm();
+ $this->uniqueid = 'feedback-showentry-anon-list-' . $cm->instance;
// There potentially can be both tables with anonymouns and non-anonymous responses on
// the same page (for example when feedback anonymity was changed after some people
// already responded). In this case we need to distinguish tables' pagination parameters.
$this->request[TABLE_VAR_PAGE] = 'apage';
- $tablecolumns = array('random_response', 'showresponse');
- $tableheaders = array('', '');
+ $tablecolumns = ['random_response'];
+ $tableheaders = [get_string('response_nr', 'feedback')];
- $context = context_module::instance($this->cm->id);
- if (has_capability('mod/feedback:deletesubmissions', $context)) {
- $tablecolumns[] = 'deleteentry';
- $tableheaders[] = '';
+ if ($this->feedbackstructure->get_feedback()->course == SITEID && !$this->feedbackstructure->get_courseid()) {
+ $tablecolumns[] = 'courseid';
+ $tableheaders[] = get_string('course');
}
$this->define_columns($tablecolumns);
$this->define_headers($tableheaders);
- $this->sortable(false, 'random_response');
- $this->collapsible(false);
- $this->set_attribute('id', 'showentryanonymtable');
+ $this->sortable(true, 'random_response');
+ $this->collapsible(true);
+ $this->set_attribute('id', 'showentryanontable');
- $params = ['instance' => $this->cm->instance, 'anon' => FEEDBACK_ANONYMOUS_YES];
+ $params = ['instance' => $cm->instance,
+ 'anon' => FEEDBACK_ANONYMOUS_YES,
+ 'courseid' => $this->feedbackstructure->get_courseid()];
- $fields = 'DISTINCT c.id, c.random_response';
+ $fields = 'c.id, c.random_response, c.courseid';
$from = '{feedback_completed} c';
$where = 'c.anonymous_response = :anon AND c.feedback = :instance';
+ if ($this->feedbackstructure->get_courseid()) {
+ $where .= ' AND c.courseid = :courseid';
+ }
- $group = groups_get_activity_group($this->cm, true);
+ $group = groups_get_activity_group($this->feedbackstructure->get_cm(), true);
if ($group) {
- $from .= ' JOIN {groups_members} g ON g.groupid = :group AND g.userid = c.userid';
+ $where .= ' AND c.userid IN (SELECT g.userid FROM {groups_members} g WHERE g.groupid = :group)';
$params['group'] = $group;
}
$this->set_sql($fields, $from, $where, $params);
- $this->set_count_sql("SELECT COUNT(DISTINCT c.id) FROM $from WHERE $where", $params);
+ $this->set_count_sql("SELECT COUNT(c.id) FROM $from WHERE $where", $params);
}
/**
@@ -95,22 +103,11 @@ class mod_feedback_responses_anon_table extends mod_feedback_responses_table {
* @return string
*/
public function col_random_response($row) {
- return get_string('response_nr', 'feedback').': '. $row->random_response;
- }
-
- /**
- * Prepares column showresponse for display
- * @param stdClass $row
- * @return string
- */
- public function col_showresponse($row) {
- return html_writer::link($this->get_link_single_entry($row), get_string('show_entry', 'feedback'));
- }
-
- /**
- * Generate the HTML for the table preferences reset button.
- */
- protected function render_reset_button() {
- return '';
+ if ($this->is_downloading()) {
+ return $row->random_response;
+ } else {
+ return html_writer::link($this->get_link_single_entry($row),
+ get_string('response_nr', 'feedback').': '. $row->random_response);
+ }
}
}
diff --git a/mod/feedback/classes/responses_table.php b/mod/feedback/classes/responses_table.php
index 5bd0948776e..6130a1bdced 100644
--- a/mod/feedback/classes/responses_table.php
+++ b/mod/feedback/classes/responses_table.php
@@ -36,8 +36,8 @@ require_once($CFG->libdir . '/tablelib.php');
*/
class mod_feedback_responses_table extends table_sql {
- /** @var cm_info */
- protected $cm;
+ /** @var mod_feedback_structure */
+ protected $feedbackstructure;
/** @var int */
protected $grandtotal = null;
@@ -48,23 +48,34 @@ class mod_feedback_responses_table extends table_sql {
/** @var string */
protected $showallparamname = 'showall';
+ /** @var string */
+ protected $downloadparamname = 'download';
+
/**
* Constructor
*
- * @param cm_info $cm
+ * @param mod_feedback_structure $feedbackstructure
*/
- public function __construct(cm_info $cm) {
- $this->cm = $cm;
+ public function __construct(mod_feedback_structure $feedbackstructure) {
+ $this->feedbackstructure = $feedbackstructure;
- parent::__construct('feedback-showentry-list-' . $cm->instance);
+ parent::__construct('feedback-showentry-list-' . $feedbackstructure->get_cm()->instance);
$this->showall = optional_param($this->showallparamname, 0, PARAM_BOOL);
$this->define_baseurl(new moodle_url('/mod/feedback/show_entries.php',
- ['id' => $this->cm->id]));
+ ['id' => $this->feedbackstructure->get_cm()->id]));
+ if ($courseid = $this->feedbackstructure->get_courseid()) {
+ $this->baseurl->param('courseid', $courseid);
+ }
if ($this->showall) {
$this->baseurl->param($this->showallparamname, $this->showall);
}
+ $this->is_downloadable(true);
+ $this->is_downloading(optional_param($this->downloadparamname, 0, PARAM_ALPHA),
+ 'feedback_test');
+
+ $this->useridfield = 'userid';
$this->init();
}
@@ -73,44 +84,85 @@ class mod_feedback_responses_table extends table_sql {
*/
protected function init() {
- $tablecolumns = array('userpic', 'fullname', 'completed_timemodified');
- $tableheaders = array(get_string('userpic'), get_string('fullnameuser'), get_string('date'));
+ $tablecolumns = array('userpic', 'fullname');
+ $tableheaders = array(get_string('userpic'), get_string('fullnameuser'));
- $context = context_module::instance($this->cm->id);
- if (has_capability('mod/feedback:deletesubmissions', $context)) {
- $tablecolumns[] = 'deleteentry';
- $tableheaders[] = '';
+ $extrafields = get_extra_user_fields($this->get_context());
+ $ufields = user_picture::fields('u', $extrafields, $this->useridfield);
+ $fields = 'c.id, c.timemodified as completed_timemodified, c.courseid, '.$ufields;
+ $from = '{feedback_completed} c '
+ . 'JOIN {user} u ON u.id = c.userid AND u.deleted = :notdeleted';
+ $where = 'c.anonymous_response = :anon
+ AND c.feedback = :instance';
+ if ($this->feedbackstructure->get_courseid()) {
+ $where .= ' AND c.courseid = :courseid';
}
+ if ($this->is_downloading()) {
+ // When downloading data:
+ // Remove 'userpic' from downloaded data.
+ array_shift($tablecolumns);
+ array_shift($tableheaders);
+
+ // Add all identity fields as separate columns.
+ foreach ($extrafields as $field) {
+ $fields .= ", u.{$field}";
+ $tablecolumns[] = $field;
+ $tableheaders[] = get_user_field_name($field);
+ }
+ }
+
+ if ($this->feedbackstructure->get_feedback()->course == SITEID && !$this->feedbackstructure->get_courseid()) {
+ $tablecolumns[] = 'courseid';
+ $tableheaders[] = get_string('course');
+ }
+
+ $tablecolumns[] = 'completed_timemodified';
+ $tableheaders[] = get_string('date');
+
$this->define_columns($tablecolumns);
$this->define_headers($tableheaders);
$this->sortable(true, 'lastname', SORT_ASC);
- $this->collapsible(false);
+ $this->collapsible(true);
$this->set_attribute('id', 'showentrytable');
$params = array();
$params['anon'] = FEEDBACK_ANONYMOUS_NO;
- $params['instance'] = $this->cm->instance;
+ $params['instance'] = $this->feedbackstructure->get_feedback()->id;
$params['notdeleted'] = 0;
+ $params['courseid'] = $this->feedbackstructure->get_courseid();
- $ufields = user_picture::fields('u', null, 'userid');
- $fields = 'DISTINCT c.id, c.timemodified as completed_timemodified, '.$ufields;
- $from = '{user} u, {feedback_completed} c';
- $where = 'anonymous_response = :anon
- AND u.id = c.userid
- AND c.feedback = :instance
- AND u.deleted = :notdeleted';
-
- $group = groups_get_activity_group($this->cm, true);
+ $group = groups_get_activity_group($this->feedbackstructure->get_cm(), true);
if ($group) {
- $from .= ', {groups_members} g';
- $where .= ' AND g.groupid = :group AND g.userid = c.userid';
+ $where .= ' AND c.userid IN (SELECT g.userid FROM {groups_members} g WHERE g.groupid = :group)';
$params['group'] = $group;
}
$this->set_sql($fields, $from, $where, $params);
- $this->set_count_sql("SELECT COUNT(DISTINCT c.id) FROM $from WHERE $where", $params);
+ $this->set_count_sql("SELECT COUNT(c.id) FROM $from WHERE $where", $params);
+ }
+
+ /**
+ * Current context
+ * @return context_module
+ */
+ protected function get_context() {
+ return context_module::instance($this->feedbackstructure->get_cm()->id);
+ }
+
+ /**
+ * Allows to set the display column value for all columns without "col_xxxxx" method.
+ * @param string $column column name
+ * @param stdClass $row current record result of SQL query
+ */
+ public function other_cols($column, $row) {
+ if (preg_match('/^val(\d+)$/', $column, $matches)) {
+ $items = $this->feedbackstructure->get_items();
+ $itemobj = feedback_get_item_class($items[$matches[1]]->typ);
+ return trim($itemobj->get_printval($items[$matches[1]], (object) ['value' => $row->$column] ));
+ }
+ return $row->$column;
}
/**
@@ -120,7 +172,8 @@ class mod_feedback_responses_table extends table_sql {
*/
public function col_userpic($row) {
global $OUTPUT;
- return $OUTPUT->user_picture($row, array('courseid' => $this->cm->course));
+ $user = user_picture::unalias($row, [], $this->useridfield);
+ return $OUTPUT->user_picture($user, array('courseid' => $this->feedbackstructure->get_cm()->course));
}
/**
@@ -129,11 +182,10 @@ class mod_feedback_responses_table extends table_sql {
* @return string
*/
public function col_deleteentry($row) {
- $context = context_module::instance($this->cm->id);
- if (has_capability('mod/feedback:deletesubmissions', $context)) {
- $deleteentryurl = new moodle_url($this->baseurl, ['delete' => $row->id]);
- return html_writer::link($deleteentryurl, get_string('delete_entry', 'feedback'));
- }
+ global $OUTPUT;
+ $icon = $OUTPUT->render(new \pix_icon('t/delete', get_string('delete_entry', 'feedback')));
+ $deleteentryurl = new moodle_url($this->baseurl, ['delete' => $row->id]);
+ return html_writer::link($deleteentryurl, $icon);
}
/**
@@ -142,7 +194,7 @@ class mod_feedback_responses_table extends table_sql {
* @return \moodle_url
*/
protected function get_link_single_entry($row) {
- return new moodle_url($this->baseurl, ['userid' => $row->userid, 'showcompleted' => $row->id]);
+ return new moodle_url($this->baseurl, ['userid' => $row->{$this->useridfield}, 'showcompleted' => $row->id]);
}
/**
@@ -151,8 +203,59 @@ class mod_feedback_responses_table extends table_sql {
* @return string
*/
public function col_completed_timemodified($student) {
- return html_writer::link($this->get_link_single_entry($student),
- userdate($student->completed_timemodified));
+ if ($this->is_downloading()) {
+ return userdate($student->completed_timemodified);
+ } else {
+ return html_writer::link($this->get_link_single_entry($student),
+ userdate($student->completed_timemodified));
+ }
+ }
+
+ /**
+ * Prepares column courseid for display
+ * @param array $row
+ * @return string
+ */
+ public function col_courseid($row) {
+ $courses = $this->feedbackstructure->get_completed_courses();
+ $name = '';
+ if (isset($courses[$row->courseid])) {
+ $name = $courses[$row->courseid];
+ if (!$this->is_downloading()) {
+ $name = html_writer::link(course_get_url($row->courseid), $name);
+ }
+ }
+ return $name;
+ }
+
+ /**
+ * Adds common values to the table that do not change the number or order of entries and
+ * are only needed when outputting or downloading data.
+ */
+ protected function add_all_values_to_output() {
+ $tablecolumns = array_keys($this->columns);
+ $tableheaders = $this->headers;
+
+ // Add all feedback response values.
+ $items = $this->feedbackstructure->get_items(true);
+ foreach ($items as $nr => $item) {
+ $this->sql->fields .= ", v{$nr}.value AS val{$nr}";
+ $this->sql->from .= " LEFT OUTER JOIN {feedback_value} v{$nr} " .
+ "ON v{$nr}.completed = c.id AND v{$nr}.item = :itemid{$nr}";
+ $this->sql->params["itemid{$nr}"] = $item->id;
+ $tablecolumns[] = "val{$nr}";
+ $itemobj = feedback_get_item_class($item->typ);
+ $tableheaders[] = $itemobj->get_display_name($item);
+ }
+
+ // Add 'Delete entry' column.
+ if (!$this->is_downloading() && has_capability('mod/feedback:deletesubmissions', $this->get_context())) {
+ $tablecolumns[] = 'deleteentry';
+ $tableheaders[] = '';
+ }
+
+ $this->define_columns($tablecolumns);
+ $this->define_headers($tableheaders);
}
/**
@@ -165,21 +268,23 @@ class mod_feedback_responses_table extends table_sql {
public function query_db($pagesize, $useinitialsbar=true) {
global $DB;
$this->totalrows = $grandtotal = $this->get_total_responses_count();
- $this->initialbars($useinitialsbar);
+ if (!$this->is_downloading()) {
+ $this->initialbars($useinitialsbar);
- list($wsql, $wparams) = $this->get_sql_where();
- if ($wsql) {
- $this->countsql .= ' AND '.$wsql;
- $this->countparams = array_merge($this->countparams, $wparams);
+ list($wsql, $wparams) = $this->get_sql_where();
+ if ($wsql) {
+ $this->countsql .= ' AND '.$wsql;
+ $this->countparams = array_merge($this->countparams, $wparams);
- $this->sql->where .= ' AND '.$wsql;
- $this->sql->params = array_merge($this->sql->params, $wparams);
+ $this->sql->where .= ' AND '.$wsql;
+ $this->sql->params = array_merge($this->sql->params, $wparams);
- $this->totalrows = $DB->count_records_sql($this->countsql, $this->countparams);
- }
+ $this->totalrows = $DB->count_records_sql($this->countsql, $this->countparams);
+ }
- if ($this->totalrows > $pagesize) {
- $this->pagesize($pagesize, $this->totalrows);
+ if ($this->totalrows > $pagesize) {
+ $this->pagesize($pagesize, $this->totalrows);
+ }
}
if ($sort = $this->get_sql_sort()) {
@@ -191,7 +296,11 @@ class mod_feedback_responses_table extends table_sql {
WHERE {$this->sql->where}
{$sort}";
- $this->rawdata = $DB->get_recordset_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size());
+ if (!$this->is_downloading()) {
+ $this->rawdata = $DB->get_recordset_sql($sql, $this->sql->params, $this->get_page_start(), $this->get_page_size());
+ } else {
+ $this->rawdata = $DB->get_recordset_sql($sql, $this->sql->params);
+ }
}
/**
@@ -211,7 +320,7 @@ class mod_feedback_responses_table extends table_sql {
* @param array $columns an array of identifying names for columns. If
* columns are sorted then column names must correspond to a field in sql.
*/
- function define_columns($columns) {
+ public function define_columns($columns) {
parent::define_columns($columns);
foreach ($this->columns as $column => $column) {
// Automatically assign classes to columns.
@@ -219,12 +328,24 @@ class mod_feedback_responses_table extends table_sql {
}
}
+ /**
+ * Convenience method to call a number of methods for you to display the
+ * table.
+ * @param int $pagesize
+ * @param bool $useinitialsbar
+ * @param string $downloadhelpbutton
+ */
+ public function out($pagesize, $useinitialsbar, $downloadhelpbutton='') {
+ $this->add_all_values_to_output();
+ parent::out($pagesize, $useinitialsbar, $downloadhelpbutton);
+ }
+
/**
* Displays the table
*/
public function display() {
global $OUTPUT;
- groups_print_activity_menu($this->cm, $this->baseurl);
+ groups_print_activity_menu($this->feedbackstructure->get_cm(), $this->baseurl->out());
$grandtotal = $this->get_total_responses_count();
if (!$grandtotal) {
echo $OUTPUT->box(get_string('nothingtodisplay'), 'generalbox nothingtodisplay');
@@ -280,4 +401,38 @@ class mod_feedback_responses_table extends table_sql {
$nextrow ? $this->get_link_single_entry($nextrow) : null,
];
}
+
+ /**
+ * Download the data.
+ */
+ public function download() {
+ \core\session\manager::write_close();
+ $this->out($this->get_total_responses_count(), false);
+ exit;
+ }
+
+ /**
+ * Returns html code for displaying "Download" button if applicable.
+ */
+ public function download_buttons() {
+ if ($this->is_downloadable() && !$this->is_downloading()) {
+
+ $elementid = $this->uniqueid . '_download';
+ $html = '';
+ $html .= '
';
+
+ return $html;
+ } else {
+ return '';
+ }
+ }
}
diff --git a/mod/feedback/lang/en/feedback.php b/mod/feedback/lang/en/feedback.php
index 27ce17583fb..87773dd84f1 100644
--- a/mod/feedback/lang/en/feedback.php
+++ b/mod/feedback/lang/en/feedback.php
@@ -129,6 +129,7 @@ $string['checkbox'] = 'Multiple choice - multiple answers allowed (check boxes)'
$string['check_values'] = 'Possible responses';
$string['choosefile'] = 'Choose a file';
$string['chosen_feedback_response'] = 'chosen feedback response';
+$string['downloadresponseas'] = 'Download all responses as:';
$string['importfromthisfile'] = 'Import from this file';
$string['import_questions'] = 'Import questions';
$string['import_successfully'] = 'Import successfully';
diff --git a/mod/feedback/show_entries.php b/mod/feedback/show_entries.php
index 794a19949e5..7b0a99081e0 100644
--- a/mod/feedback/show_entries.php
+++ b/mod/feedback/show_entries.php
@@ -32,6 +32,7 @@ $id = required_param('id', PARAM_INT);
$userid = optional_param('userid', false, PARAM_INT);
$showcompleted = optional_param('showcompleted', false, PARAM_INT);
$deleteid = optional_param('delete', null, PARAM_INT);
+$courseid = optional_param('courseid', null, PARAM_INT);
////////////////////////////////////////////////////////
//get the objects
@@ -64,9 +65,24 @@ if ($deleteid) {
$feedbackstructure = new mod_feedback_completion($feedback, $cm, 0, true, $showcompleted, $userid);
} else {
// Viewing list of reponses.
- $feedbackstructure = new mod_feedback_structure($feedback, $cm);
+ $feedbackstructure = new mod_feedback_structure($feedback, $cm, $courseid);
}
+$responsestable = new mod_feedback_responses_table($feedbackstructure);
+$anonresponsestable = new mod_feedback_responses_anon_table($feedbackstructure);
+
+if ($responsestable->is_downloading()) {
+ $responsestable->download();
+}
+if ($anonresponsestable->is_downloading()) {
+ $anonresponsestable->download();
+}
+
+// Process course select form.
+$courseselectform = new mod_feedback_course_select_form($baseurl, $feedbackstructure, $feedback->course == SITEID);
+if ($data = $courseselectform->get_data()) {
+ redirect(new moodle_url($baseurl, ['courseid' => $data->courseid]));
+}
// Print the page header.
navigation_node::override_active_url($baseurl);
$PAGE->set_heading($course->fullname);
@@ -104,12 +120,9 @@ if ($deleteid) {
$feedbackstructure, 'feedback_viewresponse_form');
$form->display();
- if ($userid) {
- $responsestable = new mod_feedback_responses_table($cm);
- } else {
- $responsestable = new mod_feedback_responses_anon_table($cm);
- }
- list($prevresponseurl, $returnurl, $nextresponseurl) = $responsestable->get_reponse_navigation_links($completedrecord);
+ list($prevresponseurl, $returnurl, $nextresponseurl) = $userid ?
+ $responsestable->get_reponse_navigation_links($completedrecord) :
+ $anonresponsestable->get_reponse_navigation_links($completedrecord);
echo html_writer::start_div('response_navigation');
echo $prevresponseurl ? html_writer::link($prevresponseurl, get_string('prev'), ['class' => 'prev_response']) : '';
@@ -118,9 +131,9 @@ if ($deleteid) {
echo html_writer::end_div();
} else {
// Print the list of responses.
+ $courseselectform->display();
// Show non-anonymous responses (always retrieve them even if current feedback is anonymous).
- $responsestable = new mod_feedback_responses_table($cm);
$totalrows = $responsestable->get_total_responses_count();
if (!$feedbackstructure->is_anonymous() || $totalrows) {
echo $OUTPUT->heading(get_string('non_anonymous_entries', 'feedback', $totalrows), 4);
@@ -129,7 +142,6 @@ if ($deleteid) {
// Show anonymous responses (always retrieve them even if current feedback is not anonymous).
$feedbackstructure->shuffle_anonym_responses();
- $anonresponsestable = new mod_feedback_responses_anon_table($cm);
$totalrows = $anonresponsestable->get_total_responses_count();
if ($feedbackstructure->is_anonymous() || $totalrows) {
echo $OUTPUT->heading(get_string('anonymous_entries', 'feedback', $totalrows), 4);
diff --git a/mod/feedback/tabs.php b/mod/feedback/tabs.php
index 849077bef29..6c51bf8fccf 100644
--- a/mod/feedback/tabs.php
+++ b/mod/feedback/tabs.php
@@ -45,44 +45,39 @@ if (!isset($current_tab)) {
$viewurl = new moodle_url('/mod/feedback/view.php', array('id' => $usedid));
$row[] = new tabobject('view', $viewurl->out(), get_string('overview', 'feedback'));
+$urlparams = ['id' => $usedid];
+if ($feedback->course == SITEID && $courseid) {
+ $urlparams['courseid'] = $courseid;
+}
if (has_capability('mod/feedback:edititems', $context)) {
- $editurl = new moodle_url('/mod/feedback/edit.php', array('id'=>$usedid, 'do_show'=>'edit'));
+ $editurl = new moodle_url('/mod/feedback/edit.php', $urlparams + ['do_show' => 'edit']);
$row[] = new tabobject('edit', $editurl->out(), get_string('edit_items', 'feedback'));
- $templateurl = new moodle_url('/mod/feedback/edit.php', array('id'=>$usedid, 'do_show'=>'templates'));
+ $templateurl = new moodle_url('/mod/feedback/edit.php', $urlparams + ['do_show' => 'templates']);
$row[] = new tabobject('templates', $templateurl->out(), get_string('templates', 'feedback'));
}
if ($feedback->course == SITEID && has_capability('mod/feedback:mapcourse', $context)) {
- $mapurl = new moodle_url('/mod/feedback/mapcourse.php', array('id' => $usedid));
+ $mapurl = new moodle_url('/mod/feedback/mapcourse.php', $urlparams);
$row[] = new tabobject('mapcourse', $mapurl->out(), get_string('mappedcourses', 'feedback'));
}
if (has_capability('mod/feedback:viewreports', $context)) {
if ($feedback->course == SITEID) {
- $url_params = array('id' => $usedid, 'courseid' => $courseid);
- $analysisurl = new moodle_url('/mod/feedback/analysis_course.php', $url_params);
- $row[] = new tabobject('analysis',
- $analysisurl->out(),
- get_string('analysis', 'feedback'));
-
+ $analysisurl = new moodle_url('/mod/feedback/analysis_course.php', $urlparams);
} else {
- $url_params = array('id' => $usedid);
- $analysisurl = new moodle_url('/mod/feedback/analysis.php', $url_params);
- $row[] = new tabobject('analysis',
- $analysisurl->out(),
- get_string('analysis', 'feedback'));
+ $analysisurl = new moodle_url('/mod/feedback/analysis.php', $urlparams);
}
+ $row[] = new tabobject('analysis', $analysisurl->out(), get_string('analysis', 'feedback'));
- $url_params = array('id' => $usedid);
- $reporturl = new moodle_url('/mod/feedback/show_entries.php', $url_params);
+ $reporturl = new moodle_url('/mod/feedback/show_entries.php', $urlparams);
$row[] = new tabobject('showentries',
$reporturl->out(),
get_string('show_entries', 'feedback'));
if ($feedback->anonymous == FEEDBACK_ANONYMOUS_NO AND $feedback->course != SITEID) {
- $nonrespondenturl = new moodle_url('/mod/feedback/show_nonrespondents.php', array('id'=>$usedid));
+ $nonrespondenturl = new moodle_url('/mod/feedback/show_nonrespondents.php', $urlparams);
$row[] = new tabobject('nonrespondents',
$nonrespondenturl->out(),
get_string('show_nonrespondents', 'feedback'));
diff --git a/mod/feedback/tests/behat/anonymous.feature b/mod/feedback/tests/behat/anonymous.feature
index 04d9ec5d48b..b6673980634 100644
--- a/mod/feedback/tests/behat/anonymous.feature
+++ b/mod/feedback/tests/behat/anonymous.feature
@@ -102,7 +102,7 @@ Feature: Anonymous feedback
And I follow "Show responses"
And I should not see "Username"
And I should see "Anonymous entries (2)"
- And I click on "Show response" "link" in the "Response number: 1" "table_row"
+ And I follow "Response number: 1"
And I should not see "Username"
And I should see "Response number: 1 (Anonymous)"
And I log out
@@ -164,7 +164,7 @@ Feature: Anonymous feedback
And I follow "Site feedback"
And I follow "Show responses"
And I should see "Anonymous entries (2)"
- And I click on "Show response" "link" in the "Response number: 1" "table_row"
+ And I follow "Response number: 1"
And I should see "Response number: 1 (Anonymous)"
And I log out
@@ -222,7 +222,7 @@ Feature: Anonymous feedback
And I follow "Show responses"
And I should not see "Username"
And I should see "Anonymous entries (2)"
- And I click on "Show response" "link" in the "Response number: 1" "table_row"
+ And I follow "Response number: 1"
And I should not see "Username"
And I should see "Response number: 1 (Anonymous)"
And I should not see "Prev"
diff --git a/mod/feedback/tests/behat/coursemapping.feature b/mod/feedback/tests/behat/coursemapping.feature
index 4c1c8543ae5..8a814c16357 100644
--- a/mod/feedback/tests/behat/coursemapping.feature
+++ b/mod/feedback/tests/behat/coursemapping.feature
@@ -115,7 +115,7 @@ Feature: Mapping courses in a feedback
And I follow "Course feedback"
And I follow "Analysis"
- And the field "Filter by course" matches value "Choose..."
+ And I should see "All courses" in the "#feedback_course_filter .fautocomplete .label" "css_element"
And I should see "1 (33.33 %)" in the "option a" "table_row"
And I should see "1 (33.33 %)" in the "option b" "table_row"
And I should see "1 (33.33 %)" in the "option c" "table_row"
@@ -124,7 +124,9 @@ Feature: Mapping courses in a feedback
And I should see "2.50" in the "C1" "table_row"
And I should see "1.00" in the "Acceptance test site" "table_row"
And I follow "Back"
- And I set the field "Filter by course" to "C1"
+ And I set the field "Filter by course" to "Course 1"
+ And I press "Filter"
+ And I should see "Course 1" in the "#feedback_course_filter .fautocomplete .label" "css_element"
And I should see "0" in the "option a" "table_row"
And I should see "1 (50.00 %)" in the "option b" "table_row"
And I should see "1 (50.00 %)" in the "option c" "table_row"
@@ -194,7 +196,7 @@ Feature: Mapping courses in a feedback
And I am on site homepage
And I follow "Course feedback"
And I follow "Analysis"
- And the field "Filter by course" matches value "Choose..."
+ And I should see "All courses" in the "#feedback_course_filter .fautocomplete .label" "css_element"
And I should see "0" in the "option a" "table_row"
And I should see "1 (33.33 %)" in the "option b" "table_row"
And I should see "2 (66.67 %)" in the "option c" "table_row"
@@ -203,12 +205,14 @@ Feature: Mapping courses in a feedback
And I should see "3.00" in the "C3" "table_row"
And I should see "2.50" in the "C2" "table_row"
And I follow "Back"
- And I set the field "Filter by course" to "C2"
+ And I set the field "Filter by course" to "Course 2"
+ And I press "Filter"
And I should see "0" in the "option a" "table_row"
And I should see "1 (50.00 %)" in the "option b" "table_row"
And I should see "1 (50.00 %)" in the "option c" "table_row"
And I should see "2 (100.00 %)" in the "option e" "table_row"
- And I set the field "Filter by course" to "C3"
+ And I set the field "Filter by course" to "Course 3"
+ And I press "Filter"
And I should see "0" in the "option a" "table_row"
And I should see "0" in the "option b" "table_row"
And I should see "1 (100.00 %)" in the "option c" "table_row"