Merge branch 'wip-MDL-53638-master' of https://github.com/marinaglancy/moodle

This commit is contained in:
Eloy Lafuente (stronk7) 2016-04-27 14:24:59 +02:00 committed by Dan Poltawski
commit 28ee220a36
73 changed files with 3859 additions and 4779 deletions

View file

@ -4,11 +4,6 @@ Feature: Block activity modules
As a manager
I can add activities block in a course or on the frontpage
Background:
Given I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "//a[@title=\"Show\"]" "xpath_element" in the "Feedback" "table_row"
Scenario: Add activities block on the frontpage
Given the following "activities" exist:
| activity | name | intro | course | idnumber |
@ -34,8 +29,9 @@ Feature: Block activity modules
| wiki | Frontpage wiki name | Frontpage wiki description | Acceptance test site | wiki0 |
| workshop | Frontpage workshop name | Frontpage workshop description | Acceptance test site | workshop0 |
When I log in as "admin"
And I am on site homepage
When I follow "Turn editing on"
And I follow "Turn editing on"
And I add the "Activities" block
And I click on "Assignments" "link" in the "Activities" "block"
Then I should see "Frontpage assignment name"
@ -112,7 +108,8 @@ Feature: Block activity modules
| wiki | Test wiki name | Test wiki description | C1 | wiki1 |
| workshop | Test workshop name | Test workshop description | C1 | workshop1 |
When I follow "Courses"
When I log in as "admin"
And I follow "Courses"
And I follow "Course 1"
And I turn editing mode on
And I add the "Activities" block

View file

@ -22,11 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
if (is_file($CFG->dirroot.'/mod/feedback/lib.php')) {
require_once($CFG->dirroot.'/mod/feedback/lib.php');
define('FEEDBACK_BLOCK_LIB_IS_OK', true);
}
class block_feedback extends block_list {
function init() {
@ -49,11 +44,6 @@ class block_feedback extends block_list {
$this->content->icons = array();
$this->content->footer = '';
if (!defined('FEEDBACK_BLOCK_LIB_IS_OK')) {
$this->content->items = array(get_string('missing_feedback_module', 'block_feedback'));
return $this->content;
}
$courseid = $this->page->course->id;
if ($courseid <= 0) {
$courseid = SITEID;

View file

@ -25,8 +25,5 @@
function xmldb_block_feedback_install() {
global $DB;
/// Disable this block by default (because Feedback is not technically part of 2.0)
$DB->set_field('block', 'visible', 0, array('name'=>'feedback'));
}

View file

@ -24,5 +24,4 @@
$string['feedback'] = 'Feedback';
$string['feedback:addinstance'] = 'Add a new feedback block';
$string['missing_feedback_module'] = 'This blocks relies on the Feedback activity module, but that module is not present!';
$string['pluginname'] = 'Feedback';

View file

@ -2652,15 +2652,15 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{
// switch next two lines for ol li containers for form items.
// $this->_elementTemplates=array('default'=>"\n\t\t".'<li class="fitem"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><div class="qfelement<!-- BEGIN error --> error<!-- END error --> {type}"><!-- BEGIN error --><span class="error">{error}</span><br /><!-- END error -->{element}</div></li>');
$this->_elementTemplates = array(
'default'=>"\n\t\t".'<div id="{id}" class="fitem {advanced}<!-- BEGIN required --> required<!-- END required --> fitem_{type} {emptylabel}" {aria-live}><div class="fitemtitle"><label>{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} </label>{help}</div><div class="felement {type}<!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error" tabindex="0">{error}</span><br /><!-- END error -->{element}</div></div>',
'default'=>"\n\t\t".'<div id="{id}" class="fitem {advanced}<!-- BEGIN required --> required<!-- END required --> fitem_{type} {emptylabel} {class}" {aria-live}><div class="fitemtitle"><label>{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} </label>{help}</div><div class="felement {type}<!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error" tabindex="0">{error}</span><br /><!-- END error -->{element}</div></div>',
'actionbuttons'=>"\n\t\t".'<div id="{id}" class="fitem fitem_actionbuttons fitem_{type}"><div class="felement {type}">{element}</div></div>',
'actionbuttons'=>"\n\t\t".'<div id="{id}" class="fitem fitem_actionbuttons fitem_{type} {class}"><div class="felement {type}">{element}</div></div>',
'fieldset'=>"\n\t\t".'<div id="{id}" class="fitem {advanced} {class}<!-- BEGIN required --> required<!-- END required --> fitem_{type} {emptylabel}"><div class="fitemtitle"><div class="fgrouplabel"><label>{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} </label>{help}</div></div><fieldset class="felement {type}<!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error" tabindex="0">{error}</span><br /><!-- END error -->{element}</fieldset></div>',
'static'=>"\n\t\t".'<div class="fitem {advanced} {emptylabel}"><div class="fitemtitle"><div class="fstaticlabel">{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} {help}</div></div><div class="felement fstatic <!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error" tabindex="0">{error}</span><br /><!-- END error -->{element}</div></div>',
'static'=>"\n\t\t".'<div id="{id}" class="fitem {advanced} {emptylabel} {class}"><div class="fitemtitle"><div class="fstaticlabel">{label}<!-- BEGIN required -->{req}<!-- END required -->{advancedimg} {help}</div></div><div class="felement fstatic <!-- BEGIN error --> error<!-- END error -->"><!-- BEGIN error --><span class="error" tabindex="0">{error}</span><br /><!-- END error -->{element}</div></div>',
'warning'=>"\n\t\t".'<div class="fitem {advanced} {emptylabel}">{element}</div>',
'warning'=>"\n\t\t".'<div id="{id}" class="fitem {advanced} {emptylabel} {class}">{element}</div>',
'nodisplay'=>'');
@ -2830,6 +2830,7 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{
$html =str_replace('{id}', 'fitem_' . $element->getAttribute('id'), $html);
$html =str_replace('{type}', 'f'.$element->getType(), $html);
$html =str_replace('{name}', $element->getName(), $html);
$html =str_replace('{class}', $element->getAttribute('class'), $html);
$emptylabel = '';
if ($element->getLabel() == '') {
$emptylabel = 'femptylabel';

View file

@ -1,212 +0,0 @@
Feedback-Module
===============
Overview
--------
The Feedback-Module is intended to create individual surveys in an easy way.
This module consists of two parts
a) the "activity" feedback (required)
b) the "sideblock" feedback (optional)
The activity is the main part an can run without the block. Here you can create, fill out or analyse the surveys.
The sideblock is an optional part. It works as a bridge between different courses and
an central placed feedback-activity. So you can create one feedback on the main site of moodle and then publish
it in many courses.
Requirements
------------
Moodle 1.9 or later
Installation
------------
The zip-archive includes the same directory hierarchy as moodle
So you only have to copy the files to the correspondent place.
copy the folder feedback.zip/mod/feedback --> moodle/mod/feedback
and the folder feedback.zip/blocks/feedback --> moodle/blocks/feedback
The langfiles normaly can be left into the folder mod/feedback/lang.
The only exception is the feedback-block. The langfile is block_feedback.php and
have to be copied into the correspondent lang folder of moodle/moodledata.
All languages should be encoded with utf8.
After it you have to run the admin-page of moodle (http://your-moodle-site/admin)
in your browser. You have to loged in as admin before.
The installation process will be displayed on the screen.
That's all.
using the block-feature
-----------------------
1. create one or more new feedback-activitys on the moodle main-site
2. go into some course and enable the feedback-block. This block now shows the feedbacks from the main-site.
3. login as student and go into the course where the feedback-block is enabled
4. fill out the feedback chosen from block
5. login as admin and look at the feedback you created above
6. now you can analyse the answers over the courses
good luck
CHANGELOG
=========
04.04.2008
- the heading has not supported multilang strings
03.04.2008
- anonymous feedback was send the userid on email-notification
(http://tracker.moodle.org/browse/CONTRIB-355)
- users can not see the own values if there are chars like single-(') or doublequotas (")
08.03.2008
- admin users now respect capability-setting
(http://tracker.moodle.org/browse/CONTRIB-321)
17.12.2007
- resolved issue http://tracker.moodle.org/browse/CONTRIB-231
03.12.2007
- changing the table feedback_template, field public -> ispublic, public is reserved in oracle
- resolved issue http://tracker.moodle.org/browse/CONTRIB-95
16.09.2007
- changing access.php, removed the lines with coursecreator, added some RISK_xxx
- removed the check of legacy roles on has_capability()
- coursesearch now use unicode characters
13.09.2007
- updated edit.php to make the output more xhtml 1.0 strict like
11.09.2007
- Update feedback settings has help showing wrongly
- Menu on "Add question to activity" should be sorted alphabetically
- missing "Add Pagebreak" is now at the item-list
- no hardcoded css
- use new print_header() (note it only is available on moodle 1.9!!!)
- missing sesskey checks in feedback
- uninitialised $filename when importing into feedback
31.07.2007
- fixed bug with missing numbers after xml Question-Import.
29.07.2007
- added "require_course_login()" in view.php
- added missing langstring "no_itemname"
25.07.2007
- now defined in applicable_formats() to hide the block in moodle My-Site
07.07.2007
- all functions in lib.php now are with comments in phpdoc-style
- removed all depricated function-calls
- some code-styling changes (http://docs.moodle.org/en/Coding)
06.07.2007
- Adding some missing lang-strings
- fixing some notice-messages with $SESSION-lstgroupid
- excelexport now uses the localwincharset from langconfig.php
Now it is possible to export excel with utf8. But to many data will crash the excel
file. If the excefile crashes so you switch to latin-export in lang-settings
- adding the default permission CAP_ALLOW to the legacy-role:user for the capabilities view and complete
24.06.2007
- fixed excel-problem with tempfiles
- added new field "idnumber" into excel detailed report
21.06.2007
- better support for xhtml
09.05.2007
- items now are classes
- most of forms use formslib
- gui now uses tabs
- new item "captcha"
Now it only runs on Moodle 1.8 or later
09.05.2007
- added two columns (random_response,anonymous_response) to feedback_complete and feedback_complete_tmp
- userids now will be logged even if the feedback is anonymous so you now can filter by group
- excelexport now use pear so cell-values can be greater then 255 chars
- logs now include the cm->id
16.01.2007
- the installation now uses the install.xml
- roles are full implemented
- now radiobuttons and checkboxes can be aligned horizontally or vertically
- now you can insert pagebreakes
- a feedback what is switch to the next page is saved temporary.
the user can cancel the completion and later continue at the last filled page.
- now you can ex-/import feedbacks into/from a xml-file
- course-reseting is supported
01.01.2007
happy new year!
14.09.2006 21:22
improve the layout of analysis (thanks to Katja Krueger)
02.06.2006 21:22
several bugfixes
improve the block "feedback"
20.05.2006 01:00
adding the block "feedback" to publish feedback over all courses
Thanks to Jun Yamog!
21.04.2006 16:00
version 2006042102
adding moving behavior like moodle activities
adding a dropdownlist on create/update item page to adjust the position
21.04.2006 16:00
version 2006042101
prefixed all function-names like "feedback_"
fixed security issues (e.g. optional_variable() >> optional_param())
improve group-feature
03.01.2006 16:00
Added "addslashes" and "stripslashes_safe" for preserving (')
03.10.2005 13:00
action handling error recovery improved (failed when debug=false)
function feedback_action_handler() argument list changed
added action handler debug modes: silent, normal, verbose
30.09.2005 00:00
version 2005300900
action handling functions added
picture item (an example for action handling added)
XHTML compliance improved
number of PHP Notify-level errors reduced
source code transferred to CVS
14.09.2005 00:20
fixed problem with restoring
new feature user-tracking (prevent multiple_submit)
new feature deleting of some completeds
22.08.2005 19:12
fixed problem with secureforms-option
16.08.2005 14:07
fixed html-syntax in edit.php
12.08.2005 21:38
fixed problem with IE
If feedback is not anonym now guest is it not allowed to fill it out
11.08.2005 22:00
added email-notification
anonymous feedbacks can be filled out by anonymous users
03.08.2005 01:20
item specific functions were moved into the items-librarys
now developers can create individual feedback-items
javascript based filling-control was replaced by php-based control
version = 2005072000
20.07.2005 01:09
adding group-ability
fixed missing bcmod()-Function-Problem
fixed referer-problem under https

View file

@ -1,6 +0,0 @@
- items use formslib
- structured Numbering and switching visible or not
- printview
- css
- the email displays the completed feedback
-

1
mod/feedback/amd/build/edit.min.js vendored Normal file
View file

@ -0,0 +1 @@
define(["jquery","core/ajax","core/str","core/notification"],function(a,b,c,d){var e={deleteItem:function(b){b.preventDefault(),c.get_strings([{key:"confirmation",component:"admin"},{key:"confirmdeleteitem",component:"mod_feedback"},{key:"yes",component:"moodle"},{key:"no",component:"moodle"}]).done(function(c){d.confirm(c[0],c[1],c[2],c[3],a.proxy(function(){window.location=a(this).attr("href")},b.currentTarget))})},setup:function(){a("body").delegate('[data-action="delete"]',"click",e.deleteItem)}};return{setup:e.setup}});

View file

@ -0,0 +1,61 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Edit items in feedback module
*
* @module mod_feedback/edit
* @package mod_feedback
* @copyright 2016 Marina Glancy
*/
define(['jquery', 'core/ajax', 'core/str', 'core/notification'],
function($, ajax, str, notification) {
var manager = {
deleteItem: function(e) {
e.preventDefault();
str.get_strings([
{
key: 'confirmation',
component: 'admin'
},
{
key: 'confirmdeleteitem',
component: 'mod_feedback'
},
{
key: 'yes',
component: 'moodle'
},
{
key: 'no',
component: 'moodle'
}
]).done(function(s) {
notification.confirm(s[0], s[1], s[2], s[3], $.proxy(function() {
window.location = $(this).attr('href');
}, e.currentTarget));
});
},
setup: function() {
$('body').delegate('[data-action="delete"]', 'click', manager.deleteItem);
}
};
return {
setup: manager.setup
};
});

View file

@ -36,16 +36,15 @@ list($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
require_course_login($course, true, $cm);
$feedback = $PAGE->activityrecord;
$feedbackstructure = new mod_feedback_structure($feedback, $cm);
$context = context_module::instance($cm->id);
if (!feedback_can_view_analysis($feedback, $context)) {
if (!$feedbackstructure->can_view_analysis()) {
print_error('error');
}
/// Print the page header
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
$PAGE->set_heading($course->fullname);
$PAGE->set_title($feedback->name);
@ -57,63 +56,31 @@ require('tabs.php');
//get the groupid
$myurl = $CFG->wwwroot.'/mod/feedback/analysis.php?id='.$cm->id.'&do_show=analysis';
$mygroupid = groups_get_activity_group($cm, true);
groups_print_activity_menu($cm, $myurl);
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));
//get completed feedbacks
$completedscount = feedback_get_completeds_group_count($feedback, $mygroupid);
echo '<div class="analysis_header">';
// Show the submissions count.
echo '<b>'.get_string('completed_feedbacks', 'feedback').': '.$completedscount. '</b><br />';
// get the items of the feedback
$items = $DB->get_records('feedback_item',
array('feedback'=>$feedback->id, 'hasvalue'=>1),
'position');
// Show the items count.
if (is_array($items)) {
echo '<b>'.get_string('questions', 'feedback').': ' .count($items). ' </b><hr />';
} else {
$items=array();
}
echo '</div>';
// Get the items of the feedback.
$items = $feedbackstructure->get_items(true);
$check_anonymously = true;
if ($mygroupid > 0 AND $feedback->anonymous == FEEDBACK_ANONYMOUS_YES) {
if ($completedscount < FEEDBACK_MIN_ANONYMOUS_COUNT_IN_GROUP) {
$completedcount = $feedbackstructure->count_completed_responses($mygroupid);
if ($completedcount < FEEDBACK_MIN_ANONYMOUS_COUNT_IN_GROUP) {
$check_anonymously = false;
}
}
echo '<div>';
if ($check_anonymously) {
$itemnr = 0;
//print the items in an analysed form
// Print the items in an analysed form.
foreach ($items as $item) {
if ($item->hasvalue == 0) {
continue;
}
echo '<table width="100%" class="generalbox">';
//get the class of item-typ
echo "<table class=\"analysis itemtype_{$item->typ}\">";
$itemobj = feedback_get_item_class($item->typ);
$itemnr++;
if ($feedback->autonumbering) {
$printnr = $itemnr.'.';
} else {
$printnr = '';
}
$printnr = ($feedback->autonumbering && $item->itemnr) ? ($item->itemnr . '.') : '';
$itemobj->print_analysed($item, $printnr, $mygroupid);
echo '</table>';
}

View file

@ -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,31 +43,27 @@ if ($courseitemfilter !== '0') {
if ($courseitemfiltertyp !== '0') {
$url->param('courseitemfiltertyp', $courseitemfiltertyp);
}
if ($searchcourse !== '') {
$url->param('searchcourse', $searchcourse);
}
$PAGE->set_url($url);
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');
}
list($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
$context = context_module::instance($cm->id);
require_login($course, true, $cm);
require_course_login($course, true, $cm);
$feedback = $PAGE->activityrecord;
if (!($feedback->publish_stats OR has_capability('mod/feedback:viewreports', $context))) {
print_error('error');
}
$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");
@ -81,33 +76,18 @@ 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;
//get completed feedbacks
$completedscount = feedback_get_completeds_group_count($feedback, $mygroupid, $courseid);
//show the count
echo '<b>'.get_string('completed_feedbacks', 'feedback').': '.$completedscount. '</b><br />';
$courseselectform->display();
// get the items of the feedback
$params = array('feedback' => $feedback->id, 'hasvalue' => 1);
$items = $DB->get_records('feedback_item', $params, 'position');
//show the count
if (is_array($items)) {
echo '<b>'.get_string('questions', 'feedback').': ' .count($items). ' </b><hr />';
}
// Show the summary.
$summary = new mod_feedback\output\summary($feedbackstructure);
echo $OUTPUT->render_from_template('mod_feedback/summary', $summary->export_for_template($OUTPUT));
// Get the items of the feedback.
$items = $feedbackstructure->get_items(true);
if ($courseitemfilter > 0) {
$sumvalue = 'SUM(' . $DB->sql_cast_char2real('value', true) . ')';
@ -123,8 +103,6 @@ if ($courseitemfilter > 0) {
echo '<div class="clearfix">';
echo '<table>';
echo '<tr><th>Course</th><th>Average</th></tr>';
$sep_dec = get_string('separator_decimal', 'feedback');
$sep_thous = get_string('separator_thousand', 'feedback');
foreach ($courses as $c) {
$coursecontext = context_course::instance($c->course_id);
@ -133,7 +111,7 @@ if ($courseitemfilter > 0) {
echo '<tr>';
echo '<td>'.$shortname.'</td>';
echo '<td align="right">';
echo number_format(($c->sumvalue / $c->countvalue), 2, $sep_dec, $sep_thous);
echo format_float(($c->sumvalue / $c->countvalue), 2);
echo '</td>';
echo '</tr>';
}
@ -146,59 +124,12 @@ if ($courseitemfilter > 0) {
echo '</a></p>';
} else {
echo '<div class="mdl-align">';
echo '<form name="report" method="get" id="analysis-form">';
echo html_writer::label(get_string('search_course', 'feedback') . ': ', 'searchcourse');
echo '<input id="searchcourse" type="text" name="searchcourse" value="'.s($searchcourse).'"/> ';
echo '<input type="submit" value="'.get_string('search').'"/>';
echo '<input type="hidden" name="id" value="'.$id.'" />';
$sql = 'select DISTINCT c.id, c.shortname from {course} c, '.
'{feedback_value} fv, {feedback_item} fi '.
'where c.id = fv.course_id and fv.item = fi.id '.
'and fi.feedback = ? '.
'and
('.$DB->sql_like('c.shortname', '?', false).'
OR '.$DB->sql_like('c.fullname', '?', false).')';
$params = array($feedback->id, "%$searchcourse%", "%$searchcourse%");
if ($courses = $DB->get_records_sql_menu($sql, $params)) {
if (!$courseid) {
$courses = array('' => get_string('choosedots')) + $courses;
}
echo ' '. html_writer::label(get_string('filter_by_course', 'feedback'). ': ', 'coursefilterid');
echo html_writer::select($courses, 'courseid', $courseid,
null, array('id'=>'coursefilterid', 'class' => 'autosubmit'));
$PAGE->requires->yui_module('moodle-core-formautosubmit',
'M.core.init_formautosubmit',
array(array('selectid' => 'coursefilterid', 'nothing' => false))
);
}
if ($courseid) {
echo ' <a href="analysis_course.php?id=' . $id . '">';
echo get_string('show_all', 'feedback');
echo '</a>';
}
echo '</form>';
echo '</div>';
echo '<hr />';
$itemnr = 0;
//print the items in an analysed form
// Print the items in an analysed form.
foreach ($items as $item) {
if ($item->hasvalue == 0) {
continue;
}
echo '<table>';
//get the class from item-typ
echo '<table class="analysis">';
$itemobj = feedback_get_item_class($item->typ);
$itemnr++;
if ($feedback->autonumbering) {
$printnr = $itemnr.'.';
} else {
$printnr = '';
}
$itemobj->print_analysed($item, $printnr, $mygroupid, $courseid);
$printnr = ($feedback->autonumbering && $item->itemnr) ? ($item->itemnr . '.') : '';
$itemobj->print_analysed($item, $printnr, $mygroupid, $feedbackstructure->get_courseid());
if (preg_match('/rated$/i', $item->typ)) {
$url = new moodle_url('/mod/feedback/analysis_course.php', array('id' => $id,
'courseitemfilter' => $item->id, 'courseitemfiltertyp' => $item->typ));

View file

@ -1,312 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* 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);
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)
$params = array('feedback' => $feedback->id, 'hasvalue' => 1);
if (!$items = $DB->get_records('feedback_item', $params, 'position')) {
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 = feedback_get_completeds_group_count($feedback, $mygroupid, $coursefilter);
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;
}

View file

@ -59,7 +59,8 @@ class backup_feedback_activity_structure_step extends backup_activity_structure_
'userid',
'timemodified',
'random_response',
'anonymous_response'));
'anonymous_response',
'courseid'));
$items = new backup_nested_element('items');
@ -76,19 +77,14 @@ class backup_feedback_activity_structure_step extends backup_activity_structure_
'dependvalue',
'options'));
$trackings = new backup_nested_element('trackings');
$tracking = new backup_nested_element('tracking', array('id'), array(
'userid',
'completed'));
$values = new backup_nested_element('values');
$value = new backup_nested_element('value', array('id'), array(
'item',
'template',
'completed',
'value'));
'value',
'course_id'));
// Build the tree
$feedback->add_child($items);
@ -100,9 +96,6 @@ class backup_feedback_activity_structure_step extends backup_activity_structure_
$completed->add_child($values);
$values->add_child($value);
$feedback->add_child($trackings);
$trackings->add_child($tracking);
// Define sources
$feedback->set_source_table('feedback', array('id' => backup::VAR_ACTIVITYID));
@ -117,16 +110,12 @@ class backup_feedback_activity_structure_step extends backup_activity_structure_
array(backup::VAR_PARENTID));
$value->set_source_table('feedback_value', array('completed' => backup::VAR_PARENTID));
$tracking->set_source_table('feedback_tracking', array('feedback' => backup::VAR_PARENTID));
}
// Define id annotations
$completed->annotate_ids('user', 'userid');
$tracking->annotate_ids('user', 'userid');
// Define file annotations
$feedback->annotate_files('mod_feedback', 'intro', null); // This file area hasn't itemid

View file

@ -40,7 +40,6 @@ class restore_feedback_activity_structure_step extends restore_activity_structur
if ($userinfo) {
$paths[] = new restore_path_element('feedback_completed', '/activity/feedback/completeds/completed');
$paths[] = new restore_path_element('feedback_value', '/activity/feedback/completeds/completed/values/value');
$paths[] = new restore_path_element('feedback_tracking', '/activity/feedback/trackings/tracking');
}
// Return the paths wrapped into standard activity structure
@ -86,6 +85,13 @@ class restore_feedback_activity_structure_step extends restore_activity_structur
$data->feedback = $this->get_new_parentid('feedback');
$data->userid = $this->get_mappingid('user', $data->userid);
$data->timemodified = $this->apply_date_offset($data->timemodified);
if ($this->task->is_samesite() && !empty($data->courseid)) {
$data->courseid = $data->courseid;
} else if ($this->get_courseid() == SITEID) {
$data->courseid = SITEID;
} else {
$data->courseid = 0;
}
$newitemid = $DB->insert_record('feedback_completed', $data);
$this->set_mapping('feedback_completed', $oldid, $newitemid);
@ -98,25 +104,18 @@ class restore_feedback_activity_structure_step extends restore_activity_structur
$oldid = $data->id;
$data->completed = $this->get_new_parentid('feedback_completed');
$data->item = $this->get_mappingid('feedback_item', $data->item);
$data->course_id = $this->get_courseid();
if ($this->task->is_samesite() && !empty($data->course_id)) {
$data->course_id = $data->course_id;
} else if ($this->get_courseid() == SITEID) {
$data->course_id = SITEID;
} else {
$data->course_id = 0;
}
$newitemid = $DB->insert_record('feedback_value', $data);
$this->set_mapping('feedback_value', $oldid, $newitemid);
}
protected function process_feedback_tracking($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
$data->feedback = $this->get_new_parentid('feedback');
$data->completed = $this->get_mappingid('feedback_completed', $data->completed);
$data->userid = $this->get_mappingid('user', $data->userid);
$newitemid = $DB->insert_record('feedback_tracking', $data);
}
protected function after_execute() {
// Add feedback related files, no need to match by itemname (just internally handled context)
$this->add_related_files('mod_feedback', 'intro', null);

View file

@ -0,0 +1,583 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains class mod_feedback_complete_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();
/**
* Class mod_feedback_complete_form
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_feedback_complete_form extends moodleform {
/** @var int */
const MODE_COMPLETE = 1;
/** @var int */
const MODE_PRINT = 2;
/** @var int */
const MODE_EDIT = 3;
/** @var int */
const MODE_VIEW_RESPONSE = 4;
/** @var int */
const MODE_VIEW_TEMPLATE = 5;
/** @var int */
protected $mode;
/** @var mod_feedback_structure|mod_feedback_completion */
protected $structure;
/** @var mod_feedback_completion */
protected $completion;
/** @var int */
protected $gopage;
/** @var bool */
protected $hasrequired = false;
/**
* Constructor
*
* @param int $mode
* @param mod_feedback_structure $structure
* @param string $formid CSS id attribute of the form
* @param array $customdata
*/
public function __construct($mode, mod_feedback_structure $structure, $formid, $customdata = null) {
$this->mode = $mode;
$this->structure = $structure;
$this->gopage = isset($customdata['gopage']) ? $customdata['gopage'] : 0;
$isanonymous = $this->structure->is_anonymous() ? ' ianonymous' : '';
parent::__construct(null, $customdata, 'POST', '',
array('id' => $formid, 'class' => 'feedback_form' . $isanonymous), true);
}
/**
* Form definition
*/
public function definition() {
$mform = $this->_form;
$mform->addElement('hidden', 'id', $this->get_cm()->id);
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'courseid', $this->get_current_course_id());
$mform->setType('courseid', PARAM_INT);
$mform->addElement('hidden', 'gopage');
$mform->setType('gopage', PARAM_INT);
$mform->addElement('hidden', 'lastpage');
$mform->setType('lastpage', PARAM_INT);
$mform->addElement('hidden', 'startitempos');
$mform->setType('startitempos', PARAM_INT);
$mform->addElement('hidden', 'lastitempos');
$mform->setType('lastitempos', PARAM_INT);
if (isloggedin() && !isguestuser() && $this->mode != self::MODE_EDIT && $this->mode != self::MODE_VIEW_TEMPLATE &&
$this->mode != self::MODE_VIEW_RESPONSE) {
// Output information about the current mode (anonymous or not) in some modes.
if ($this->structure->is_anonymous()) {
$anonymousmodeinfo = get_string('anonymous', 'feedback');
} else {
$anonymousmodeinfo = get_string('non_anonymous', 'feedback');
}
$element = $mform->addElement('static', 'anonymousmode', '',
get_string('mode', 'feedback') . ': ' . $anonymousmodeinfo);
$element->setAttributes($element->getAttributes() + ['class' => 'feedback_mode']);
}
// Add buttons to go to previous/next pages and submit the feedback.
if ($this->mode == self::MODE_COMPLETE) {
$buttonarray = array();
$buttonarray[] = &$mform->createElement('submit', 'gopreviouspage', get_string('previous_page', 'feedback'));
$buttonarray[] = &$mform->createElement('submit', 'gonextpage', get_string('next_page', 'feedback'),
array('class' => 'form-submit'));
$buttonarray[] = &$mform->createElement('submit', 'savevalues', get_string('save_entries', 'feedback'),
array('class' => 'form-submit'));
$buttonarray[] = &$mform->createElement('static', 'buttonsseparator', '', '<br>');
$buttonarray[] = &$mform->createElement('cancel');
$mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
$mform->closeHeaderBefore('buttonar');
}
// Set data.
$this->set_data(array('gopage' => $this->gopage));
}
/**
* This method is called after definition(), data submission and set_data().
* All form setup that is dependent on form values should go in here.
*/
public function definition_after_data() {
parent::definition_after_data();
if ($this->mode == self::MODE_COMPLETE) {
$this->definition_after_data_complete();
} else {
$this->definition_after_data_preview();
}
}
/**
* Called from definition_after_data() in the completion mode
*
* This will add only items from a current page to the feedback and adjust the buttons
*/
protected function definition_after_data_complete() {
if (!$this->structure instanceof mod_feedback_completion) {
// We should not really be here but just in case.
return;
}
$pages = $this->structure->get_pages();
$gopage = $this->gopage;
$pageitems = $pages[$gopage];
$hasnextpage = $gopage < count($pages) - 1; // Until we complete this page we can not trust get_next_page().
$hasprevpage = $gopage && ($this->structure->get_previous_page($gopage, false) !== null);
// Add elements.
foreach ($pageitems as $item) {
$itemobj = feedback_get_item_class($item->typ);
$itemobj->complete_form_element($item, $this);
}
// Remove invalid buttons (for example, no "previous page" if we are on the first page).
if (!$hasprevpage) {
$this->remove_button('gopreviouspage');
}
if (!$hasnextpage) {
$this->remove_button('gonextpage');
}
if ($hasnextpage) {
$this->remove_button('savevalues');
}
}
/**
* Called from definition_after_data() in all modes except for completion
*
* This will add all items to the form, including pagebreaks as horizontal rules.
*/
protected function definition_after_data_preview() {
foreach ($this->structure->get_items() as $feedbackitem) {
$itemobj = feedback_get_item_class($feedbackitem->typ);
$itemobj->complete_form_element($feedbackitem, $this);
}
}
/**
* Removes the button that is not applicable for the current page
*
* @param string $buttonname
*/
private function remove_button($buttonname) {
$el = $this->_form->getElement('buttonar');
foreach ($el->_elements as $idx => $button) {
if ($button instanceof MoodleQuickForm_submit && $button->getName() === $buttonname) {
unset($el->_elements[$idx]);
return;
}
}
}
/**
* Returns value for this element that is already stored in temporary or permanent table,
* usually only available when user clicked "Previous page". Null means no value is stored.
*
* @param stdClass $item
* @return string
*/
public function get_item_value($item) {
if ($this->structure instanceof mod_feedback_completion) {
return $this->structure->get_item_value($item);
}
return null;
}
/**
* Can be used by the items to get the course id for which feedback is taken
*
* This function returns 0 for feedbacks that are located inside the courses.
* $this->get_feedback()->course will return the course where feedback is located.
* $this->get_current_course_id() will return the course where user was before taking the feedback
*
* @return int
*/
public function get_course_id() {
return $this->structure->get_courseid();
}
/**
* Record from 'feedback' table corresponding to the current feedback
* @return stdClass
*/
public function get_feedback() {
return $this->structure->get_feedback();
}
/**
* Current feedback mode, see constants on the top of this class
* @return int
*/
public function get_mode() {
return $this->mode;
}
/**
* Returns whether the form is frozen, some items may prefer to change the element
* type in case of frozen form. For example, text or textarea element does not look
* nice when frozen
*
* @return bool
*/
public function is_frozen() {
return $this->mode == self::MODE_VIEW_RESPONSE;
}
/**
* Returns the current course module
* @return cm_info
*/
public function get_cm() {
return $this->structure->get_cm();
}
/**
* Returns the course where user was before taking the feedback.
*
* For feedbacks inside the course it will be the same as $this->get_feedback()->course.
* For feedbacks on the frontpage it will be the same as $this->get_course_id()
*
* @return int
*/
public function get_current_course_id() {
return $this->structure->get_courseid() ?: $this->get_feedback()->course;
}
/**
* CSS class for the item
* @param stdClass $item
* @return string
*/
protected function get_suggested_class($item) {
$class = "feedback_itemlist feedback-item-{$item->typ}";
if ($item->dependitem) {
$class .= " feedback_is_dependent";
}
if ($item->typ !== 'pagebreak') {
$itemobj = feedback_get_item_class($item->typ);
if ($itemobj->get_hasvalue()) {
$class .= " feedback_hasvalue";
}
}
return $class;
}
/**
* Adds an element to this form - to be used by items in their complete_form_element() method
*
* @param stdClass $item
* @param HTML_QuickForm_element|array $element either completed form element or an array that
* can be passed as arguments to $this->_form->createElement() function
* @param bool $addrequiredrule automatically add 'required' rule
* @param bool $setdefaultvalue automatically set default value for element
* @return HTML_QuickForm_element
*/
public function add_form_element($item, $element, $addrequiredrule = true, $setdefaultvalue = true) {
global $OUTPUT;
// Add element to the form.
if (is_array($element)) {
if ($this->is_frozen() && $element[0] === 'text') {
// Convert 'text' element to 'static' when freezing for better display.
$element = ['static', $element[1], $element[2]];
}
$element = call_user_func_array(array($this->_form, 'createElement'), $element);
}
$element = $this->_form->addElement($element);
// Prepend standard CSS classes to the element classes.
$attributes = $element->getAttributes();
$class = !empty($attributes['class']) ? ' ' . $attributes['class'] : '';
$attributes['class'] = $this->get_suggested_class($item) . $class;
$element->setAttributes($attributes);
// Add required rule.
if ($item->required && $addrequiredrule) {
$this->_form->addRule($element->getName(), get_string('required'), 'required', null, 'client');
}
// Set default value.
if ($setdefaultvalue && ($tmpvalue = $this->get_item_value($item))) {
$this->_form->setDefault($element->getName(), $tmpvalue);
}
// Freeze if needed.
if ($this->is_frozen()) {
$element->freeze();
}
// Add red asterisks on required fields.
if ($item->required) {
$required = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$element->setLabel($element->getLabel() . $required);
$this->hasrequired = true;
}
// Add different useful stuff to the question name.
$this->add_item_label($item, $element);
$this->add_item_dependencies($item, $element);
$this->add_item_number($item, $element);
if ($this->mode == self::MODE_EDIT) {
$this->enhance_name_for_edit($item, $element);
}
return $element;
}
/**
* Adds a group element to this form - to be used by items in their complete_form_element() method
*
* @param stdClass $item
* @param string $groupinputname name for the form element
* @param string $name question text
* @param array $elements array of arrays that can be passed to $this->_form->createElement()
* @param string $separator separator between group elements
* @param string $class additional CSS classes for the form element
* @return HTML_QuickForm_element
*/
public function add_form_group_element($item, $groupinputname, $name, $elements, $separator,
$class = '') {
$objects = array();
foreach ($elements as $element) {
$object = call_user_func_array(array($this->_form, 'createElement'), $element);
$objects[] = $object;
}
$element = $this->add_form_element($item,
['group', $groupinputname, $name, $objects, $separator, false],
false,
false);
if ($class !== '') {
$attributes = $element->getAttributes();
$attributes['class'] .= ' ' . $class;
$element->setAttributes($attributes);
}
return $element;
}
/**
* Adds an item number to the question name (if feedback autonumbering is on)
* @param stdClass $item
* @param HTML_QuickForm_element $element
*/
protected function add_item_number($item, $element) {
if ($this->get_feedback()->autonumbering && !empty($item->itemnr)) {
$name = $element->getLabel();
$element->setLabel(html_writer::span($item->itemnr. '.', 'itemnr') . ' ' . $name);
}
}
/**
* Adds an item label to the question name
* @param stdClass $item
* @param HTML_QuickForm_element $element
*/
protected function add_item_label($item, $element) {
if (strlen($item->label) && ($this->mode == self::MODE_EDIT || $this->mode == self::MODE_VIEW_TEMPLATE)) {
$name = $element->getLabel();
$name = '('.format_string($item->label).') '.$name;
$element->setLabel($name);
}
}
/**
* Adds a dependency description to the question name
* @param stdClass $item
* @param HTML_QuickForm_element $element
*/
protected function add_item_dependencies($item, $element) {
$allitems = $this->structure->get_items();
if ($item->dependitem && ($this->mode == self::MODE_EDIT || $this->mode == self::MODE_VIEW_TEMPLATE)) {
if (isset($allitems[$item->dependitem])) {
$dependitem = $allitems[$item->dependitem];
$name = $element->getLabel();
$name .= html_writer::span(' ('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')',
'feedback_depend');
$element->setLabel($name);
}
}
}
/**
* Returns the CSS id attribute that will be assigned by moodleform later to this element
* @param stdClass $item
* @param HTML_QuickForm_element $element
*/
protected function guess_element_id($item, $element) {
if (!$id = $element->getAttribute('id')) {
$attributes = $element->getAttributes();
$id = $attributes['id'] = 'feedback_item_' . $item->id;
$element->setAttributes($attributes);
}
if ($element->getType() === 'group') {
return 'fgroup_' . $id;
}
return 'fitem_' . $id;
}
/**
* Adds editing actions to the question name in the edit mode
* @param stdClass $item
* @param HTML_QuickForm_element $element
*/
protected function enhance_name_for_edit($item, $element) {
global $OUTPUT;
$menu = new action_menu();
$menu->set_owner_selector('#' . $this->guess_element_id($item, $element));
$menu->set_constraint('.feedback_form');
$menu->set_alignment(action_menu::TR, action_menu::BR);
$menu->set_menu_trigger(get_string('edit'));
$menu->do_not_enhance();
$menu->prioritise = true;
$itemobj = feedback_get_item_class($item->typ);
$actions = $itemobj->edit_actions($item, $this->get_feedback(), $this->get_cm());
foreach ($actions as $action) {
$menu->add($action);
}
$editmenu = $OUTPUT->render($menu);
$name = $element->getLabel();
$name = html_writer::span('', 'itemdd', array('id' => 'feedback_item_box_' . $item->id)) .
html_writer::span($name, 'itemname') .
html_writer::span($editmenu, 'itemactions');
$element->setLabel(html_writer::span($name, 'itemtitle'));
}
/**
* Sets the default value for form element - alias to $this->_form->setDefault()
* @param HTML_QuickForm_element|string $element
* @param mixed $defaultvalue
*/
public function set_element_default($element, $defaultvalue) {
if ($element instanceof HTML_QuickForm_element) {
$element = $element->getName();
}
$this->_form->setDefault($element, $defaultvalue);
}
/**
* Sets the default value for form element - wrapper to $this->_form->setType()
* @param HTML_QuickForm_element|string $element
* @param int $type
*/
public function set_element_type($element, $type) {
if ($element instanceof HTML_QuickForm_element) {
$element = $element->getName();
}
$this->_form->setType($element, $type);
}
/**
* Adds a validation rule for the given field - wrapper for $this->_form->addRule()
*
* Do not use for 'required' rule!
* Required * will be added automatically, if additional validation is needed
* use method {@link self::add_validation_rule()}
*
* @param string $element Form element name
* @param string $message Message to display for invalid data
* @param string $type Rule type, use getRegisteredRules() to get types
* @param string $format (optional)Required for extra rule data
* @param string $validation (optional)Where to perform validation: "server", "client"
* @param bool $reset Client-side validation: reset the form element to its original value if there is an error?
* @param bool $force Force the rule to be applied, even if the target form element does not exist
*/
public function add_element_rule($element, $message, $type, $format = null, $validation = 'server',
$reset = false, $force = false) {
if ($element instanceof HTML_QuickForm_element) {
$element = $element->getName();
}
$this->_form->addRule($element, $message, $type, $format, $validation, $reset, $force);
}
/**
* Adds a validation rule to the form
*
* @param callable $callback with arguments ($values, $files)
*/
public function add_validation_rule(callable $callback) {
if ($this->mode == self::MODE_COMPLETE) {
$this->_form->addFormRule($callback);
}
}
/**
* Returns a reference to the element - wrapper for function $this->_form->getElement()
*
* @param string $elementname Element name
* @return HTML_QuickForm_element reference to element
*/
public function get_form_element($elementname) {
return $this->_form->getElement($elementname);
}
/**
* Displays the form
*/
public function display() {
global $OUTPUT, $PAGE;
// Finalize the form definition if not yet done.
if (!$this->_definition_finalized) {
$this->_definition_finalized = true;
$this->definition_after_data();
}
$mform = $this->_form;
// Add "This form has required fields" text in the bottom of the form.
if (($mform->_required || $this->hasrequired) &&
($this->mode == self::MODE_COMPLETE || $this->mode == self::MODE_PRINT || $this->mode == self::MODE_VIEW_TEMPLATE)) {
$element = $mform->addElement('static', 'requiredfields', '',
get_string('somefieldsrequired', 'form',
'<img alt="'.get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />'));
$element->setAttributes($element->getAttributes() + ['class' => 'requirednote']);
}
// Reset _required array so the default red * are not displayed.
$mform->_required = array();
// Move buttons to the end of the form.
if ($this->mode == self::MODE_COMPLETE) {
$mform->addElement('hidden', '__dummyelement');
$buttons = $mform->removeElement('buttonar', false);
$mform->insertElementBefore($buttons, '__dummyelement');
$mform->removeElement('__dummyelement');
}
$this->_form->display();
if ($this->mode == self::MODE_EDIT) {
$PAGE->requires->js_call_amd('mod_feedback/edit', 'setup');
}
}
}

View file

@ -0,0 +1,582 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains class mod_feedback_completion
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Collects information and methods about feedback completion (either complete.php or show_entries.php)
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_feedback_completion extends mod_feedback_structure {
/** @var stdClass */
protected $completed;
/** @var stdClass */
protected $completedtmp = null;
/** @var stdClass[] */
protected $valuestmp = null;
/** @var stdClass[] */
protected $values = null;
/** @var bool */
protected $iscompleted = false;
/**
* Constructor
*
* @param stdClass $feedback feedback object, in case of the template
* this is the current feedback the template is accessed from
* @param cm_info $cm course module object corresponding to the $feedback
* @param int $courseid current course (for site feedbacks only)
* @param bool $iscompleted has feedback been already completed? If yes either completedid or userid must be specified.
* @param int $completedid id in the table feedback_completed, may be omitted if userid is specified
* but it is highly recommended because the same user may have multiple responses to the same feedback
* for different courses
* @param int $userid id of the user - if specified only non-anonymous replies will be returned. If not
* specified only anonymous replies will be returned and the $completedid is mandatory.
*/
public function __construct($feedback, $cm, $courseid, $iscompleted = false, $completedid = null, $userid = null) {
global $DB;
// Make sure courseid is always set for site feedback and never for course feedback.
if ($feedback->course == SITEID) {
$courseid = $courseid ?: SITEID;
} else {
$courseid = 0;
}
parent::__construct($feedback, $cm, $courseid, 0);
if ($iscompleted) {
// Retrieve information about the completion.
$this->iscompleted = true;
$params = array('feedback' => $feedback->id);
if (!$userid && !$completedid) {
throw new coding_exception('Either $completedid or $userid must be specified for completed feedbacks');
}
if ($completedid) {
$params['id'] = $completedid;
}
if ($userid) {
// We must respect the anonymousity of the reply that the user saw when they were completing the feedback,
// not the current state that may have been changed later by the teacher.
$params['anonymous_response'] = FEEDBACK_ANONYMOUS_NO;
$params['userid'] = $userid;
}
$this->completed = $DB->get_record('feedback_completed', $params, '*', MUST_EXIST);
$this->courseid = $this->completed->courseid;
}
}
/**
* Returns a record from 'feedback_completed' table
* @return stdClass
*/
public function get_completed() {
return $this->completed;
}
/**
* Returns the temporary completion record for the current user or guest session
*
* @return stdClass|false record from feedback_completedtmp or false if not found
*/
protected function get_current_completed_tmp() {
global $USER, $DB;
if ($this->completedtmp === null) {
$params = array('feedback' => $this->get_feedback()->id);
if ($courseid = $this->get_courseid()) {
$params['courseid'] = $courseid;
}
if (isloggedin() && !isguestuser()) {
$params['userid'] = $USER->id;
} else {
$params['guestid'] = sesskey();
}
$this->completedtmp = $DB->get_record('feedback_completedtmp', $params);
}
return $this->completedtmp;
}
/**
* Can the current user see the item, if dependency is met?
*
* @param stdClass $item
* @return bool whether user can see item or not,
* null if dependency is broken or dependent question is not answered.
*/
protected function can_see_item($item) {
if (empty($item->dependitem)) {
return true;
}
if ($this->dependency_has_error($item)) {
return null;
}
$allitems = $this->get_items();
$ditem = $allitems[$item->dependitem];
$itemobj = feedback_get_item_class($ditem->typ);
if ($this->iscompleted) {
$value = $this->get_values($ditem);
} else {
$value = $this->get_values_tmp($ditem);
}
if ($value === null) {
return null;
}
return $itemobj->compare_value($ditem, $value, $item->dependvalue) ? true : false;
}
/**
* Dependency condition has an error
* @param stdClass $item
* @return bool
*/
protected function dependency_has_error($item) {
if (empty($item->dependitem)) {
// No dependency - no error.
return false;
}
$allitems = $this->get_items();
if (!array_key_exists($item->dependitem, $allitems)) {
// Looks like dependent item has been removed.
return true;
}
$itemids = array_keys($allitems);
$index1 = array_search($item->dependitem, $itemids);
$index2 = array_search($item->id, $itemids);
if ($index1 >= $index2) {
// Dependent item is after the current item in the feedback.
return true;
}
for ($i = $index1 + 1; $i < $index2; $i++) {
if ($allitems[$itemids[$i]]->typ === 'pagebreak') {
return false;
}
}
// There are no page breaks between dependent items.
return true;
}
/**
* Returns a value stored for this item in the feedback (temporary or not, depending on the mode)
* @param stdClass $item
* @return string
*/
public function get_item_value($item) {
if ($this->iscompleted) {
return $this->get_values($item);
} else {
return $this->get_values_tmp($item);
}
}
/**
* Returns all temporary values for this feedback or just a value for an item
* @param stdClass $item
* @return array
*/
protected function get_values_tmp($item = null) {
global $DB;
if ($this->valuestmp === null) {
$completedtmp = $this->get_current_completed_tmp();
if ($completedtmp) {
$this->valuestmp = $DB->get_records_menu('feedback_valuetmp',
['completed' => $completedtmp->id], '', 'item, value');
} else {
$this->valuestmp = array();
}
}
if ($item) {
return array_key_exists($item->id, $this->valuestmp) ? $this->valuestmp[$item->id] : null;
}
return $this->valuestmp;
}
/**
* Returns all completed values for this feedback or just a value for an item
* @param stdClass $item
* @return array
*/
protected function get_values($item = null) {
global $DB;
if ($this->values === null) {
if ($this->completed) {
$this->values = $DB->get_records_menu('feedback_value',
['completed' => $this->completed->id], '', 'item, value');
} else {
$this->values = array();
}
}
if ($item) {
return array_key_exists($item->id, $this->values) ? $this->values[$item->id] : null;
}
return $this->values;
}
/**
* Splits the feedback items into pages
*
* Items that we definitely know at this stage as not applicable are excluded.
* Items that are dependent on something that has not yet been answered are
* still present, as well as items with broken dependencies.
*
* @return array array of arrays of items
*/
public function get_pages() {
$pages = [[]]; // The first page always exists.
$items = $this->get_items();
foreach ($items as $item) {
if ($item->typ === 'pagebreak') {
$pages[] = [];
} else if ($this->can_see_item($item) !== false) {
$pages[count($pages) - 1][] = $item;
}
}
return $pages;
}
/**
* Returns the last page that has items with the value (i.e. not label) which have been answered
* as well as the first page that has items with the values that have not been answered.
*
* Either of the two return values may be null if there are no answered page or there are no
* unanswered pages left respectively.
*
* Two pages may not be directly following each other because there may be empty pages
* or pages with information texts only between them
*
* @return array array of two elements [$lastcompleted, $firstincompleted]
*/
protected function get_last_completed_page() {
$completed = [];
$incompleted = [];
$pages = $this->get_pages();
foreach ($pages as $pageidx => $pageitems) {
foreach ($pageitems as $item) {
if ($item->hasvalue) {
if ($this->get_values_tmp($item) !== null) {
$completed[$pageidx] = true;
} else {
$incompleted[$pageidx] = true;
}
}
}
}
$completed = array_keys($completed);
$incompleted = array_keys($incompleted);
// If some page has both completed and incompleted items it is considered incompleted.
$completed = array_diff($completed, $incompleted);
// If the completed page follows an incompleted page, it does not count.
$firstincompleted = $incompleted ? min($incompleted) : null;
if ($firstincompleted !== null) {
$completed = array_filter($completed, function($a) use ($firstincompleted) {
return $a < $firstincompleted;
});
}
$lastcompleted = $completed ? max($completed) : null;
return [$lastcompleted, $firstincompleted];
}
/**
* Get the next page for the feedback
*
* This is normally $gopage+1 but may be bigger if there are empty pages or
* pages without visible questions.
*
* This method can only be called when questions on the current page are
* already answered, otherwise it may be inaccurate.
*
* @param int $gopage current page
* @param bool $strictcheck when gopage is the user-input value, make sure we do not jump over unanswered questions
* @return int|null the index of the next page or null if this is the last page
*/
public function get_next_page($gopage, $strictcheck = true) {
if ($strictcheck) {
list($lastcompleted, $firstincompleted) = $this->get_last_completed_page();
if ($firstincompleted !== null && $firstincompleted <= $gopage) {
return $firstincompleted;
}
}
$pages = $this->get_pages();
for ($pageidx = $gopage + 1; $pageidx < count($pages); $pageidx++) {
if (!empty($pages[$pageidx])) {
return $pageidx;
}
}
// No further pages in the feedback have any visible items.
return null;
}
/**
* Get the previous page for the feedback
*
* This is normally $gopage-1 but may be smaller if there are empty pages or
* pages without visible questions.
*
* @param int $gopage current page
* @param bool $strictcheck when gopage is the user-input value, make sure we do not jump over unanswered questions
* @return int|null the index of the next page or null if this is the first page with items
*/
public function get_previous_page($gopage, $strictcheck = true) {
if (!$gopage) {
// If we are already on the first (0) page, there is definitely no previous page.
return null;
}
$pages = $this->get_pages();
$rv = null;
// Iterate through previous pages and find the closest one that has any items on it.
for ($pageidx = $gopage - 1; $pageidx >= 0; $pageidx--) {
if (!empty($pages[$pageidx])) {
$rv = $pageidx;
break;
}
}
if ($rv === null) {
// We are on the very first page that has items.
return null;
}
if ($rv > 0 && $strictcheck) {
// Check if this page is actually not past than first incompleted page.
list($lastcompleted, $firstincompleted) = $this->get_last_completed_page();
if ($firstincompleted !== null && $firstincompleted < $rv) {
return $firstincompleted;
}
}
return $rv;
}
/**
* Page index to resume the feedback
*
* When user abandones answering feedback and then comes back to it we should send him
* to the first page after the last page he fully completed.
* @return int
*/
public function get_resume_page() {
list($lastcompleted, $firstincompleted) = $this->get_last_completed_page();
return $lastcompleted === null ? 0 : $this->get_next_page($lastcompleted, false);
}
/**
* Creates a new record in the 'feedback_completedtmp' table for the current user/guest session
*
* @return stdClass record from feedback_completedtmp or false if not found
*/
protected function create_current_completed_tmp() {
global $USER, $DB;
$record = (object)['feedback' => $this->feedback->id];
if ($this->get_courseid()) {
$record->courseid = $this->get_courseid();
}
if (isloggedin() && !isguestuser()) {
$record->userid = $USER->id;
} else {
$record->guestid = sesskey();
}
$record->timemodified = time();
$record->anonymous_response = $this->feedback->anonymous;
$id = $DB->insert_record('feedback_completedtmp', $record);
$this->completedtmp = $DB->get_record('feedback_completedtmp', ['id' => $id]);
$this->valuestmp = null;
return $this->completedtmp;
}
/**
* Saves unfinished response to the temporary table
*
* This is called when user proceeds to the next/previous page in the complete form
* and also right after the form submit.
* After the form submit the {@link save_response()} is called to
* move response from temporary table to completion table.
*
* @param stdClass $data data from the form mod_feedback_complete_form
*/
public function save_response_tmp($data) {
global $DB;
if (!$completedtmp = $this->get_current_completed_tmp()) {
$completedtmp = $this->create_current_completed_tmp();
} else {
$currentime = time();
$DB->update_record('feedback_completedtmp',
['id' => $completedtmp->id, 'timemodified' => $currentime]);
$completedtmp->timemodified = $currentime;
}
// Find all existing values.
$existingvalues = $DB->get_records_menu('feedback_valuetmp',
['completed' => $completedtmp->id], '', 'item, id');
// Loop through all feedback items and save the ones that are present in $data.
$allitems = $this->get_items();
foreach ($allitems as $item) {
if (!$item->hasvalue) {
continue;
}
$keyname = $item->typ . '_' . $item->id;
if (!isset($data->$keyname)) {
// This item is either on another page or dependency was not met - nothing to save.
continue;
}
$newvalue = ['item' => $item->id, 'completed' => $completedtmp->id, 'course_id' => $completedtmp->courseid];
// Convert the value to string that can be stored in 'feedback_valuetmp' or 'feedback_value'.
$itemobj = feedback_get_item_class($item->typ);
$newvalue['value'] = $itemobj->create_value($data->$keyname);
// Update or insert the value in the 'feedback_valuetmp' table.
if (array_key_exists($item->id, $existingvalues)) {
$newvalue['id'] = $existingvalues[$item->id];
$DB->update_record('feedback_valuetmp', $newvalue);
} else {
$DB->insert_record('feedback_valuetmp', $newvalue);
}
}
// Reset valuestmp cache.
$this->valuestmp = null;
}
/**
* Saves the response
*
* The form data has already been stored in the temporary table in
* {@link save_response_tmp()}. This function copies the values
* from the temporary table to the completion table.
* It is also responsible for sending email notifications when applicable.
*/
public function save_response() {
global $USER, $SESSION, $DB;
$feedbackcompleted = $this->find_last_completed();
$feedbackcompletedtmp = $this->get_current_completed_tmp();
if (feedback_check_is_switchrole()) {
// We do not actually save anything if the role is switched, just delete temporary values.
$this->delete_completedtmp();
return;
}
// Save values.
$completedid = feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted);
$this->completed = $DB->get_record('feedback_completed', array('id' => $completedid));
// Send email.
if ($this->feedback->anonymous == FEEDBACK_ANONYMOUS_NO) {
feedback_send_email($this->cm, $this->feedback, $this->cm->get_course(), $USER);
} else {
feedback_send_email_anonym($this->cm, $this->feedback, $this->cm->get_course());
}
unset($SESSION->feedback->is_started);
// Update completion state.
$completion = new completion_info($this->cm->get_course());
if (isloggedin() && !isguestuser() && $completion->is_enabled($this->cm) && $this->feedback->completionsubmit) {
$completion->update_state($this->cm, COMPLETION_COMPLETE);
}
}
/**
* Deletes the temporary completed and all related temporary values
*/
protected function delete_completedtmp() {
global $DB;
if ($completedtmp = $this->get_current_completed_tmp()) {
$DB->delete_records('feedback_valuetmp', ['completed' => $completedtmp->id]);
$DB->delete_records('feedback_completedtmp', ['id' => $completedtmp->id]);
$this->completedtmp = null;
}
}
/**
* Retrieves the last completion record for the current user
*
* @return stdClass record from feedback_completed or false if not found
*/
protected function find_last_completed() {
global $USER, $DB;
if (isloggedin() || isguestuser()) {
// Not possible to retrieve completed feedback for guests.
return false;
}
if ($this->is_anonymous()) {
// Not possible to retrieve completed anonymous feedback.
return false;
}
$params = array('feedback' => $this->feedback->id, 'userid' => $USER->id);
if ($this->get_courseid()) {
$params['courseid'] = $this->get_courseid();
}
$this->completed = $DB->get_record('feedback_completed', $params);
return $this->completed;
}
/**
* Checks if current user has capability to submit the feedback
*
* There is an exception for fully anonymous feedbacks when guests can complete
* feedback without the proper capability.
*
* This should be followed by checking {@link can_submit()} because even if
* user has capablity to complete, they may have already submitted feedback
* and can not re-submit
*
* @return bool
*/
public function can_complete() {
global $CFG;
$context = context_module::instance($this->cm->id);
if (has_capability('mod/feedback:complete', $context)) {
return true;
}
if (!empty($CFG->feedback_allowfullanonymous)
AND $this->feedback->course == SITEID
AND $this->feedback->anonymous == FEEDBACK_ANONYMOUS_YES
AND (!isloggedin() OR isguestuser())) {
// Guests are allowed to complete fully anonymous feedback without having 'mod/feedback:complete' capability.
return true;
}
return false;
}
/**
* Checks if user is prevented from re-submission.
*
* This must be called after {@link can_complete()}
*
* @return bool
*/
public function can_submit() {
if ($this->get_feedback()->multiple_submit == 0 ) {
if ($this->is_already_submitted()) {
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,83 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* 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]);
}
}

View file

@ -50,6 +50,29 @@ class course_module_viewed extends \core\event\course_module_viewed {
$this->data['objecttable'] = 'feedback';
}
/**
* Creates an instance from feedback record
*
* @param stdClass $feedback
* @param cm_info|stdClass $cm
* @param stdClass $course
* @return course_module_viewed
*/
public static function create_from_record($feedback, $cm, $course) {
$event = self::create(array(
'objectid' => $feedback->id,
'context' => \context_module::instance($cm->id),
'anonymous' => ($feedback->anonymous == FEEDBACK_ANONYMOUS_YES),
'other' => array(
'anonymous' => $feedback->anonymous // Deprecated.
)
));
$event->add_record_snapshot('course_modules', $cm);
$event->add_record_snapshot('course', $course);
$event->add_record_snapshot('feedback', $feedback);
return $event;
}
/**
* Define whether a user can view the event or not. Make sure no one except admin can see details of an anonymous response.
*

View file

@ -54,6 +54,32 @@ class response_deleted extends \core\event\base {
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
}
/**
* Creates an instance from the record from db table feedback_completed
*
* @param stdClass $completed
* @param stdClass|cm_info $cm
* @param stdClass $feedback
* @return self
*/
public static function create_from_record($completed, $cm, $feedback) {
$event = self::create(array(
'relateduserid' => $completed->userid,
'objectid' => $completed->id,
'courseid' => $cm->course,
'context' => \context_module::instance($cm->id),
'anonymous' => ($completed->anonymous_response == FEEDBACK_ANONYMOUS_YES),
'other' => array(
'cmid' => $cm->id,
'instanceid' => $feedback->id,
'anonymous' => $completed->anonymous_response) // Deprecated.
));
$event->add_record_snapshot('feedback_completed', $completed);
$event->add_record_snapshot('feedback', $feedback);
return $event;
}
/**
* Returns localised general event name.
*

View file

@ -57,6 +57,29 @@ class response_submitted extends \core\event\base {
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
}
/**
* Creates an instance from the record from db table feedback_completed
*
* @param stdClass $completed
* @param stdClass|cm_info $cm
* @return self
*/
public static function create_from_record($completed, $cm) {
$event = self::create(array(
'relateduserid' => $completed->userid,
'objectid' => $completed->id,
'context' => \context_module::instance($cm->id),
'anonymous' => ($completed->anonymous_response == FEEDBACK_ANONYMOUS_YES),
'other' => array(
'cmid' => $cm->id,
'instanceid' => $completed->feedback,
'anonymous' => $completed->anonymous_response // Deprecated.
)
));
$event->add_record_snapshot('feedback_completed', $completed);
return $event;
}
/**
* Returns localised general event name.
*

View file

@ -0,0 +1,84 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains class mod_feedback\output\summary
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_feedback\output;
use renderable;
use templatable;
use renderer_base;
use stdClass;
use moodle_url;
use mod_feedback_structure;
/**
* Class to help display feedback summary
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class summary implements renderable, templatable {
/** @var mod_feedback_structure */
protected $feedbackstructure;
/** @var int */
protected $mygroupid;
/** @var bool */
protected $extradetails;
/**
* Constructor.
*
* @param mod_feedback_structure $feedbackstructure
* @param int $mygroupid currently selected group
* @param bool $extradetails display additional details (time open, time closed)
*/
public function __construct($feedbackstructure, $mygroupid = false, $extradetails = false) {
$this->feedbackstructure = $feedbackstructure;
$this->mygroupid = $mygroupid;
$this->extradetails = $extradetails;
}
/**
* Export this data so it can be used as the context for a mustache template.
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output) {
$r = new stdClass();
$r->completedcount = $this->feedbackstructure->count_completed_responses($this->mygroupid);
$r->itemscount = count($this->feedbackstructure->get_items(true));
if ($this->extradetails && ($timeopen = $this->feedbackstructure->get_feedback()->timeopen)) {
$r->timeopen = userdate($timeopen);
}
if ($this->extradetails && ($timeclose = $this->feedbackstructure->get_feedback()->timeclose)) {
$r->timeclose = userdate($timeclose);
}
return $r;
}
}

View file

@ -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);
}
}
}

View file

@ -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,11 @@ 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;
$deleteentryurl = new moodle_url($this->baseurl, ['delete' => $row->id, 'sesskey' => sesskey()]);
$deleteaction = new confirm_action(get_string('confirmdeleteentry', 'feedback'));
return $OUTPUT->action_icon($deleteentryurl,
new pix_icon('t/delete', get_string('delete_entry', 'feedback')), $deleteaction);
}
/**
@ -142,7 +195,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 +204,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 +269,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 +297,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);
}
}
/**
@ -206,12 +316,37 @@ class mod_feedback_responses_table extends table_sql {
return $this->grandtotal;
}
/**
* Defines columns
* @param array $columns an array of identifying names for columns. If
* columns are sorted then column names must correspond to a field in sql.
*/
public function define_columns($columns) {
parent::define_columns($columns);
foreach ($this->columns as $column => $column) {
// Automatically assign classes to columns.
$this->column_class[$column] = ' ' . $column;
}
}
/**
* 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');
@ -267,4 +402,27 @@ 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() {
global $OUTPUT;
if ($this->is_downloadable() && !$this->is_downloading()) {
return $OUTPUT->download_dataformat_selector(get_string('downloadas', 'table'),
$this->baseurl->out_omit_querystring(), $this->downloadparamname, $this->baseurl->params());
} else {
return '';
}
}
}

View file

@ -0,0 +1,329 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Contains class mod_feedback_structure
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Stores and manipulates the structure of the feedback or template (items, pages, etc.)
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_feedback_structure {
/** @var stdClass */
protected $feedback;
/** @var cm_info */
protected $cm;
/** @var int */
protected $courseid = 0;
/** @var int */
protected $templateid;
/** @var array */
protected $allitems;
/** @var array */
protected $allcourses;
/**
* Constructor
*
* @param stdClass $feedback feedback object, in case of the template
* this is the current feedback the template is accessed from
* @param cm_info $cm course module object corresponding to the $feedback
* @param int $courseid current course (for site feedbacks only)
* @param int $templateid template id if this class represents the template structure
*/
public function __construct($feedback, $cm, $courseid = 0, $templateid = null) {
$this->feedback = $feedback;
$this->cm = $cm;
$this->courseid = ($feedback->course == SITEID) ? $courseid : 0;
$this->templateid = $templateid;
}
/**
* Current feedback
* @return stdClass
*/
public function get_feedback() {
return $this->feedback;
}
/**
* Current course module
* @return stdClass
*/
public function get_cm() {
return $this->cm;
}
/**
* Id of the current course (for site feedbacks only)
* @return stdClass
*/
public function get_courseid() {
return $this->courseid;
}
/**
* Template id
* @return int
*/
public function get_templateid() {
return $this->templateid;
}
/**
* Is this feedback open (check timeopen and timeclose)
* @return bool
*/
public function is_open() {
$checktime = time();
return (!$this->feedback->timeopen || $this->feedback->timeopen <= $checktime) &&
(!$this->feedback->timeclose || $this->feedback->timeclose >= $checktime);
}
/**
* Get all items in this feedback or this template
* @param bool $hasvalueonly only count items with a value.
* @return array of objects from feedback_item with an additional attribute 'itemnr'
*/
public function get_items($hasvalueonly = false) {
global $DB;
if ($this->allitems === null) {
if ($this->templateid) {
$this->allitems = $DB->get_records('feedback_item', ['template' => $this->templateid], 'position');
} else {
$this->allitems = $DB->get_records('feedback_item', ['feedback' => $this->feedback->id], 'position');
}
$idx = 1;
foreach ($this->allitems as $id => $item) {
$this->allitems[$id]->itemnr = $item->hasvalue ? ($idx++) : null;
}
}
if ($hasvalueonly && $this->allitems) {
return array_filter($this->allitems, function($item) {
return $item->hasvalue;
});
}
return $this->allitems;
}
/**
* Is the items list empty?
* @return bool
*/
public function is_empty() {
$items = $this->get_items();
$displayeditems = array_filter($items, function($item) {
return $item->typ !== 'pagebreak';
});
return !$displayeditems;
}
/**
* Is this feedback anonymous?
* @return bool
*/
public function is_anonymous() {
return $this->feedback->anonymous == FEEDBACK_ANONYMOUS_YES;
}
/**
* Returns the formatted text of the page after submit or null if it is not set
*
* @return string|null
*/
public function page_after_submit() {
global $CFG;
require_once($CFG->libdir . '/filelib.php');
$pageaftersubmit = $this->get_feedback()->page_after_submit;
if (empty($pageaftersubmit)) {
return null;
}
$pageaftersubmitformat = $this->get_feedback()->page_after_submitformat;
$context = context_module::instance($this->get_cm()->id);
$output = file_rewrite_pluginfile_urls($pageaftersubmit,
'pluginfile.php', $context->id, 'mod_feedback', 'page_after_submit', 0);
return format_text($output, $pageaftersubmitformat, array('overflowdiv' => true));
}
/**
* Checks if current user is able to view feedback on this course.
*
* @return bool
*/
public function can_view_analysis() {
$context = context_module::instance($this->cm->id);
if (has_capability('mod/feedback:viewreports', $context)) {
return true;
}
if (intval($this->feedback->publish_stats) != 1 ||
!has_capability('mod/feedback:viewanalysepage', $context)) {
return false;
}
if (!isloggedin() || isguestuser()) {
// There is no tracking for the guests, assume that they can view analysis if condition above is satisfied.
return $this->feedback->course == SITEID;
}
return $this->is_already_submitted(true);
}
/**
* check for multiple_submit = false.
* if the feedback is global so the courseid must be given
*
* @param bool $anycourseid if true checks if this feedback was submitted in any course, otherwise checks $this->courseid .
* Applicable to frontpage feedbacks only
* @return bool true if the feedback already is submitted otherwise false
*/
public function is_already_submitted($anycourseid = false) {
global $USER, $DB;
if (!isloggedin() || isguestuser()) {
return false;
}
$params = array('userid' => $USER->id, 'feedback' => $this->feedback->id);
if (!$anycourseid && $this->courseid) {
$params['courseid'] = $this->courseid;
}
return $DB->record_exists('feedback_completed', $params);
}
/**
* Check whether the feedback is mapped to the given courseid.
*/
public function check_course_is_mapped() {
global $DB;
if ($this->feedback->course != SITEID) {
return true;
}
if ($DB->get_records('feedback_sitecourse_map', array('feedbackid' => $this->feedback->id))) {
$params = array('feedbackid' => $this->feedback->id, 'courseid' => $this->courseid);
if (!$DB->get_record('feedback_sitecourse_map', $params)) {
return false;
}
}
// No mapping means any course is mapped.
return true;
}
/**
* If there are any new responses to the anonymous feedback, re-shuffle all
* responses and assign response number to each of them.
*/
public function shuffle_anonym_responses() {
global $DB;
$params = array('feedback' => $this->feedback->id,
'random_response' => 0,
'anonymous_response' => FEEDBACK_ANONYMOUS_YES);
if ($DB->count_records('feedback_completed', $params, 'random_response')) {
// Get all of the anonymous records, go through them and assign a response id.
unset($params['random_response']);
$feedbackcompleteds = $DB->get_records('feedback_completed', $params, 'id');
shuffle($feedbackcompleteds);
$num = 1;
foreach ($feedbackcompleteds as $compl) {
$compl->random_response = $num++;
$DB->update_record('feedback_completed', $compl);
}
}
}
/**
* Counts records from {feedback_completed} table for a given feedback
*
* If $groupid or $this->courseid is set, the records are filtered by the group/course
*
* @param int $groupid
* @return mixed array of found completeds otherwise false
*/
public function count_completed_responses($groupid = 0) {
global $DB;
if (intval($groupid) > 0) {
$query = "SELECT COUNT(DISTINCT fbc.id)
FROM {feedback_completed} fbc, {groups_members} gm
WHERE fbc.feedback = :feedback
AND gm.groupid = :groupid
AND fbc.userid = gm.userid";
} else if ($this->courseid) {
$query = "SELECT COUNT(fbc.id)
FROM {feedback_completed} fbc
WHERE fbc.feedback = :feedback
AND fbc.courseid = :courseid";
} else {
$query = "SELECT COUNT(fbc.id) FROM {feedback_completed} fbc WHERE fbc.feedback = :feedback";
}
$params = ['feedback' => $this->feedback->id, 'groupid' => $groupid, 'courseid' => $this->courseid];
return $DB->get_field_sql($query, $params);
}
/**
* For the frontpage feedback returns the list of courses with at least one completed feedback
*
* @return array id=>name pairs of courses
*/
public function get_completed_courses() {
global $DB;
if ($this->get_feedback()->course != SITEID) {
return [];
}
if ($this->allcourses !== null) {
return $this->allcourses;
}
$courseselect = "SELECT fbc.courseid
FROM {feedback_completed} fbc
WHERE fbc.feedback = :feedbackid";
$ctxselect = context_helper::get_preload_record_columns_sql('ctx');
$sql = 'SELECT c.id, c.shortname, c.fullname, c.idnumber, c.visible, '. $ctxselect. '
FROM {course} c
JOIN {context} ctx ON c.id = ctx.instanceid AND ctx.contextlevel = :contextcourse
WHERE c.id IN ('. $courseselect.') ORDER BY c.sortorder';
$list = $DB->get_records_sql($sql, ['contextcourse' => CONTEXT_COURSE, 'feedbackid' => $this->get_feedback()->id]);
$this->allcourses = array();
foreach ($list as $course) {
context_helper::preload_from_record($course);
if (!$course->visible && !has_capability('moodle/course:viewhiddencourses', context_course::instance($course->id))) {
// Do not return courses that current user can not see.
continue;
}
$label = get_course_display_name_for_list($course);
$this->allcourses[$course->id] = $label;
}
return $this->allcourses;
}
}

View file

@ -77,9 +77,10 @@ class mod_feedback_templates_table extends flexible_table {
foreach ($templates as $template) {
$data = array();
$data[] = format_string($template->name);
$url = new moodle_url($this->baseurl, array('deletetempl' => $template->id));
$url = new moodle_url($this->baseurl, array('deletetempl' => $template->id, 'sesskey' => sesskey()));
$data[] = $OUTPUT->single_button($url, $strdeletefeedback, 'post');
$deleteaction = new confirm_action(get_string('confirmdeletetemplate', 'feedback'));
$data[] = $OUTPUT->action_icon($url, new pix_icon('t/delete', $strdeletefeedback), $deleteaction);
$this->add_data($data);
}
$this->finish_output();

View file

@ -29,527 +29,137 @@ require_once($CFG->libdir . '/completionlib.php');
feedback_init_feedback_session();
$id = required_param('id', PARAM_INT);
$completedid = optional_param('completedid', false, PARAM_INT);
$preservevalues = optional_param('preservevalues', 0, PARAM_INT);
$courseid = optional_param('courseid', false, PARAM_INT);
$gopage = optional_param('gopage', -1, PARAM_INT);
$lastpage = optional_param('lastpage', false, PARAM_INT);
$startitempos = optional_param('startitempos', 0, PARAM_INT);
$lastitempos = optional_param('lastitempos', 0, PARAM_INT);
$anonymous_response = optional_param('anonymous_response', 0, PARAM_INT); //arb
$highlightrequired = false;
if (($formdata = data_submitted()) AND !confirm_sesskey()) {
print_error('invalidsesskey');
}
//if the use hit enter into a textfield so the form should not submit
if (isset($formdata->sesskey) AND
!isset($formdata->savevalues) AND
!isset($formdata->gonextpage) AND
!isset($formdata->gopreviouspage)) {
$gopage = $formdata->lastpage;
}
if (isset($formdata->savevalues)) {
$savevalues = true;
} else {
$savevalues = false;
}
if ($gopage < 0 AND !$savevalues) {
if (isset($formdata->gonextpage)) {
$gopage = $lastpage + 1;
$gonextpage = true;
$gopreviouspage = false;
} else if (isset($formdata->gopreviouspage)) {
$gopage = $lastpage - 1;
$gonextpage = false;
$gopreviouspage = true;
} else {
print_error('missingparameter');
}
} else {
$gonextpage = $gopreviouspage = false;
}
$courseid = optional_param('courseid', null, PARAM_INT);
$gopage = optional_param('gopage', 0, PARAM_INT);
list($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
$feedback = $DB->get_record("feedback", array("id" => $cm->instance), '*', MUST_EXIST);
$context = context_module::instance($cm->id);
$feedback_complete_cap = false;
if (has_capability('mod/feedback:complete', $context)) {
$feedback_complete_cap = true;
}
if (!empty($CFG->feedback_allowfullanonymous)
AND $course->id == SITEID
AND $feedback->anonymous == FEEDBACK_ANONYMOUS_YES
AND (!isloggedin() OR isguestuser())) {
// Guests are allowed to complete fully anonymous feedback without having 'mod/feedback:complete' capability.
$feedback_complete_cap = true;
}
//check whether the feedback is located and! started from the mainsite
if ($course->id == SITEID AND !$courseid) {
$courseid = SITEID;
}
//check whether the feedback is mapped to the given courseid
if ($course->id == SITEID AND !has_capability('mod/feedback:edititems', $context)) {
if ($DB->get_records('feedback_sitecourse_map', array('feedbackid'=>$feedback->id))) {
$params = array('feedbackid'=>$feedback->id, 'courseid'=>$courseid);
if (!$DB->get_record('feedback_sitecourse_map', $params)) {
print_error('notavailable', 'feedback');
}
}
}
$urlparams = array('id' => $cm->id, 'gopage' => $gopage, 'courseid' => $courseid);
$PAGE->set_url('/mod/feedback/complete.php', $urlparams);
require_course_login($course, true, $cm);
$PAGE->set_activity_record($feedback);
//check whether the given courseid exists
if ($courseid AND $courseid != SITEID) {
if ($course2 = $DB->get_record('course', array('id'=>$courseid))) {
require_course_login($course2); //this overwrites the object $course :-(
$course = $DB->get_record("course", array("id"=>$cm->course)); // the workaround
} else {
print_error('invalidcourseid');
}
$context = context_module::instance($cm->id);
$feedbackcompletion = new mod_feedback_completion($feedback, $cm, $courseid);
$courseid = $feedbackcompletion->get_courseid();
// Check whether the feedback is mapped to the given courseid.
if (!has_capability('mod/feedback:edititems', $context) &&
!$feedbackcompletion->check_course_is_mapped()) {
echo $OUTPUT->header();
echo $OUTPUT->notification(get_string('cannotaccess', 'mod_feedback'));
echo $OUTPUT->footer();
exit;
}
if (!$feedback_complete_cap) {
//check whether the given courseid exists
if ($courseid AND $courseid != SITEID) {
require_course_login(get_course($courseid)); // This overwrites the object $COURSE .
}
if (!$feedbackcompletion->can_complete()) {
print_error('error');
}
// Mark activity viewed for completion-tracking
$completion = new completion_info($course);
if (isloggedin() && !isguestuser()) {
$completion->set_module_viewed($cm);
}
/// Print the page header
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
if ($course->id == SITEID) {
$PAGE->set_cm($cm, $course); // set's up global $COURSE
$PAGE->set_pagelayout('incourse');
}
$PAGE->navbar->add(get_string('feedback:complete', 'feedback'));
$urlparams = array('id'=>$cm->id, 'gopage'=>$gopage, 'courseid'=>$course->id);
$PAGE->set_url('/mod/feedback/complete.php', $urlparams);
$PAGE->set_heading($course->fullname);
$PAGE->set_title($feedback->name);
echo $OUTPUT->header();
$PAGE->set_pagelayout('incourse');
//check, if the feedback is open (timeopen, timeclose)
$checktime = time();
$feedback_is_closed = ($feedback->timeopen > $checktime) ||
($feedback->timeclose < $checktime &&
$feedback->timeclose > 0);
if ($feedback_is_closed) {
// Check if the feedback is open (timeopen, timeclose).
if (!$feedbackcompletion->is_open()) {
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($feedback->name));
echo $OUTPUT->box_start('generalbox boxaligncenter');
echo $OUTPUT->notification(get_string('feedback_is_not_open', 'feedback'));
echo $OUTPUT->continue_button($CFG->wwwroot.'/course/view.php?id='.$course->id);
echo $OUTPUT->continue_button(course_get_url($courseid ?: $feedback->course));
echo $OUTPUT->box_end();
echo $OUTPUT->footer();
exit;
}
//additional check for multiple-submit (prevent browsers back-button).
//the main-check is in view.php
$feedback_can_submit = true;
if ($feedback->multiple_submit == 0 ) {
if (feedback_is_already_submitted($feedback->id, $courseid)) {
$feedback_can_submit = false;
}
// Mark activity viewed for completion-tracking.
$completion = new completion_info($course);
if (isloggedin() && !isguestuser()) {
$completion->set_module_viewed($cm);
}
if ($feedback_can_submit) {
//preserving the items
if ($preservevalues == 1) {
// Check if user is prevented from re-submission.
$cansubmit = $feedbackcompletion->can_submit();
// Initialise the form processing feedback completion.
if (!$feedbackcompletion->is_empty() && $cansubmit) {
$form = new mod_feedback_complete_form(mod_feedback_complete_form::MODE_COMPLETE,
$feedbackcompletion, 'feedback_complete_form', array('gopage' => $gopage));
if ($form->is_cancelled()) {
// Form was cancelled - return to the course page.
redirect(course_get_url($courseid ?: $course));
} else if ($form->is_submitted() &&
($form->is_validated() || optional_param('gopreviouspage', null, PARAM_RAW))) {
// Form was submitted (skip validation for "Previous page" button).
$data = $form->get_submitted_data();
if (!isset($SESSION->feedback->is_started) OR !$SESSION->feedback->is_started == true) {
print_error('error', '', $CFG->wwwroot.'/course/view.php?id='.$course->id);
}
// Check if all required items have a value.
if (feedback_check_values($startitempos, $lastitempos)) {
$userid = $USER->id; //arb
if (isloggedin() && !isguestuser()) {
$completedid = feedback_save_values($USER->id, true);
$feedbackcompletion->save_response_tmp($data);
if (!empty($data->savevalues) || !empty($data->gonextpage)) {
if (($nextpage = $feedbackcompletion->get_next_page($gopage)) !== null) {
redirect(new moodle_url($PAGE->url, array('gopage' => $nextpage)));
} else {
$completedid = feedback_save_guest_values(sesskey());
}
if ($completedid) {
if (!$gonextpage AND !$gopreviouspage) {
$preservevalues = false;// It can be stored.
}
} else {
$savereturn = 'failed';
if (isset($lastpage)) {
$gopage = $lastpage;
} else {
print_error('missingparameter');
$feedbackcompletion->save_response();
if (!$feedback->page_after_submit) {
\core\notification::success(get_string('entries_saved', 'feedback'));
}
}
} else {
$savereturn = 'missing';
$highlightrequired = true;
if (isset($lastpage)) {
$gopage = $lastpage;
} else {
print_error('missingparameter');
}
} else if (!empty($data->gopreviouspage)) {
$prevpage = $feedbackcompletion->get_previous_page($gopage);
redirect(new moodle_url($PAGE->url, array('gopage' => intval($prevpage))));
}
}
}
//saving the items
if ($savevalues AND !$preservevalues) {
//exists there any pagebreak, so there are values in the feedback_valuetmp
$userid = $USER->id; //arb
// Print the page header.
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
if ($feedback->anonymous == FEEDBACK_ANONYMOUS_NO) {
$feedbackcompleted = feedback_get_current_completed($feedback->id, false, $courseid);
} else {
$feedbackcompleted = false;
}
$params = array('id' => $completedid);
$feedbackcompletedtmp = $DB->get_record('feedback_completedtmp', $params);
//fake saving for switchrole
$is_switchrole = feedback_check_is_switchrole();
if ($is_switchrole) {
$savereturn = 'saved';
feedback_delete_completedtmp($completedid);
} else {
$new_completed_id = feedback_save_tmp_values($feedbackcompletedtmp,
$feedbackcompleted,
$userid);
if ($new_completed_id) {
$savereturn = 'saved';
if ($feedback->anonymous == FEEDBACK_ANONYMOUS_NO) {
feedback_send_email($cm, $feedback, $course, $userid);
} else {
feedback_send_email_anonym($cm, $feedback, $course, $userid);
}
if (isloggedin() && !isguestuser()) {
// Tracking the submit.
$tracking = new stdClass();
$tracking->userid = $USER->id;
$tracking->feedback = $feedback->id;
$tracking->completed = $new_completed_id;
$DB->insert_record('feedback_tracking', $tracking);
}
unset($SESSION->feedback->is_started);
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($feedback->name));
// Update completion state
$completion = new completion_info($course);
if (isloggedin() && !isguestuser() && $completion->is_enabled($cm) && $feedback->completionsubmit) {
$completion->update_state($cm, COMPLETION_COMPLETE);
}
} else {
$savereturn = 'failed';
}
}
}
if ($allbreaks = feedback_get_all_break_positions($feedback->id)) {
if ($gopage <= 0) {
$startposition = 0;
} else {
if (!isset($allbreaks[$gopage - 1])) {
$gopage = count($allbreaks);
}
$startposition = $allbreaks[$gopage - 1];
}
$ispagebreak = true;
} else {
$startposition = 0;
$newpage = 0;
$ispagebreak = false;
}
//get the feedbackitems after the last shown pagebreak
$select = 'feedback = ? AND position > ?';
$params = array($feedback->id, $startposition);
$feedbackitems = $DB->get_records_select('feedback_item', $select, $params, 'position');
//get the first pagebreak
$params = array('feedback' => $feedback->id, 'typ' => 'pagebreak');
if ($pagebreaks = $DB->get_records('feedback_item', $params, 'position')) {
$pagebreaks = array_values($pagebreaks);
$firstpagebreak = $pagebreaks[0];
} else {
$firstpagebreak = false;
}
$maxitemcount = $DB->count_records('feedback_item', array('feedback'=>$feedback->id));
//get the values of completeds before done. Anonymous user can not get these values.
if ((!isset($SESSION->feedback->is_started)) AND
(!isset($savereturn)) AND
($feedback->anonymous == FEEDBACK_ANONYMOUS_NO)) {
$feedbackcompletedtmp = feedback_get_current_completed($feedback->id, true, $courseid);
if (!$feedbackcompletedtmp) {
$feedbackcompleted = feedback_get_current_completed($feedback->id, false, $courseid);
if ($feedbackcompleted) {
//copy the values to feedback_valuetmp create a completedtmp
$feedbackcompletedtmp = feedback_set_tmp_values($feedbackcompleted);
}
}
} else if (isloggedin() && !isguestuser()) {
$feedbackcompletedtmp = feedback_get_current_completed($feedback->id, true, $courseid);
} else {
$feedbackcompletedtmp = feedback_get_current_completed($feedback->id, true, $courseid, sesskey());
}
/// Print the main part of the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
$analysisurl = new moodle_url('/mod/feedback/analysis.php', array('id'=>$id));
if ($courseid > 0) {
$analysisurl->param('courseid', $courseid);
}
echo $OUTPUT->heading(format_string($feedback->name));
if (isset($savereturn) && $savereturn == 'saved') {
if ($feedbackcompletion->is_empty()) {
\core\notification::error(get_string('no_items_available_yet', 'feedback'));
} else if ($cansubmit) {
if (!empty($data->savevalues) || !empty($data->gonextpage)) {
// Display information after the submit.
if ($feedback->page_after_submit) {
require_once($CFG->libdir . '/filelib.php');
$page_after_submit_output = file_rewrite_pluginfile_urls($feedback->page_after_submit,
'pluginfile.php',
$context->id,
'mod_feedback',
'page_after_submit',
0);
echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide');
echo format_text($page_after_submit_output,
$feedback->page_after_submitformat,
array('overflowdiv' => true));
echo $OUTPUT->box_end();
} else {
echo '<p align="center">';
echo '<b><font color="green">';
echo get_string('entries_saved', 'feedback');
echo '</font></b>';
echo '</p>';
echo $OUTPUT->box($feedbackcompletion->page_after_submit(),
'generalbox boxaligncenter');
}
if (feedback_can_view_analysis($feedback, $context, $courseid)) {
echo '<p align="center"><a href="'.$analysisurl->out().'">';
echo get_string('completed_feedbacks', 'feedback').'</a>';
if ($feedbackcompletion->can_view_analysis()) {
echo '<p align="center">';
$analysisurl = new moodle_url('/mod/feedback/analysis.php', array('id' => $cm->id, 'courseid' => $courseid));
echo html_writer::link($analysisurl, get_string('completed_feedbacks', 'feedback'));
echo '</p>';
}
if ($feedback->site_after_submit) {
$url = feedback_encode_target_url($feedback->site_after_submit);
} else {
if ($courseid) {
if ($courseid == SITEID) {
$url = $CFG->wwwroot;
} else {
$url = $CFG->wwwroot.'/course/view.php?id='.$courseid;
}
} else {
if ($course->id == SITEID) {
$url = $CFG->wwwroot;
} else {
$url = $CFG->wwwroot.'/course/view.php?id='.$course->id;
}
}
$url = course_get_url($courseid ?: $course->id);
}
echo $OUTPUT->continue_button($url);
} else {
if (isset($savereturn) && $savereturn == 'failed') {
echo $OUTPUT->box_start('mform');
echo '<span class="error">'.get_string('saving_failed', 'feedback').'</span>';
echo $OUTPUT->box_end();
}
if (isset($savereturn) && $savereturn == 'missing') {
echo $OUTPUT->box_start('mform');
echo '<span class="error">'.get_string('saving_failed_because_missing_or_false_values', 'feedback').'</span>';
echo $OUTPUT->box_end();
}
//print the items
if (is_array($feedbackitems)) {
echo $OUTPUT->box_start('feedback_form');
echo '<form action="complete.php" class="feedback_complete" method="post">';
echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
$anonymousmodeinfo = '';
switch ($feedback->anonymous) {
case FEEDBACK_ANONYMOUS_YES:
echo '<input type="hidden" name="anonymous" value="1" />';
$inputvalue = 'value="'.FEEDBACK_ANONYMOUS_YES.'"';
echo '<input type="hidden" name="anonymous_response" '.$inputvalue.' />';
$anonymousmodeinfo = get_string('anonymous', 'feedback');
break;
case FEEDBACK_ANONYMOUS_NO:
echo '<input type="hidden" name="anonymous" value="0" />';
$inputvalue = 'value="'.FEEDBACK_ANONYMOUS_NO.'"';
echo '<input type="hidden" name="anonymous_response" '.$inputvalue.' />';
$anonymousmodeinfo = get_string('non_anonymous', 'feedback');
break;
}
if (isloggedin() && !isguestuser()) {
echo $OUTPUT->box(get_string('mode', 'feedback') . ': ' . $anonymousmodeinfo, 'feedback_anonymousinfo');
}
//check, if there exists required-elements
$params = array('feedback' => $feedback->id, 'required' => 1);
$countreq = $DB->count_records('feedback_item', $params);
if ($countreq > 0) {
echo '<span class="fdescription required">';
echo get_string('somefieldsrequired', 'form', '<img alt="'.get_string('requiredelement', 'form').
'" src="'.$OUTPUT->pix_url('req') .'" class="req" />');
echo '</span>';
}
echo $OUTPUT->box_start('feedback_items');
unset($startitem);
$select = 'feedback = ? AND hasvalue = 1 AND position < ?';
$params = array($feedback->id, $startposition);
$itemnr = $DB->count_records_select('feedback_item', $select, $params);
$lastbreakposition = 0;
$align = right_to_left() ? 'right' : 'left';
foreach ($feedbackitems as $feedbackitem) {
if (!isset($startitem)) {
//avoid showing double pagebreaks
if ($feedbackitem->typ == 'pagebreak') {
continue;
}
$startitem = $feedbackitem;
}
if ($feedbackitem->dependitem > 0) {
//chech if the conditions are ok
$fb_compare_value = feedback_compare_item_value($feedbackcompletedtmp->id,
$feedbackitem->dependitem,
$feedbackitem->dependvalue,
true);
if (!isset($feedbackcompletedtmp->id) OR !$fb_compare_value) {
$lastitem = $feedbackitem;
$lastbreakposition = $feedbackitem->position;
continue;
}
}
if ($feedbackitem->dependitem > 0) {
$dependstyle = ' feedback_complete_depend';
} else {
$dependstyle = '';
}
echo $OUTPUT->box_start('feedback_item_box_'.$align.$dependstyle);
$value = '';
//get the value
$frmvaluename = $feedbackitem->typ . '_'. $feedbackitem->id;
if (isset($savereturn)) {
$value = isset($formdata->{$frmvaluename}) ? $formdata->{$frmvaluename} : null;
$value = feedback_clean_input_value($feedbackitem, $value);
} else {
if (isset($feedbackcompletedtmp->id)) {
$value = feedback_get_item_value($feedbackcompletedtmp->id,
$feedbackitem->id,
true);
}
}
if ($feedbackitem->hasvalue == 1 AND $feedback->autonumbering) {
$itemnr++;
echo $OUTPUT->box_start('feedback_item_number_'.$align);
echo $itemnr;
echo $OUTPUT->box_end();
}
if ($feedbackitem->typ != 'pagebreak') {
echo $OUTPUT->box_start('box generalbox boxalign_'.$align);
feedback_print_item_complete($feedbackitem, $value, $highlightrequired);
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
$lastbreakposition = $feedbackitem->position; //last item-pos (item or pagebreak)
if ($feedbackitem->typ == 'pagebreak') {
break;
} else {
$lastitem = $feedbackitem;
}
}
echo $OUTPUT->box_end();
echo '<input type="hidden" name="id" value="'.$id.'" />';
echo '<input type="hidden" name="feedbackid" value="'.$feedback->id.'" />';
echo '<input type="hidden" name="lastpage" value="'.$gopage.'" />';
if (isset($feedbackcompletedtmp->id)) {
$inputvalue = 'value="'.$feedbackcompletedtmp->id.'"';
} else {
$inputvalue = 'value=""';
}
echo '<input type="hidden" name="completedid" '.$inputvalue.' />';
echo '<input type="hidden" name="courseid" value="'. $courseid . '" />';
echo '<input type="hidden" name="preservevalues" value="1" />';
if (isset($startitem)) {
echo '<input type="hidden" name="startitempos" value="'.$startitem->position.'" />';
echo '<input type="hidden" name="lastitempos" value="'.$lastitem->position.'" />';
}
if ( $ispagebreak AND $lastbreakposition > $firstpagebreak->position) {
$inputvalue = 'value="'.get_string('previous_page', 'feedback').'"';
echo '<input name="gopreviouspage" type="submit" '.$inputvalue.' />';
}
if ($lastbreakposition < $maxitemcount) {
$inputvalue = 'value="'.get_string('next_page', 'feedback').'"';
echo '<input name="gonextpage" type="submit" '.$inputvalue.' />';
}
if ($lastbreakposition >= $maxitemcount) { //last page
$inputvalue = 'value="'.get_string('save_entries', 'feedback').'"';
echo '<input name="savevalues" type="submit" '.$inputvalue.' />';
}
echo '</form>';
echo $OUTPUT->box_end();
echo $OUTPUT->box_start('feedback_complete_cancel');
if ($courseid) {
$action = 'action="'.$CFG->wwwroot.'/course/view.php?id='.$courseid.'"';
} else {
if ($course->id == SITEID) {
$action = 'action="'.$CFG->wwwroot.'"';
} else {
$action = 'action="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'"';
}
}
echo '<form '.$action.' method="post" onsubmit=" ">';
echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
echo '<input type="hidden" name="courseid" value="'. $courseid . '" />';
echo '<button type="submit">'.get_string('cancel').'</button>';
echo '</form>';
echo $OUTPUT->box_end();
$SESSION->feedback->is_started = true;
}
// Print the items.
$SESSION->feedback->is_started = true;
$form->display();
}
} else {
echo $OUTPUT->heading(format_string($feedback->name));
echo $OUTPUT->box_start('generalbox boxaligncenter');
echo $OUTPUT->notification(get_string('this_feedback_is_already_submitted', 'feedback'));
echo $OUTPUT->continue_button($CFG->wwwroot.'/course/view.php?id='.$course->id);
echo $OUTPUT->continue_button(course_get_url($courseid ?: $course->id));
echo $OUTPUT->box_end();
}
/// Finish the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
echo $OUTPUT->footer();

View file

@ -17,7 +17,4 @@
function xmldb_feedback_install() {
global $DB;
/// Disable this module by default (because it's not technically part of Moodle 2.0)
$DB->set_field('modules', 'visible', 0, array('name'=>'feedback'));
}

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/feedback/db" VERSION="20120122" COMMENT="XMLDB file for Moodle mod/feedback"
<XMLDB PATH="mod/feedback/db" VERSION="20160326" COMMENT="XMLDB file for Moodle mod/feedback"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@ -75,6 +75,7 @@
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="random_response" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="anonymous_response" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for feedback_completed"/>
@ -93,6 +94,7 @@
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="random_response" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="anonymous_response" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for feedback_completedtmp"/>
@ -136,23 +138,6 @@
<INDEX NAME="course_id" UNIQUE="false" FIELDS="course_id"/>
</INDEXES>
</TABLE>
<TABLE NAME="feedback_tracking" COMMENT="feedback trackingdata">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="feedback" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="completed" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="tmp_completed" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for feedback_tracking"/>
<KEY NAME="feedback" TYPE="foreign" FIELDS="feedback" REFTABLE="feedback" REFFIELDS="id"/>
<KEY NAME="completed" TYPE="foreign" FIELDS="completed" REFTABLE="feedback_completed" REFFIELDS="id"/>
</KEYS>
<INDEXES>
<INDEX NAME="userid" UNIQUE="false" FIELDS="userid"/>
</INDEXES>
</TABLE>
<TABLE NAME="feedback_sitecourse_map" COMMENT="feedback sitecourse map">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
@ -160,7 +145,7 @@
<FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for feedback_tracking"/>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for feedback_sitecourse_map"/>
<KEY NAME="feedbackid" TYPE="foreign" FIELDS="feedbackid" REFTABLE="feedback" REFFIELDS="id"/>
</KEYS>
<INDEXES>
@ -168,4 +153,4 @@
</INDEXES>
</TABLE>
</TABLES>
</XMLDB>
</XMLDB>

View file

@ -38,6 +38,9 @@ defined('MOODLE_INTERNAL') || die();
function xmldb_feedback_upgrade($oldversion) {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/feedback/db/upgradelib.php');
$dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
// Moodle v2.8.0 release upgrade line.
// Put any upgrade step following this.
@ -72,5 +75,41 @@ function xmldb_feedback_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2016040100, 'feedback');
}
if ($oldversion < 2016040300) {
// Define field courseid to be added to feedback_completed.
$table = new xmldb_table('feedback_completed');
$field = new xmldb_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'anonymous_response');
// Conditionally launch add field courseid.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Define field courseid to be added to feedback_completedtmp.
$table = new xmldb_table('feedback_completedtmp');
$field = new xmldb_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'anonymous_response');
// Conditionally launch add field courseid.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Define table feedback_tracking to be dropped.
$table = new xmldb_table('feedback_tracking');
// Conditionally launch drop table for feedback_tracking.
if ($dbman->table_exists($table)) {
$dbman->drop_table($table);
}
// Run upgrade script to fill the new field courseid with the data from feedback_value* tables.
mod_feedback_upgrade_courseid(false);
mod_feedback_upgrade_courseid(true);
// Feedback savepoint reached.
upgrade_mod_savepoint(true, 2016040300, 'feedback');
}
return true;
}

View file

@ -0,0 +1,64 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Upgrade helper functions
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Fill new field courseid in tables feedback_completed or feedback_completedtmp
*
* @param bool $tmp use for temporary table
*/
function mod_feedback_upgrade_courseid($tmp = false) {
global $DB;
$suffix = $tmp ? 'tmp' : '';
// Part 1. Ensure that each completed record has associated values with only one courseid.
$sql = "SELECT c.id
FROM {feedback_completed$suffix} c, {feedback_value$suffix} v
WHERE c.id = v.completed
GROUP by c.id
having count(DISTINCT v.course_id) > 1";
$problems = $DB->get_fieldset_sql($sql);
foreach ($problems as $problem) {
$courses = $DB->get_fieldset_sql("SELECT DISTINCT course_id "
. "FROM {feedback_value$suffix} WHERE completed = ?", array($problem));
$firstcourse = array_shift($courses);
$record = $DB->get_record('feedback_completed'.$suffix, array('id' => $problem));
unset($record->id);
$DB->update_record('feedback_completed'.$suffix, ['id' => $problem, 'courseid' => $firstcourse]);
foreach ($courses as $courseid) {
$record->courseid = $courseid;
$completedid = $DB->insert_record('feedback_completed'.$suffix, $record);
$DB->execute("UPDATE {feedback_value$suffix} SET completed = ? WHERE completed = ? AND course_id = ?",
array($completedid, $problem, $courseid));
}
}
// Part 2. Update courseid in the completed table.
$sql = "UPDATE {feedback_completed$suffix} "
. "SET courseid = (SELECT COALESCE(MIN(v.course_id), 0) "
. "FROM {feedback_value$suffix} v "
. "WHERE v.completed = {feedback_completed$suffix}.id)";
$DB->execute($sql);
}

View file

@ -1,91 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* deletes an item 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('delete_item_form.php');
$id = required_param('id', PARAM_INT);
$deleteitem = required_param('deleteitem', PARAM_INT);
$PAGE->set_url('/mod/feedback/delete_item.php', array('id'=>$id, 'deleteitem'=>$deleteitem));
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);
require_capability('mod/feedback:edititems', $context);
$mform = new mod_feedback_delete_item_form();
$newformdata = array('id'=>$id,
'deleteitem'=>$deleteitem,
'confirmdelete'=>'1');
$mform->set_data($newformdata);
$formdata = $mform->get_data();
if ($mform->is_cancelled()) {
redirect('edit.php?id='.$id);
}
if (isset($formdata->confirmdelete) AND $formdata->confirmdelete == 1) {
feedback_delete_item($formdata->deleteitem);
redirect('edit.php?id=' . $id);
}
/// Print the page header
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
$PAGE->navbar->add(get_string('delete_item', 'feedback'));
$PAGE->set_heading($course->fullname);
$PAGE->set_title($feedback->name);
echo $OUTPUT->header();
/// Print the main part of the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
echo $OUTPUT->heading(format_string($feedback->name));
echo $OUTPUT->box_start('generalbox errorboxcontent boxaligncenter boxwidthnormal');
echo html_writer::tag('p', get_string('confirmdeleteitem', 'feedback'), array('class' => 'bold'));
print_string('relateditemsdeleted', 'feedback');
$mform->display();
echo $OUTPUT->box_end();
echo $OUTPUT->footer();

View file

@ -1,50 +0,0 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* prints the form to confirm delete a completed
*
* @author Andreas Grabs
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package mod_feedback
*/
//It must be included from a Moodle page
if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.');
}
require_once($CFG->libdir.'/formslib.php');
class mod_feedback_delete_item_form extends moodleform {
public function definition() {
$mform =& $this->_form;
// hidden elements
$mform->addElement('hidden', 'id');
$mform->setType('id', PARAM_INT);
$mform->addElement('hidden', 'deleteitem');
$mform->setType('deleteitem', PARAM_INT);
$mform->addElement('hidden', 'confirmdelete');
$mform->setType('confirmdelete', PARAM_INT);
//-------------------------------------------------------------------------------
// buttons
$this->add_action_buttons(true, get_string('yes'));
}
}

View file

@ -43,7 +43,8 @@ $feedback = $PAGE->activityrecord;
$systemcontext = context_system::instance();
// Process template deletion.
if ($deletetempl && optional_param('confirm', 0, PARAM_BOOL) && confirm_sesskey()) {
if ($deletetempl) {
require_sesskey();
$template = $DB->get_record('feedback_template', array('id' => $deletetempl), '*', MUST_EXIST);
if ($template->ispublic) {
@ -69,36 +70,29 @@ echo $OUTPUT->heading(format_string($feedback->name));
/// print the tabs
require('tabs.php');
/// Print the main part of the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Print the main part of the page.
echo $OUTPUT->heading($strdeletefeedback, 3);
if ($deletetempl) {
$continueurl = new moodle_url($baseurl, array('deletetempl' => $deletetempl, 'confirm' => 1, 'sesskey' => sesskey()));
echo $OUTPUT->confirm(get_string('confirmdeletetemplate', 'feedback'), $continueurl, $baseurl);
} else {
// First we get the course templates.
$templates = feedback_get_template_list($course, 'own');
echo $OUTPUT->box_start('coursetemplates');
echo $OUTPUT->heading(get_string('course'), 4);
$tablecourse = new mod_feedback_templates_table('feedback_template_course_table', $baseurl);
$tablecourse->display($templates);
echo $OUTPUT->box_end();
// Now we get the public templates if it is permitted.
if (has_capability('mod/feedback:createpublictemplate', $systemcontext) AND
has_capability('mod/feedback:deletetemplate', $systemcontext)) {
$templates = feedback_get_template_list($course, 'public');
echo $OUTPUT->box_start('publictemplates');
echo $OUTPUT->heading(get_string('public', 'feedback'), 4);
$tablepublic = new mod_feedback_templates_table('feedback_template_public_table', $baseurl);
$tablepublic->display($templates);
echo $OUTPUT->box_end();
}
$url = new moodle_url('/mod/feedback/edit.php', array('id' => $id, 'do_show' => 'templates'));
echo $OUTPUT->single_button($url, get_string('back'), 'post');
// First we get the course templates.
$templates = feedback_get_template_list($course, 'own');
echo $OUTPUT->box_start('coursetemplates');
echo $OUTPUT->heading(get_string('course'), 4);
$tablecourse = new mod_feedback_templates_table('feedback_template_course_table', $baseurl);
$tablecourse->display($templates);
echo $OUTPUT->box_end();
// Now we get the public templates if it is permitted.
if (has_capability('mod/feedback:createpublictemplate', $systemcontext) AND
has_capability('mod/feedback:deletetemplate', $systemcontext)) {
$templates = feedback_get_template_list($course, 'public');
echo $OUTPUT->box_start('publictemplates');
echo $OUTPUT->heading(get_string('public', 'feedback'), 4);
$tablepublic = new mod_feedback_templates_table('feedback_template_public_table', $baseurl);
$tablepublic->display($templates);
echo $OUTPUT->box_end();
}
$url = new moodle_url('/mod/feedback/edit.php', array('id' => $id, 'do_show' => 'templates'));
echo $OUTPUT->single_button($url, get_string('back'), 'post');
echo $OUTPUT->footer();

View file

@ -35,63 +35,37 @@ if (($formdata = data_submitted()) AND !confirm_sesskey()) {
}
$do_show = optional_param('do_show', 'edit', PARAM_ALPHA);
$moveupitem = optional_param('moveupitem', false, PARAM_INT);
$movedownitem = optional_param('movedownitem', false, PARAM_INT);
$moveitem = optional_param('moveitem', false, PARAM_INT);
$movehere = optional_param('movehere', false, PARAM_INT);
$switchitemrequired = optional_param('switchitemrequired', false, PARAM_INT);
$deleteitem = optional_param('deleteitem', false, PARAM_INT);
$current_tab = $do_show;
$url = new moodle_url('/mod/feedback/edit.php', array('id'=>$id, 'do_show'=>$do_show));
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');
}
list($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
$context = context_module::instance($cm->id);
require_login($course, true, $cm);
require_login($course, false, $cm);
require_capability('mod/feedback:edititems', $context);
//Move up/down items
if ($moveupitem) {
$item = $DB->get_record('feedback_item', array('id'=>$moveupitem));
feedback_moveup_item($item);
}
if ($movedownitem) {
$item = $DB->get_record('feedback_item', array('id'=>$movedownitem));
feedback_movedown_item($item);
}
//Moving of items
if ($movehere && isset($SESSION->feedback->moving->movingitem)) {
$item = $DB->get_record('feedback_item', array('id'=>$SESSION->feedback->moving->movingitem));
feedback_move_item($item, intval($movehere));
$moveitem = false;
}
if ($moveitem) {
$item = $DB->get_record('feedback_item', array('id'=>$moveitem));
$SESSION->feedback->moving->shouldmoving = 1;
$SESSION->feedback->moving->movingitem = $moveitem;
} else {
unset($SESSION->feedback->moving);
}
$feedback = $PAGE->activityrecord;
$feedbackstructure = new mod_feedback_structure($feedback, $cm);
if ($switchitemrequired) {
$item = $DB->get_record('feedback_item', array('id'=>$switchitemrequired));
@feedback_switch_item_required($item);
redirect($url->out(false));
exit;
require_sesskey();
$items = $feedbackstructure->get_items();
if (isset($items[$switchitemrequired])) {
feedback_switch_item_required($items[$switchitemrequired]);
}
redirect($url);
}
if ($deleteitem) {
require_sesskey();
$items = $feedbackstructure->get_items();
if (isset($items[$deleteitem])) {
feedback_delete_item($deleteitem);
}
redirect($url);
}
// Process the create template form.
@ -156,15 +130,10 @@ echo $OUTPUT->heading(format_string($feedback->name));
/// print the tabs
require('tabs.php');
/// Print the main part of the page.
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Print the main part of the page.
///////////////////////////////////////////////////////////////////////////
///Print the template-section.
///////////////////////////////////////////////////////////////////////////
if ($do_show == 'templates') {
// Print the template-section.
$use_template_form->display();
if ($cancreatetemplates) {
@ -187,218 +156,22 @@ if ($do_show == 'templates') {
</p>';
}
}
///////////////////////////////////////////////////////////////////////////
///Print the Item-Edit-section.
///////////////////////////////////////////////////////////////////////////
if ($do_show == 'edit') {
$select = new single_select(new moodle_url('/mod/feedback/edit_item.php', array('cmid' => $id, 'position' => $lastposition)),
if ($do_show == 'edit') {
// Print the Item-Edit-section.
$select = new single_select(new moodle_url('/mod/feedback/edit_item.php',
array('cmid' => $id, 'position' => $lastposition, 'sesskey' => sesskey())),
'typ', feedback_load_feedback_items_options());
$select->label = get_string('add_item', 'mod_feedback');
echo $OUTPUT->render($select);
if (is_array($feedbackitems)) {
$itemnr = 0;
$align = right_to_left() ? 'right' : 'left';
$helpbutton = $OUTPUT->help_icon('preview', 'feedback');
echo $OUTPUT->heading(get_string('preview', 'feedback').$helpbutton, 3);
if (isset($SESSION->feedback->moving) AND $SESSION->feedback->moving->shouldmoving == 1) {
$anker = '<a href="edit.php?id='.$id.'">';
$anker .= get_string('cancel_moving', 'feedback');
$anker .= '</a>';
echo $OUTPUT->heading($anker);
}
//Check, if there exists required-elements.
$params = array('feedback' => $feedback->id, 'required' => 1);
$countreq = $DB->count_records('feedback_item', $params);
if ($countreq > 0) {
echo '<div class="fdescription required">';
echo get_string('somefieldsrequired', 'form', '<img alt="'.get_string('requiredelement', 'form').
'" src="'.$OUTPUT->pix_url('req') .'" class="req" />');
echo '</div>';
}
//Use list instead a table
echo $OUTPUT->box_start('feedback_items');
if (isset($SESSION->feedback->moving) AND $SESSION->feedback->moving->shouldmoving == 1) {
$moveposition = 1;
$movehereurl = new moodle_url($url, array('movehere'=>$moveposition));
//Only shown if shouldmoving = 1
echo $OUTPUT->box_start('feedback_item_box_'.$align.' clipboard');
$buttonlink = $movehereurl->out();
$strbutton = get_string('move_here', 'feedback');
$src = $OUTPUT->pix_url('movehere');
echo '<a title="'.$strbutton.'" href="'.$buttonlink.'">
<img class="movetarget" alt="'.$strbutton.'" src="'.$src.'" />
</a>';
echo $OUTPUT->box_end();
}
//Print the inserted items
$itempos = 0;
echo '<div id="feedback_dragarea">'; //The container for the dragging area
echo '<ul id="feedback_draglist">'; //The list what includes the draggable items
foreach ($feedbackitems as $feedbackitem) {
$itempos++;
//Hiding the item to move
if (isset($SESSION->feedback->moving)) {
if ($SESSION->feedback->moving->movingitem == $feedbackitem->id) {
continue;
}
}
//Here come the draggable items, each one in a single li-element.
echo '<li class="feedback_itemlist generalbox" id="feedback_item_'.$feedbackitem->id.'">';
echo '<span class="spinnertest"> </span>';
if ($feedbackitem->dependitem > 0) {
$dependstyle = ' feedback_depend';
} else {
$dependstyle = '';
}
echo $OUTPUT->box_start('feedback_item_box_'.$align.$dependstyle,
'feedback_item_box_'.$feedbackitem->id);
//Items without value only are labels
if ($feedbackitem->hasvalue == 1 AND $feedback->autonumbering) {
$itemnr++;
echo $OUTPUT->box_start('feedback_item_number_'.$align);
echo $itemnr;
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_start('box boxalign_'.$align);
echo $OUTPUT->box_start('feedback_item_commands_'.$align);
echo '<span class="feedback_item_commands position">';
echo '('.get_string('position', 'feedback').':'.$itempos .')';
echo '</span>';
//Print the moveup-button
if ($feedbackitem->position > 1) {
echo '<span class="feedback_item_command_moveup">';
$moveupurl = new moodle_url($url, array('moveupitem'=>$feedbackitem->id));
$buttonlink = $moveupurl->out();
$strbutton = get_string('moveup_item', 'feedback');
echo '<a class="icon up" title="'.$strbutton.'" href="'.$buttonlink.'">
<img alt="'.$strbutton.'" src="'.$OUTPUT->pix_url('t/up') . '" />
</a>';
echo '</span>';
}
//Print the movedown-button
if ($feedbackitem->position < $lastposition - 1) {
echo '<span class="feedback_item_command_movedown">';
$urlparams = array('movedownitem'=>$feedbackitem->id);
$movedownurl = new moodle_url($url, $urlparams);
$buttonlink = $movedownurl->out();
$strbutton = get_string('movedown_item', 'feedback');
echo '<a class="icon down" title="'.$strbutton.'" href="'.$buttonlink.'">
<img alt="'.$strbutton.'" src="'.$OUTPUT->pix_url('t/down') . '" />
</a>';
echo '</span>';
}
//Print the move-button
if (count($feedbackitems) > 1) {
echo '<span class="feedback_item_command_move">';
$moveurl = new moodle_url($url, array('moveitem'=>$feedbackitem->id));
$buttonlink = $moveurl->out();
$strbutton = get_string('move_item', 'feedback');
echo '<a class="editing_move" title="'.$strbutton.'" href="'.$buttonlink.'">
<img alt="'.$strbutton.'" src="'.$OUTPUT->pix_url('t/move') . '" />
</a>';
echo '</span>';
}
//Print the button to edit the item
if ($feedbackitem->typ != 'pagebreak') {
echo '<span class="feedback_item_command_edit">';
$editurl = new moodle_url('/mod/feedback/edit_item.php');
$editurl->params(array('do_show'=>$do_show,
'cmid'=>$id,
'id'=>$feedbackitem->id,
'typ'=>$feedbackitem->typ));
// In edit_item.php the param id is used for the itemid
// and the cmid is the id to get the module.
$buttonlink = $editurl->out();
$strbutton = get_string('edit_item', 'feedback');
echo '<a class="editing_update" title="'.$strbutton.'" href="'.$buttonlink.'">
<img alt="'.$strbutton.'" src="'.$OUTPUT->pix_url('t/edit') . '" />
</a>';
echo '</span>';
}
//Print the toggle-button to switch required yes/no
if ($feedbackitem->hasvalue == 1) {
echo '<span class="feedback_item_command_toggle">';
if ($feedbackitem->required == 1) {
$buttontitle = get_string('switch_item_to_not_required', 'feedback');
$buttonimg = $OUTPUT->pix_url('required', 'feedback');
} else {
$buttontitle = get_string('switch_item_to_required', 'feedback');
$buttonimg = $OUTPUT->pix_url('notrequired', 'feedback');
}
$urlparams = array('switchitemrequired'=>$feedbackitem->id);
$requiredurl = new moodle_url($url, $urlparams);
$buttonlink = $requiredurl->out();
echo '<a class="icon '.
'feedback_switchrequired" '.
'title="'.$buttontitle.'" '.
'href="'.$buttonlink.'">'.
'<img alt="'.$buttontitle.'" src="'.$buttonimg.'" />'.
'</a>';
echo '</span>';
}
//Print the delete-button
echo '<span class="feedback_item_command_toggle">';
$deleteitemurl = new moodle_url('/mod/feedback/delete_item.php');
$deleteitemurl->params(array('id'=>$id,
'do_show'=>$do_show,
'deleteitem'=>$feedbackitem->id));
$buttonlink = $deleteitemurl->out();
$strbutton = get_string('delete_item', 'feedback');
$src = $OUTPUT->pix_url('t/delete');
echo '<a class="icon delete" title="'.$strbutton.'" href="'.$buttonlink.'">
<img alt="'.$strbutton.'" src="'.$src.'" />
</a>';
echo '</span>';
echo $OUTPUT->box_end();
if ($feedbackitem->typ != 'pagebreak') {
feedback_print_item_preview($feedbackitem);
} else {
echo $OUTPUT->box_start('feedback_pagebreak');
echo get_string('pagebreak', 'feedback').'<hr class="feedback_pagebreak" />';
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
echo $OUTPUT->box_end();
echo '<div class="clearer">&nbsp;</div>';
echo '</li>';
//Print out the target box if we ar moving an item
if (isset($SESSION->feedback->moving) AND $SESSION->feedback->moving->shouldmoving == 1) {
echo '<li>';
$moveposition++;
$movehereurl->param('movehere', $moveposition);
echo $OUTPUT->box_start('clipboard'); //Only shown if shouldmoving = 1
$buttonlink = $movehereurl->out();
$strbutton = get_string('move_here', 'feedback');
$src = $OUTPUT->pix_url('movehere');
echo '<a title="'.$strbutton.'" href="'.$buttonlink.'">
<img class="movetarget" alt="'.$strbutton.'" src="'.$src.'" />
</a>';
echo $OUTPUT->box_end();
echo '</li>';
}
}
echo $OUTPUT->box_end();
echo '</ul>';
echo '</div>';
} else {
echo $OUTPUT->box(get_string('no_items_available_yet', 'feedback'),
'generalbox boxaligncenter');
}
$form = new mod_feedback_complete_form(mod_feedback_complete_form::MODE_EDIT,
$feedbackstructure, 'feedback_edit_form');
echo '<div id="feedback_dragarea">'; // The container for the dragging area.
$form->display();
echo '</div>';
}
/// Finish the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
echo $OUTPUT->footer();

View file

@ -27,53 +27,36 @@ require_once("lib.php");
feedback_init_feedback_session();
$cmid = required_param('cmid', PARAM_INT);
$typ = optional_param('typ', false, PARAM_ALPHA);
$id = optional_param('id', false, PARAM_INT);
$action = optional_param('action', false, PARAM_ALPHA);
$editurl = new moodle_url('/mod/feedback/edit.php', array('id'=>$cmid));
if (!$typ) {
redirect($editurl->out(false));
$itemid = optional_param('id', false, PARAM_INT);
if (!$itemid) {
$cmid = required_param('cmid', PARAM_INT);
$typ = required_param('typ', PARAM_ALPHA);
}
$url = new moodle_url('/mod/feedback/edit_item.php', array('cmid'=>$cmid));
if ($typ !== false) {
$url->param('typ', $typ);
if ($itemid) {
$item = $DB->get_record('feedback_item', array('id' => $itemid), '*', MUST_EXIST);
list($course, $cm) = get_course_and_cm_from_instance($item->feedback, 'feedback');
$url = new moodle_url('/mod/feedback/edit_item.php', array('id' => $itemid));
$typ = $item->typ;
} else {
$item = null;
list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'feedback');
$url = new moodle_url('/mod/feedback/edit_item.php', array('cmid' => $cm->id, 'typ' => $typ));
$item = (object)['id' => null, 'position' => -1, 'typ' => $typ, 'options' => ''];
}
if ($id !== false) {
$url->param('id', $id);
}
$PAGE->set_url($url);
// set up some general variables
if (($formdata = data_submitted()) AND !confirm_sesskey()) {
print_error('invalidsesskey');
}
if (! $cm = get_coursemodule_from_id('feedback', $cmid)) {
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);
$context = context_module::instance($cm->id);
require_capability('mod/feedback:edititems', $context);
$feedback = $PAGE->activityrecord;
//if the typ is pagebreak so the item will be saved directly
if ($typ == 'pagebreak') {
$editurl = new moodle_url('/mod/feedback/edit.php', array('id' => $cm->id));
$PAGE->set_url($url);
// If the typ is pagebreak so the item will be saved directly.
if (!$item->id && $typ === 'pagebreak') {
require_sesskey();
feedback_create_pagebreak($feedback->id);
redirect($editurl->out(false));
exit;
@ -81,17 +64,8 @@ if ($typ == 'pagebreak') {
//get the existing item or create it
// $formdata->itemid = isset($formdata->itemid) ? $formdata->itemid : NULL;
if ($id and $item = $DB->get_record('feedback_item', array('id'=>$id))) {
$typ = $item->typ;
} else {
$item = new stdClass();
$item->id = null;
$item->position = -1;
if (!$typ) {
print_error('typemissing', 'feedback', $editurl->out(false));
}
$item->typ = $typ;
$item->options = '';
if (!$typ || !file_exists($CFG->dirroot.'/mod/feedback/item/'.$typ.'/lib.php')) {
print_error('typemissing', 'feedback', $editurl->out(false));
}
require_once($CFG->dirroot.'/mod/feedback/item/'.$typ.'/lib.php');
@ -101,13 +75,13 @@ $itemobj = feedback_get_item_class($typ);
$itemobj->build_editform($item, $feedback, $cm);
if ($itemobj->is_cancelled()) {
redirect($editurl->out(false));
redirect($editurl);
exit;
}
if ($itemobj->get_data()) {
if ($item = $itemobj->save_item()) {
feedback_move_item($item, $item->position);
redirect($editurl->out(false));
redirect($editurl);
}
}
@ -116,6 +90,8 @@ if ($itemobj->get_data()) {
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
navigation_node::override_active_url(new moodle_url('/mod/feedback/edit.php',
array('id' => $cm->id, 'do_show' => 'edit')));
if ($item->id) {
$PAGE->navbar->add(get_string('edit_item', 'feedback'));
} else {
@ -129,6 +105,8 @@ echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($feedback->name));
/// print the tabs
$current_tab = 'edit';
$id = $cm->id;
require('tabs.php');
//print errormsg

View file

@ -19,14 +19,6 @@ require_once($CFG->dirroot.'/mod/feedback/item/feedback_item_class.php');
class feedback_item_captcha extends feedback_item_base {
protected $type = "captcha";
private $commonparams;
private $item_form = false;
private $item = false;
private $feedback = false;
public function init() {
}
public function build_editform($item, $feedback, $cm) {
global $DB;
@ -47,7 +39,6 @@ class feedback_item_captcha extends feedback_item_base {
}
$this->item = $item;
$this->feedback = $feedback;
$this->item_form = true; //dummy
$lastposition = $DB->count_records('feedback_item', array('feedback'=>$feedback->id));
@ -93,11 +84,6 @@ class feedback_item_captcha extends feedback_item_base {
return $DB->get_record('feedback_item', array('id'=>$this->item->id));
}
//liefert eine Struktur ->name, ->data = array(mit Antworten)
public function get_analysed($item, $groupid = false, $courseid = false) {
return null;
}
public function get_printval($item, $value) {
return '';
}
@ -113,195 +99,56 @@ class feedback_item_captcha extends feedback_item_base {
}
/**
* print the item at the edit-page of feedback
* Returns the formatted name of the item for the complete form or response view
*
* @global object
* @param object $item
* @return void
* @param stdClass $item
* @param bool $withpostfix
* @return string
*/
public function print_item_preview($item) {
global $DB, $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$cmid = 0;
$feedbackid = $item->feedback;
if ($feedbackid > 0) {
$feedback = $DB->get_record('feedback', array('id'=>$feedbackid));
$cm = get_coursemodule_from_instance("feedback", $feedback->id, $feedback->course);
if ($cm) {
$cmid = $cm->id;
}
}
$requiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
public function get_display_name($item, $withpostfix = true) {
return get_string('captcha', 'feedback');
}
/**
* print the item at the complete-page of feedback
* Adds an input element to the complete form
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function print_item_complete($item, $value = '', $highlightrequire = false) {
global $SESSION, $CFG, $DB, $USER, $OUTPUT;
require_once($CFG->libdir.'/recaptchalib.php');
public function complete_form_element($item, $form) {
$name = $this->get_display_name($item);
$inputname = $item->typ . '_' . $item->id;
$align = right_to_left() ? 'right' : 'left';
if ($form->get_mode() != mod_feedback_complete_form::MODE_COMPLETE) {
$form->add_form_element($item,
['static', $inputname, $name],
false,
false);
} else {
$form->add_form_element($item,
['recaptcha', $inputname, $name],
false,
false);
}
$cmid = 0;
$feedbackid = $item->feedback;
if ($feedbackid > 0) {
$feedback = $DB->get_record('feedback', array('id'=>$feedbackid));
$cm = get_coursemodule_from_instance("feedback", $feedback->id, $feedback->course);
if ($cm) {
$cmid = $cm->id;
// Add recaptcha validation to the form.
$form->add_validation_rule(function($values, $files) use ($item, $form) {
$elementname = $item->typ . '_' . $item->id;
$recaptchaelement = $form->get_form_element($elementname);
if (empty($values['recaptcha_response_field'])) {
return array($elementname => get_string('required'));
} else if (!empty($values['recaptcha_challenge_field'])) {
$challengefield = $values['recaptcha_challenge_field'];
$responsefield = $values['recaptcha_response_field'];
if (true !== ($result = $recaptchaelement->verify($challengefield, $responsefield))) {
return array($elementname => $result);
}
} else {
return array($elementname => get_string('missingrecaptchachallengefield'));
}
}
//check if an false value even the value is not required
if ($highlightrequire AND !$this->check_value($value, $item)) {
$falsevalue = true;
} else {
$falsevalue = false;
}
if ($falsevalue) {
$highlight = '<br class="error"><span id="id_error_recaptcha_response_field" class="error"> '.
get_string('err_required', 'form').'</span><br id="id_error_break_recaptcha_response_field" class="error" >';
} else {
$highlight = '';
}
$requiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
if (isset($SESSION->feedback->captchacheck) AND
$SESSION->feedback->captchacheck == $USER->sesskey AND
$value == $USER->sesskey) {
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
$inputname = 'name="'.$item->typ.'_'.$item->id.'"';
echo '<input type="hidden" value="'.$USER->sesskey.'" '.$inputname.' />';
echo '</div>';
return;
}
$strincorrectpleasetryagain = get_string('incorrectpleasetryagain', 'auth');
$strenterthewordsabove = get_string('enterthewordsabove', 'auth');
$strenterthenumbersyouhear = get_string('enterthenumbersyouhear', 'auth');
$strgetanothercaptcha = get_string('getanothercaptcha', 'auth');
$strgetanaudiocaptcha = get_string('getanaudiocaptcha', 'auth');
$strgetanimagecaptcha = get_string('getanimagecaptcha', 'auth');
$recaptureoptions = Array('theme'=>'custom', 'custom_theme_widget'=>'recaptcha_widget');
$html = html_writer::script(js_writer::set_variable('RecaptchaOptions', $recaptureoptions));
$html .= '
<div id="recaptcha_widget" style="display:none">
<div id="recaptcha_image"></div>
<div class="recaptcha_only_if_incorrect_sol" style="color:red">'.
$strincorrectpleasetryagain.
'</div>
<span class="recaptcha_only_if_image">
<label for="recaptcha_response_field">'.$strenterthewordsabove.$requiredmark.'</label>
</span>
<span class="recaptcha_only_if_audio">
<label for="recaptcha_response_field">'.$strenterthenumbersyouhear.'</label>
</span>
<label for="recaptcha_response_field">'.$highlight.'</label>
<input type="text" id="recaptcha_response_field" name="'.$item->typ.'_'.$item->id.'" />
<div><a href="javascript:Recaptcha.reload()">' . $strgetanothercaptcha . '</a></div>
<div class="recaptcha_only_if_image">
<a href="javascript:Recaptcha.switch_type(\'audio\')">' . $strgetanaudiocaptcha . '</a>
</div>
<div class="recaptcha_only_if_audio">
<a href="javascript:Recaptcha.switch_type(\'image\')">' . $strgetanimagecaptcha . '</a>
</div>
</div>';
// Check if we are using SSL.
if (is_https()) {
$ssl = true;
} else {
$ssl = false;
}
//we have to rename the challengefield
if (!empty($CFG->recaptchaprivatekey) AND !empty($CFG->recaptchapublickey)) {
$captchahtml = recaptcha_get_html($CFG->recaptchapublickey, null, $ssl);
echo $html.$captchahtml;
}
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @return void
*/
public function print_item_show_value($item, $value = '') {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$requiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
}
public function check_value($value, $item) {
global $SESSION, $CFG, $USER;
require_once($CFG->libdir.'/recaptchalib.php');
//is recaptcha configured in moodle?
if (empty($CFG->recaptchaprivatekey) OR empty($CFG->recaptchapublickey)) {
return true;
}
$challenge = optional_param('recaptcha_challenge_field', '', PARAM_RAW);
});
if ($value == $USER->sesskey AND $challenge == '') {
return true;
}
$remoteip = getremoteaddr(null);
$response = recaptcha_check_answer($CFG->recaptchaprivatekey, $remoteip, $challenge, $value);
if ($response->is_valid) {
$SESSION->feedback->captchacheck = $USER->sesskey;
return true;
}
unset($SESSION->feedback->captchacheck);
return false;
}
public function create_value($data) {
@ -309,20 +156,6 @@ class feedback_item_captcha extends feedback_item_base {
return $USER->sesskey;
}
//compares the dbvalue with the dependvalue
//dbvalue is value stored in the db
//dependvalue is the value to check
public function compare_value($item, $dbvalue, $dependvalue) {
if ($dbvalue == $dependvalue) {
return true;
}
return false;
}
public function get_presentation($data) {
return '';
}
public function get_hasvalue() {
global $CFG;
@ -337,11 +170,17 @@ class feedback_item_captcha extends feedback_item_base {
return false;
}
public function value_type() {
return PARAM_RAW;
}
public function clean_input_value($value) {
return clean_param($value, $this->value_type());
/**
* Returns the list of actions allowed on this item in the edit mode
*
* @param stdClass $item
* @param stdClass $feedback
* @param cm_info $cm
* @return action_menu_link[]
*/
public function edit_actions($item, $feedback, $cm) {
$actions = parent::edit_actions($item, $feedback, $cm);
unset($actions['update']);
return $actions;
}
}

View file

@ -15,25 +15,45 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
abstract class feedback_item_base {
/** @var string type of the element, should be overridden by each item type */
protected $type;
/** @var feedback_item_form */
protected $item_form;
/** @var stdClass */
protected $item;
/**
* constructor
*
*/
public function __construct() {
$this->init();
}
//this function only can used after the call of build_editform()
/**
* Displays the form for editing an item
*
* this function only can used after the call of build_editform()
*/
public function show_editform() {
$this->item_form->display();
}
/**
* Checks if the editing form was cancelled
*
* @return bool
*/
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
/**
* Gets submitted data from the edit form and saves it in $this->item
*
* @return bool
*/
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
@ -41,27 +61,62 @@ abstract class feedback_item_base {
return false;
}
public function value_type() {
return PARAM_RAW;
}
public function value_is_array() {
return false;
}
abstract public function init();
/**
* Creates and returns an instance of the form for editing the item
*
* @param stdClass $item
* @param stdClass $feedback
* @param cm_info|stdClass $cm
*/
abstract public function build_editform($item, $feedback, $cm);
abstract public function save_item();
abstract public function check_value($value, $item);
abstract public function create_value($data);
abstract public function compare_value($item, $dbvalue, $dependvalue);
abstract public function get_presentation($data);
abstract public function get_hasvalue();
abstract public function can_switch_require();
/**
* Saves the item after it has been edited (or created)
*/
abstract public function save_item();
/**
* Converts the value from complete_form data to the string value that is stored in the db.
* @param mixed $value element from mod_feedback_complete_form::get_data() with the name $item->typ.'_'.$item->id
* @return string
*/
public function create_value($value) {
return strval($value);
}
/**
* Compares the dbvalue with the dependvalue
*
* @param stdClass $item
* @param string $dbvalue is the value input by user in the format as it is stored in the db
* @param string $dependvalue is the value that it needs to be compared against
*/
public function compare_value($item, $dbvalue, $dependvalue) {
return strval($dbvalue) === strval($dependvalue);
}
/**
* Wether this item type has a value that is expected from the user and saved in the stored values.
* @return int
*/
public function get_hasvalue() {
return 1;
}
/**
* Wether this item can be set as both required and not
* @return bool
*/
public function can_switch_require() {
return true;
}
/**
* Adds summary information about an item to the Excel export file
*
* @param object $worksheet a reference to the pear_spreadsheet-object
* @param integer $row_offset
* @param stdClass $xls_formats see analysis_to_excel.php
* @param object $item the db-object from feedback_item
* @param integer $groupid
* @param integer $courseid
@ -72,6 +127,8 @@ abstract class feedback_item_base {
$groupid, $courseid = false);
/**
* Prints analysis for the current item
*
* @param $item the db-object from feedback_item
* @param string $itemnr
* @param integer $groupid
@ -81,6 +138,8 @@ abstract class feedback_item_base {
abstract public function print_analysed($item, $itemnr = '', $groupid = false, $courseid = false);
/**
* Prepares the value for exporting to Excel
*
* @param object $item the db-object from feedback_item
* @param string $value a item-related value from feedback_values
* @return string
@ -88,54 +147,105 @@ abstract class feedback_item_base {
abstract public function get_printval($item, $value);
/**
* returns an Array with three values(typ, name, XXX)
* XXX is also an Array (count of responses on type $this->type)
* each element is a structure (answertext, answercount)
* @param $item the db-object from feedback_item
* @param $groupid if given
* @param $courseid if given
* @return array
* Returns the formatted name of the item for the complete form or response view
*
* @param stdClass $item
* @param bool $withpostfix
* @return string
*/
abstract public function get_analysed($item, $groupid = false, $courseid = false);
public function get_display_name($item, $withpostfix = true) {
return format_text($item->name, FORMAT_HTML, array('noclean' => true, 'para' => false)) .
($withpostfix ? $this->get_display_name_postfix($item) : '');
}
/**
* print the item at the edit-page of feedback
* Returns the postfix to be appended to the display name that is based on other settings
*
* @global object
* @param object $item
* @return void
* @param stdClass $item
* @return string
*/
abstract public function print_item_preview($item);
public function get_display_name_postfix($item) {
return '';
}
/**
* print the item at the complete-page of feedback
* Adds an input element to the complete form
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
* This method is called:
* - to display the form when user completes feedback
* - to display existing elements when teacher edits the feedback items
* - to display the feedback preview (print.php)
* - to display the completed response
* - to preview a feedback template
*
* If it is important which mode the form is in, use $form->get_mode()
*
* Each item type must add a single form element with the name $item->typ.'_'.$item->id
* To add an element use either:
* $form->add_form_element() - adds a single element to the form
* $form->add_form_group_element() - adds a group element to the form
*
* Other useful methods:
* $form->get_item_value()
* $form->set_element_default()
* $form->add_validation_rule()
* $form->set_element_type()
*
* The element must support freezing so it can be used for viewing the response as well.
* If the desired form element does not support freezing, check $form->is_frozen()
* and create a static element instead.
*
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
abstract public function print_item_complete($item, $value = '', $highlightrequire = false);
abstract public function complete_form_element($item, $form);
/**
* print the item at the complete-page of feedback
* Returns the list of actions allowed on this item in the edit mode
*
* @global object
* @param object $item
* @param string $value
* @return void
* @param stdClass $item
* @param stdClass $feedback
* @param cm_info $cm
* @return action_menu_link[]
*/
abstract public function print_item_show_value($item, $value = '');
public function edit_actions($item, $feedback, $cm) {
$actions = array();
/**
* cleans the userinput while submitting the form
*
* @param mixed $value
* @return mixed
*/
abstract public function clean_input_value($value);
$strupdate = get_string('edit_item', 'feedback');
$actions['update'] = new action_menu_link_secondary(
new moodle_url('/mod/feedback/edit_item.php', array('id' => $item->id)),
new pix_icon('t/edit', $strupdate, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$strupdate,
array('class' => 'editing_update', 'data-action' => 'update')
);
if ($this->can_switch_require()) {
if ($item->required == 1) {
$buttontitle = get_string('switch_item_to_not_required', 'feedback');
$buttonimg = 'required';
} else {
$buttontitle = get_string('switch_item_to_required', 'feedback');
$buttonimg = 'notrequired';
}
$actions['required'] = new action_menu_link_secondary(
new moodle_url('/mod/feedback/edit.php', array('id' => $cm->id,
'switchitemrequired' => $item->id, 'sesskey' => sesskey())),
new pix_icon($buttonimg, $buttontitle, 'feedback', array('class' => 'iconsmall', 'title' => '')),
$buttontitle,
array('class' => 'editing_togglerequired', 'data-action' => 'togglerequired')
);
}
$strdelete = get_string('delete_item', 'feedback');
$actions['delete'] = new action_menu_link_secondary(
new moodle_url('/mod/feedback/edit.php', array('id' => $cm->id, 'deleteitem' => $item->id, 'sesskey' => sesskey())),
new pix_icon('t/delete', $strdelete, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$strdelete,
array('class' => 'editing_delete', 'data-action' => 'delete')
);
return $actions;
}
}
//a dummy class to realize pagebreaks
@ -144,25 +254,23 @@ class feedback_item_pagebreak extends feedback_item_base {
public function show_editform() {
}
/**
* Checks if the editing form was cancelled
* @return bool
*/
public function is_cancelled() {
}
public function get_data() {
}
public function init() {
}
public function build_editform($item, $feedback, $cm) {
}
public function save_item() {
}
public function check_value($value, $item) {
}
public function create_value($data) {
}
public function compare_value($item, $dbvalue, $dependvalue) {
}
public function get_presentation($data) {
}
public function get_hasvalue() {
return 0;
}
public function excelprint_item(&$worksheet, $row_offset,
$xls_formats, $item,
@ -173,19 +281,38 @@ class feedback_item_pagebreak extends feedback_item_base {
}
public function get_printval($item, $value) {
}
public function get_analysed($item, $groupid = false, $courseid = false) {
}
public function print_item_preview($item) {
}
public function print_item_complete($item, $value = '', $highlightrequire = false) {
}
public function print_item_show_value($item, $value = '') {
}
public function can_switch_require() {
}
public function value_type() {
}
public function clean_input_value($value) {
return false;
}
/**
* Adds an input element to the complete form
*
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function complete_form_element($item, $form) {
$form->add_form_element($item,
['static', $item->typ.'_'.$item->id, '', '<hr class="feedback_pagebreak">']);
}
/**
* Returns the list of actions allowed on this item in the edit mode
*
* @param stdClass $item
* @param stdClass $feedback
* @param cm_info $cm
* @return action_menu_link[]
*/
public function edit_actions($item, $feedback, $cm) {
$actions = array();
$strdelete = get_string('delete_pagebreak', 'feedback');
$actions['delete'] = new action_menu_link_secondary(
new moodle_url('/mod/feedback/edit.php', array('id' => $cm->id, 'deleteitem' => $item->id, 'sesskey' => sesskey())),
new pix_icon('t/delete', $strdelete, 'moodle', array('class' => 'iconsmall', 'title' => '')),
$strdelete,
array('class' => 'editing_delete', 'data-action' => 'delete')
);
return $actions;
}
}

View file

@ -38,7 +38,7 @@ abstract class feedback_item_form extends moodleform {
$mform =& $this->_form;
if ($common['items']) {
if (array_filter(array_keys($common['items']))) {
$mform->addElement('select',
'dependitem',
get_string('dependitem', 'feedback').'&nbsp;',
@ -49,6 +49,7 @@ abstract class feedback_item_form extends moodleform {
'dependvalue',
get_string('dependvalue', 'feedback'),
array('size'=>FEEDBACK_ITEM_LABEL_TEXTBOX_SIZE, 'maxlength'=>255));
$mform->disabledIf('dependvalue', 'dependitem', 'eq', '0');
} else {
$mform->addElement('hidden', 'dependitem', 0);
$mform->addElement('hidden', 'dependvalue', '');
@ -107,5 +108,20 @@ abstract class feedback_item_form extends moodleform {
$mform->addGroup($buttonarray, 'buttonar', '&nbsp;', array(' '), false);
}
/**
* Return submitted data if properly submitted or returns NULL if validation fails or
* if there is no submitted data.
*
* @return object submitted data; NULL if not valid or not submitted or cancelled
*/
public function get_data() {
if ($item = parent::get_data()) {
if (!isset($item->dependvalue)) {
$item->dependvalue = '';
}
}
return $item;
}
}

View file

@ -19,13 +19,13 @@ require_once($CFG->dirroot.'/mod/feedback/item/feedback_item_class.php');
class feedback_item_info extends feedback_item_base {
protected $type = "info";
private $commonparams;
private $item_form;
private $item;
public function init() {
}
/** Mode recording response time (for non-anonymous feedbacks only) */
const MODE_RESPONSETIME = 1;
/** Mode recording current course */
const MODE_COURSE = 2;
/** Mode recording current course category */
const MODE_CATEGORY = 3;
public function build_editform($item, $feedback, $cm) {
global $DB, $CFG;
@ -64,22 +64,6 @@ class feedback_item_info extends feedback_item_base {
'position' => $position));
}
//this function only can used after the call of build_editform()
public function show_editform() {
$this->item_form->display();
}
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
}
return false;
}
public function save_item() {
global $DB;
@ -102,8 +86,15 @@ class feedback_item_info extends feedback_item_base {
return $DB->get_record('feedback_item', array('id'=>$item->id));
}
//liefert eine Struktur ->name, ->data = array(mit Antworten)
public function get_analysed($item, $groupid = false, $courseid = false) {
/**
* Helper function for collected data, both for analysis page and export to excel
*
* @param stdClass $item the db-object from feedback_item
* @param int|false $groupid
* @param int $courseid
* @return stdClass
*/
protected function get_analysed($item, $groupid = false, $courseid = false) {
$presentation = $item->presentation;
$analysed_val = new stdClass();
@ -116,15 +107,15 @@ class feedback_item_info extends feedback_item_base {
$datavalue = new stdClass();
switch($presentation) {
case 1:
case self::MODE_RESPONSETIME:
$datavalue->value = $value->value;
$datavalue->show = userdate($datavalue->value);
break;
case 2:
case self::MODE_COURSE:
$datavalue->value = $value->value;
$datavalue->show = $datavalue->value;
break;
case 3:
case self::MODE_CATEGORY:
$datavalue->value = $value->value;
$datavalue->show = $datavalue->value;
break;
@ -142,7 +133,8 @@ class feedback_item_info extends feedback_item_base {
if (!isset($value->value)) {
return '';
}
return $item->presentation == 1 ? userdate($value->value) : $value->value;
return $item->presentation == self::MODE_RESPONSETIME ?
userdate($value->value) : $value->value;
}
public function print_analysed($item, $itemnr = '', $groupid = false, $courseid = false) {
@ -158,7 +150,7 @@ class feedback_item_info extends feedback_item_base {
echo '</th></tr>';
$sizeofdata = count($data);
for ($i = 0; $i < $sizeofdata; $i++) {
echo '<tr><td colspan="2" valign="top" align="left">-&nbsp;&nbsp;';
echo '<tr><td colspan="2" class="singlevalue">';
echo str_replace("\n", '<br />', $data[$i]->show);
echo '</td></tr>';
}
@ -187,236 +179,84 @@ class feedback_item_info extends feedback_item_base {
}
/**
* print the item at the edit-page of feedback
* Calculates the value of the item (time, course, course category)
*
* @global object
* @param object $item
* @return void
* @param stdClass $item
* @param stdClass $feedback
* @param int $courseid
* @return string
*/
public function print_item_preview($item) {
global $USER, $DB, $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$presentation = $item->presentation;
$requiredmark = ($item->required == 1)?'<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />':'';
if ($item->feedback) {
$courseid = $DB->get_field('feedback', 'course', array('id'=>$item->feedback));
} else { // the item must be a template item
$cmid = required_param('id', PARAM_INT);
$courseid = $DB->get_field('course_modules', 'course', array('id'=>$cmid));
}
if (!$course = $DB->get_record('course', array('id'=>$courseid))) {
print_error('error');
}
if ($course->id !== SITEID) {
$coursecategory = $DB->get_record('course_categories', array('id'=>$course->category));
} else {
$coursecategory = false;
}
switch($presentation) {
case 1:
$itemvalue = time();
$itemshowvalue = userdate($itemvalue);
protected function get_current_value($item, $feedback, $courseid) {
global $DB;
switch ($item->presentation) {
case self::MODE_RESPONSETIME:
if ($feedback->anonymous != FEEDBACK_ANONYMOUS_YES) {
// Response time is not allowed in anonymous feedbacks.
return time();
}
break;
case 2:
$coursecontext = context_course::instance($course->id);
$itemvalue = format_string($course->shortname,
true,
array('context' => $coursecontext));
$itemshowvalue = $itemvalue;
case self::MODE_COURSE:
$course = get_course($courseid);
return format_string($course->shortname, true,
array('context' => context_course::instance($course->id)));
break;
case 3:
if ($coursecategory) {
$category_context = context_coursecat::instance($coursecategory->id);
$itemvalue = format_string($coursecategory->name,
true,
array('context' => $category_context));
$itemshowvalue = $itemvalue;
} else {
$itemvalue = '';
$itemshowvalue = '';
case self::MODE_CATEGORY:
if ($courseid !== SITEID) {
$coursecategory = $DB->get_record_sql('SELECT cc.id, cc.name FROM {course_categories} cc, {course} c '
. 'WHERE c.category = cc.id AND c.id = ?', array($courseid));
return format_string($coursecategory->name, true,
array('context' => context_coursecat::instance($coursecategory->id)));
}
break;
}
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($item->dependitem) {
if ($dependitem = $DB->get_record('feedback_item', array('id'=>$item->dependitem))) {
echo ' <span class="feedback_depend">';
echo '('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')';
echo '</span>';
}
}
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<input type="hidden" name="'.$item->typ.'_'.$item->id.'" value="'.$itemvalue.'" />';
echo '<span class="feedback_item_info">'.$itemshowvalue.'</span>';
echo '</div>';
return '';
}
/**
* print the item at the complete-page of feedback
* Adds an input element to the complete form
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function print_item_complete($item, $value = '', $highlightrequire = false) {
global $USER, $DB, $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$presentation = $item->presentation;
if ($highlightrequire AND $item->required AND strval($value) == '') {
$highlight = 'error';
public function complete_form_element($item, $form) {
if ($form->get_mode() == mod_feedback_complete_form::MODE_VIEW_RESPONSE) {
$value = strval($form->get_item_value($item));
} else {
$highlight = '';
$value = $this->get_current_value($item,
$form->get_feedback(), $form->get_current_course_id());
}
$requiredmark = ($item->required == 1)?'<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />':'';
$printval = $this->get_printval($item, (object)['value' => $value]);
$feedback = $DB->get_record('feedback', array('id'=>$item->feedback));
if ($courseid = optional_param('courseid', 0, PARAM_INT)) {
$course = $DB->get_record('course', array('id'=>$courseid));
} else {
$course = $DB->get_record('course', array('id'=>$feedback->course));
}
if ($course->id !== SITEID) {
$coursecategory = $DB->get_record('course_categories', array('id'=>$course->category));
} else {
$coursecategory = false;
}
switch($presentation) {
case 1:
if ($feedback->anonymous == FEEDBACK_ANONYMOUS_YES) {
$itemvalue = 0;
$itemshowvalue = '-';
} else {
$itemvalue = time();
$itemshowvalue = userdate($itemvalue);
}
$class = '';
switch ($item->presentation) {
case self::MODE_RESPONSETIME:
$class = 'info-responsetime';
break;
case 2:
$coursecontext = context_course::instance($course->id);
$itemvalue = format_string($course->shortname,
true,
array('context' => $coursecontext));
$itemshowvalue = $itemvalue;
case self::MODE_COURSE:
$class = 'info-course';
break;
case 3:
if ($coursecategory) {
$category_context = context_coursecat::instance($coursecategory->id);
$itemvalue = format_string($coursecategory->name,
true,
array('context' => $category_context));
$itemshowvalue = $itemvalue;
} else {
$itemvalue = '';
$itemshowvalue = '';
}
case self::MODE_CATEGORY:
$class = 'info-category';
break;
}
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
echo '<span class="'.$highlight.'">';
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</span>';
echo '</div>';
$name = $this->get_display_name($item);
$inputname = $item->typ . '_' . $item->id;
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<input type="hidden" name="'.$item->typ.'_'.$item->id.'" value="'.$itemvalue.'" />';
echo '<span class="feedback_item_info">'.$itemshowvalue.'</span>';
echo '</div>';
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @return void
*/
public function print_item_show_value($item, $value = '') {
global $USER, $DB, $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$presentation = $item->presentation;
$requiredmark = ($item->required == 1)?'<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />':'';
if ($presentation == 1) {
$value = $value ? userdate($value) : '&nbsp;';
$element = $form->add_form_element($item,
['select', $inputname, $name,
array($value => $printval),
array('class' => $class)],
false,
false);
$form->set_element_default($inputname, $value);
$element->freeze();
if ($form->get_mode() == mod_feedback_complete_form::MODE_COMPLETE) {
$element->setPersistantFreeze(true);
}
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
//print the presentation
echo $OUTPUT->box_start('generalbox boxalign'.$align);
echo $value;
echo $OUTPUT->box_end();
}
public function check_value($value, $item) {
return true;
}
public function create_value($data) {
$data = clean_text($data);
return $data;
}
//compares the dbvalue with the dependvalue
//the values can be the shortname of a course or the category name
//the date is not compareable :(.
public function compare_value($item, $dbvalue, $dependvalue) {
if ($dbvalue == $dependvalue) {
return true;
}
return false;
}
public function get_presentation($data) {
return $data->infotype;
}
public function get_hasvalue() {
return 1;
}
public function can_switch_require() {
return false;
}
public function value_type() {
return PARAM_TEXT;
}
public function clean_input_value($value) {
return clean_param($value, $this->value_type());
}
}

View file

@ -21,13 +21,12 @@ require_once($CFG->libdir.'/formslib.php');
class feedback_item_label extends feedback_item_base {
protected $type = "label";
private $presentationoptions = null;
private $commonparams;
private $item_form;
private $context;
private $item;
public function init() {
global $CFG;
/**
* Constructor
*/
public function __construct() {
$this->presentationoptions = array('maxfiles' => EDITOR_UNLIMITED_FILES,
'trusttext'=>true);
@ -87,22 +86,6 @@ class feedback_item_label extends feedback_item_base {
$this->item_form = new feedback_label_form('edit_item.php', $customdata);
}
//this function only can used after the call of build_editform()
public function show_editform() {
$this->item_form->display();
}
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
}
return false;
}
public function save_item() {
global $DB;
@ -137,7 +120,12 @@ class feedback_item_label extends feedback_item_base {
return $DB->get_record('feedback_item', array('id'=>$item->id));
}
public function print_item($item) {
/**
* prepares the item for output or export to file
* @param stdClass $item
* @return string
*/
private function print_item($item) {
global $DB, $CFG;
require_once($CFG->libdir . '/filelib.php');
@ -172,63 +160,51 @@ class feedback_item_label extends feedback_item_base {
}
/**
* print the item at the edit-page of feedback
*
* @global object
* @param object $item
* @return void
* @param stdClass $item
* @param bool|true $withpostfix
* @return string
*/
public function print_item_preview($item) {
global $OUTPUT, $DB;
public function get_display_name($item, $withpostfix = true) {
return '';
}
if ($item->dependitem) {
if ($dependitem = $DB->get_record('feedback_item', array('id'=>$item->dependitem))) {
echo ' <span class="feedback_depend">';
echo '('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')';
echo '</span>';
/**
* Adds an input element to the complete form
*
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function complete_form_element($item, $form) {
global $DB;
if (!$item->feedback AND $item->template) {
// This is a template.
$template = $DB->get_record('feedback_template', array('id' => $item->template));
if ($template->ispublic) {
$context = context_system::instance();
} else {
$context = context_course::instance($template->course);
}
$filearea = 'template';
} else {
// This is a question in the current feedback.
$context = $form->get_cm()->context;
$filearea = 'item';
}
$this->print_item($item);
}
$output = file_rewrite_pluginfile_urls($item->presentation, 'pluginfile.php',
$context->id, 'mod_feedback', $filearea, $item->id);
$formatoptions = array('overflowdiv' => true, 'noclean' => true);
$output = format_text($output, FORMAT_HTML, $formatoptions);
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
*/
public function print_item_complete($item, $value = '', $highlightrequire = false) {
$this->print_item($item);
}
$inputname = $item->typ . '_' . $item->id;
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @return void
*/
public function print_item_show_value($item, $value = '') {
$this->print_item($item);
}
public function create_value($data) {
return false;
$name = $this->get_display_name($item);
$form->add_form_element($item, ['static', $inputname, $name, $output], false, false);
}
public function compare_value($item, $dbvalue, $dependvalue) {
return false;
}
//used by create_item and update_item functions,
//when provided $data submitted from feedback_show_edit
public function get_presentation($data) {
}
public function postupdate($item) {
global $DB;
@ -253,9 +229,6 @@ class feedback_item_label extends feedback_item_base {
return false;
}
public function check_value($value, $item) {
}
public function excelprint_item(&$worksheet,
$row_offset,
$xls_formats,
@ -268,12 +241,4 @@ class feedback_item_label extends feedback_item_base {
}
public function get_printval($item, $value) {
}
public function get_analysed($item, $groupid = false, $courseid = false) {
}
public function value_type() {
return PARAM_BOOL;
}
public function clean_input_value($value) {
return '';
}
}

View file

@ -25,13 +25,6 @@ define('FEEDBACK_MULTICHOICE_HIDENOSELECT', 'h');
class feedback_item_multichoice extends feedback_item_base {
protected $type = "multichoice";
private $commonparams;
private $item_form;
private $item;
public function init() {
}
public function build_editform($item, $feedback, $cm) {
global $DB, $CFG;
@ -75,22 +68,6 @@ class feedback_item_multichoice extends feedback_item_base {
$this->item_form = new feedback_multichoice_form('edit_item.php', $customdata);
}
//this function only can used after the call of build_editform()
public function show_editform() {
$this->item_form->display();
}
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
}
return false;
}
public function save_item() {
global $DB;
@ -119,7 +96,16 @@ class feedback_item_multichoice extends feedback_item_base {
//gets an array with three values(typ, name, XXX)
//XXX is an object with answertext, answercount and quotient
public function get_analysed($item, $groupid = false, $courseid = false) {
/**
* Helper function for collected data, both for analysis page and export to excel
*
* @param stdClass $item the db-object from feedback_item
* @param int $groupid
* @param int $courseid
* @return array
*/
protected function get_analysed($item, $groupid = false, $courseid = false) {
$info = $this->get_info($item);
$analysed_item = array();
@ -217,15 +203,6 @@ class feedback_item_multichoice extends feedback_item_base {
public function print_analysed($item, $itemnr = '', $groupid = false, $courseid = false) {
global $OUTPUT;
$sep_dec = get_string('separator_decimal', 'feedback');
if (substr($sep_dec, 0, 2) == '[[') {
$sep_dec = FEEDBACK_DECIMAL;
}
$sep_thous = get_string('separator_thousand', 'feedback');
if (substr($sep_thous, 0, 2) == '[[') {
$sep_thous = FEEDBACK_THOUSAND;
}
$analysed_item = $this->get_analysed($item, $groupid, $courseid);
if ($analysed_item) {
@ -243,19 +220,22 @@ class feedback_item_multichoice extends feedback_item_base {
foreach ($analysed_vals as $val) {
$intvalue = $pixnr % 10;
$pix = $OUTPUT->pix_url('multichoice/' . $intvalue, 'feedback');
$pixspacer = $OUTPUT->pix_url('spacer');
$pixnr++;
$pixwidth = intval($val->quotient * FEEDBACK_MAX_PIX_LENGTH);
$quotient = number_format(($val->quotient * 100), 2, $sep_dec, $sep_thous);
$pixwidth = max(2, intval($val->quotient * FEEDBACK_MAX_PIX_LENGTH));
$pixwidthspacer = FEEDBACK_MAX_PIX_LENGTH + 1 - $pixwidth;
$quotient = format_float($val->quotient * 100, 2);
$str_quotient = '';
if ($val->quotient > 0) {
$str_quotient = ' ('. $quotient . ' %)';
}
echo '<tr>';
echo '<td align="left" valign="top">
-&nbsp;&nbsp;'.trim($val->answertext).':
echo '<td class="optionname">' .
format_text(trim($val->answertext), FORMAT_HTML, array('noclean' => true, 'para' => false)).':
</td>
<td align="left" style="width:'.FEEDBACK_MAX_PIX_LENGTH.';">
<img class="feedback_bar_image" alt="'.$intvalue.'" src="'.$pix.'" height="5" width="'.$pixwidth.'" />
<td class="optioncount" style="width:'.FEEDBACK_MAX_PIX_LENGTH.';">
<img class="feedback_bar_image" alt="'.$intvalue.'" src="'.$pix.'" width="'.$pixwidth.'" />'.
'<img class="feedback_bar_image" alt="" src="'.$pixspacer.'" width="'.$pixwidthspacer.'" />
'.$val->answercount.$str_quotient.'
</td>';
echo '</tr>';
@ -300,310 +280,109 @@ class feedback_item_multichoice extends feedback_item_base {
}
/**
* print the item at the edit-page of feedback
*
* @global object
* @param object $item
* @return void
* Options for the multichoice element
* @param stdClass $item
* @return array
*/
public function print_item_preview($item) {
global $OUTPUT, $DB;
protected function get_options($item) {
$info = $this->get_info($item);
$align = right_to_left() ? 'right' : 'left';
$presentation = explode (FEEDBACK_MULTICHOICE_LINE_SEP, $info->presentation);
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
//test if required and no value is set so we have to mark this item
//we have to differ check and the other subtypes
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if ($info->subtype == 'd') {
echo '<label for="'. $item->typ . '_' . $item->id .'">';
$options = array();
foreach ($presentation as $idx => $optiontext) {
$options[$idx + 1] = format_text($optiontext, FORMAT_HTML, array('noclean' => true, 'para' => false));
}
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($item->dependitem) {
if ($dependitem = $DB->get_record('feedback_item', array('id'=>$item->dependitem))) {
echo ' <span class="feedback_depend">';
echo '('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')';
echo '</span>';
}
}
if ($info->subtype == 'd') {
echo '</label>';
}
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
$index = 1;
$checked = '';
if ($info->subtype == 'r' || $info->subtype == 'c') {
// if (r)adio buttons or (c)heckboxes
echo '<fieldset>';
echo '<ul>';
if ($info->subtype === 'r' && !$this->hidenoselect($item)) {
$options = array(0 => get_string('not_selected', 'feedback')) + $options;
}
if ($info->horizontal) {
$hv = 'h';
} else {
$hv = 'v';
}
if ($info->subtype == 'r' AND !$this->hidenoselect($item)) {
//print the "not_selected" item on radiobuttons
?>
<li class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<span class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<?php
echo '<input type="radio" '.
'name="'.$item->typ.'_'.$item->id.'[]" '.
'id="'.$item->typ.'_'.$item->id.'_xxx" '.
'value="" checked="checked" />';
?>
</span>
<span class="feedback_item_radiolabel_<?php echo $hv.'_'.$align;?>">
<label for="<?php echo $item->typ . '_' . $item->id.'_xxx';?>">
<?php print_string('not_selected', 'feedback');?>
</label>
</span>
</li>
<?php
}
switch($info->subtype) {
case 'r':
$this->print_item_radio($presentation, $item, false, $info, $align);
break;
case 'c':
$this->print_item_check($presentation, $item, false, $info, $align);
break;
case 'd':
$this->print_item_dropdown($presentation, $item, false, $info, $align);
break;
}
if ($info->subtype == 'r' || $info->subtype == 'c') {
// if (r)adio buttons or (c)heckboxes
echo '</ul>';
echo '</fieldset>';
}
echo '</div>';
return $options;
}
/**
* print the item at the complete-page of feedback
* Adds an input element to the complete form
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
* This element has many options - it can be displayed as group or radio elements,
* group of checkboxes or a dropdown list.
*
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function print_item_complete($item, $value = null, $highlightrequire = false) {
global $OUTPUT;
public function complete_form_element($item, $form) {
$info = $this->get_info($item);
$align = right_to_left() ? 'right' : 'left';
if ($value == null) {
$value = array();
}
$presentation = explode (FEEDBACK_MULTICHOICE_LINE_SEP, $info->presentation);
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
//test if required and no value is set so we have to mark this item
//we have to differ check and the other subtypes
if (is_array($value)) {
$values = $value;
} else {
$values = explode(FEEDBACK_MULTICHOICE_LINE_SEP, $value);
}
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
$name = $this->get_display_name($item);
$class = 'multichoice-' . $info->subtype;
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
if ($info->subtype == 'd') {
echo '<label for="'. $inputname .'">';
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($highlightrequire AND $item->required AND (count($values) == 0 OR $values[0] == '' OR $values[0] == 0)) {
echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
'</span><br id="id_error_break_'.$inputname.'" class="error" >';
}
echo '</label>';
} else {
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($highlightrequire AND $item->required AND (count($values) == 0 OR $values[0] == '' OR $values[0] == 0)) {
echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
'</span><br id="id_error_break_'.$inputname.'" class="error" >';
}
}
echo '</div>';
$options = $this->get_options($item);
$separator = !empty($info->horizontal) ? ' ' : '<br>';
$tmpvalue = $form->get_item_value($item);
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
if ($info->subtype == 'r' || $info->subtype == 'c') {
// if (r)adio buttons or (c)heckboxes
echo '<fieldset>';
echo '<ul>';
}
if ($info->horizontal) {
$hv = 'h';
if ($info->subtype === 'd' || ($info->subtype === 'r' && $form->is_frozen())) {
// Display as a dropdown in the complete form or a single value in the response view.
$element = $form->add_form_element($item,
['select', $inputname.'[0]', $name, array(0 => '') + $options, array('class' => $class)],
false, false);
$form->set_element_default($inputname.'[0]', $tmpvalue);
} else if ($info->subtype === 'c' && $form->is_frozen()) {
// Display list of checkbox values in the response view.
$objs = [];
foreach (explode(FEEDBACK_MULTICHOICE_LINE_SEP, $form->get_item_value($item)) as $v) {
$objs[] = ['static', $inputname."[$v]", '', isset($options[$v]) ? $options[$v] : ''];
}
$element = $form->add_form_group_element($item, 'group_'.$inputname, $name, $objs, $separator, $class);
} else {
$hv = 'v';
}
//print the "not_selected" item on radiobuttons
if ($info->subtype == 'r' AND !$this->hidenoselect($item)) {
?>
<li class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<span class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<?php
$checked = '';
// if (!$value) {
// $checked = 'checked="checked"';
// }
if (count($values) == 0 OR $values[0] == '' OR $values[0] == 0) {
$checked = 'checked="checked"';
// Display group or radio or checkbox elements.
$class .= ' multichoice-' . ($info->horizontal ? 'horizontal' : 'vertical');
$objs = [];
if ($info->subtype === 'c') {
// Checkboxes.
$objs[] = ['hidden', $inputname.'[0]', 0];
foreach ($options as $idx => $label) {
$objs[] = ['advcheckbox', $inputname.'['.$idx.']', '', $label, null, array(0, $idx)];
}
$element = $form->add_form_group_element($item, 'group_'.$inputname, $name, $objs, $separator, $class);
if ($tmpvalue) {
foreach (explode(FEEDBACK_MULTICHOICE_LINE_SEP, $tmpvalue) as $v) {
$form->set_element_default($inputname.'['.$v.']', $v);
}
echo '<input type="radio" '.
'name="'.$item->typ.'_'.$item->id.'[]" '.
'id="'.$item->typ.'_'.$item->id.'_xxx" '.
'value="" '.$checked.' />';
?>
</span>
<span class="feedback_item_radiolabel_<?php echo $hv.'_'.$align;?>">
<label for="<?php echo $item->typ.'_'.$item->id.'_xxx';?>">
<?php print_string('not_selected', 'feedback');?>
</label>
</span>
</li>
<?php
}
} else {
// Radio.
foreach ($options as $idx => $label) {
$objs[] = ['radio', $inputname.'[0]', '', $label, $idx];
}
$element = $form->add_form_group_element($item, 'group_'.$inputname, $name, $objs, $separator, $class);
$form->set_element_default($inputname.'[0]', $tmpvalue);
}
}
switch($info->subtype) {
case 'r':
$this->print_item_radio($presentation, $item, $value, $info, $align);
break;
case 'c':
$this->print_item_check($presentation, $item, $value, $info, $align);
break;
case 'd':
$this->print_item_dropdown($presentation, $item, $value, $info, $align);
break;
// Process 'required' rule.
if ($item->required) {
$elementname = $element->getName();
$form->add_validation_rule(function($values, $files) use ($elementname, $item) {
$inputname = $item->typ . '_' . $item->id;
return empty($values[$inputname]) || !array_filter($values[$inputname]) ?
array($elementname => get_string('required')) : true;
});
}
if ($info->subtype == 'r' || $info->subtype == 'c') {
// if (r)adio buttons or (c)heckboxes
echo '</ul>';
echo '</fieldset>';
}
echo '</div>';
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @return void
* Prepares value that user put in the form for storing in DB
* @param array $value
* @return string
*/
public function print_item_show_value($item, $value = null) {
global $OUTPUT;
$info = $this->get_info($item);
$align = right_to_left() ? 'right' : 'left';
if ($value == null) {
$value = array();
}
$presentation = explode (FEEDBACK_MULTICHOICE_LINE_SEP, $info->presentation);
//test if required and no value is set so we have to mark this item
//we have to differ check and the other subtypes
if ($info->subtype == 'c') {
if (is_array($value)) {
$values = $value;
} else {
$values = explode(FEEDBACK_MULTICHOICE_LINE_SEP, $value);
}
}
$requiredmark = '';
if ($item->required == 1) {
$requiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
}
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
$index = 1;
if ($info->subtype == 'c') {
echo $OUTPUT->box_start('generalbox boxalign'.$align);
foreach ($presentation as $pres) {
foreach ($values as $val) {
if ($val == $index) {
echo '<div class="feedback_item_multianswer">';
echo format_text($pres, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
break;
}
}
$index++;
}
echo $OUTPUT->box_end();
} else {
foreach ($presentation as $pres) {
if ($value == $index) {
echo $OUTPUT->box_start('generalbox boxalign'.$align);
echo format_text($pres, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo $OUTPUT->box_end();
break;
}
$index++;
}
}
echo '</div>';
public function create_value($value) {
$value = array_unique(array_filter($value));
return join(FEEDBACK_MULTICHOICE_LINE_SEP, $value);
}
public function check_value($value, $item) {
$info = $this->get_info($item);
if ($item->required != 1) {
return true;
}
if (empty($value) OR !is_array($value) OR !array_filter($value)) {
return false;
}
return true;
}
public function create_value($data) {
$vallist = $data;
if (is_array($vallist)) {
$vallist = array_unique(array_filter($vallist));
}
return trim($this->item_array_to_string($vallist));
}
//compares the dbvalue with the dependvalue
//dbvalue is the number of one selection
//dependvalue is the presentation of one selection
/**
* Compares the dbvalue with the dependvalue
*
* @param stdClass $item
* @param string $dbvalue is the value input by user in the format as it is stored in the db
* @param string $dependvalue is the value that it needs to be compared against
*/
public function compare_value($item, $dbvalue, $dependvalue) {
if (is_array($dbvalue)) {
@ -626,23 +405,6 @@ class feedback_item_multichoice extends feedback_item_base {
return false;
}
public function get_presentation($data) {
$present = str_replace("\n", FEEDBACK_MULTICHOICE_LINE_SEP, trim($data->itemvalues));
if (!isset($data->subtype)) {
$subtype = 'r';
} else {
$subtype = substr($data->subtype, 0, 1);
}
if (isset($data->horizontal) AND $data->horizontal == 1 AND $subtype != 'd') {
$present .= FEEDBACK_MULTICHOICE_ADJUST_SEP.'1';
}
return $subtype.FEEDBACK_MULTICHOICE_TYPE_SEP.$present;
}
public function get_hasvalue() {
return 1;
}
public function get_info($item) {
$presentation = empty($item->presentation) ? '' : $item->presentation;
@ -671,163 +433,6 @@ class feedback_item_multichoice extends feedback_item_base {
return $info;
}
private function item_array_to_string($value) {
if (!is_array($value)) {
return $value;
}
if (empty($value)) {
return '0';
}
$retval = '';
$arrvals = array_values($value);
$arrvals = clean_param_array($arrvals, PARAM_INT); //prevent sql-injection
$retval = $arrvals[0];
$sizeofarrvals = count($arrvals);
for ($i = 1; $i < $sizeofarrvals; $i++) {
$retval .= FEEDBACK_MULTICHOICE_LINE_SEP.$arrvals[$i];
}
return $retval;
}
private function print_item_radio($presentation, $item, $value, $info, $align) {
$index = 1;
$checked = '';
if (is_array($value)) {
$values = $value;
} else {
$values = array($value);
}
if ($info->horizontal) {
$hv = 'h';
} else {
$hv = 'v';
}
foreach ($presentation as $radio) {
foreach ($values as $val) {
if ($val == $index) {
$checked = 'checked="checked"';
break;
} else {
$checked = '';
}
}
$inputname = $item->typ . '_' . $item->id;
$inputid = $inputname.'_'.$index;
?>
<li class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<span class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<?php
echo '<input type="radio" '.
'name="'.$inputname.'[]" '.
'id="'.$inputid.'" '.
'value="'.$index.'" '.$checked.' />';
?>
</span>
<span class="feedback_item_radiolabel_<?php echo $hv.'_'.$align;?>">
<label for="<?php echo $inputid;?>">
<?php echo format_text($radio, FORMAT_HTML, array('noclean' => true, 'para' => false));?>
</label>
</span>
</li>
<?php
$index++;
}
}
private function print_item_check($presentation, $item, $value, $info, $align) {
if (is_array($value)) {
$values = $value;
} else {
$values = explode(FEEDBACK_MULTICHOICE_LINE_SEP, $value);
}
if ($info->horizontal) {
$hv = 'h';
} else {
$hv = 'v';
}
$index = 1;
$checked = '';
$inputname = $item->typ. '_' . $item->id;
echo '<input type="hidden" name="'.$inputname.'[]" value="0" />';
foreach ($presentation as $check) {
foreach ($values as $val) {
if ($val == $index) {
$checked = 'checked="checked"';
break;
} else {
$checked = '';
}
}
$inputid = $item->typ. '_' . $item->id.'_'.$index;
?>
<li class="feedback_item_check_<?php echo $hv.'_'.$align;?>">
<span class="feedback_item_check_<?php echo $hv.'_'.$align;?>">
<?php
echo '<input type="checkbox" '.
'name="'.$inputname.'[]" '.
'id="'.$inputid.'" '.
'value="'.$index.'" '.$checked.' />';
?>
</span>
<span class="feedback_item_radiolabel_<?php echo $hv.'_'.$align;?>">
<label for="<?php echo $inputid;?>">
<?php echo format_text($check, FORMAT_HTML, array('noclean' => true, 'para' => false));?>&nbsp;
</label>
</span>
</li>
<?php
$index++;
}
}
private function print_item_dropdown($presentation, $item, $value, $info, $align) {
if (is_array($value)) {
$values = $value;
} else {
$values = array($value);
}
if ($info->horizontal) {
$hv = 'h';
} else {
$hv = 'v';
}
?>
<div class="feedback_item_select_<?php echo $hv.'_'.$align;?>">
<select id="<?php echo $item->typ .'_' . $item->id;?>" name="<?php echo $item->typ .'_' . $item->id;?>[]" size="1">
<option value="0">&nbsp;</option>
<?php
$index = 1;
$selected = '';
foreach ($presentation as $dropdown) {
foreach ($values as $val) {
if ($val == $index) {
$selected = 'selected="selected"';
break;
} else {
$selected = '';
}
}
?>
<option value="<?php echo $index;?>" <?php echo $selected;?>>
<?php echo format_text($dropdown, FORMAT_HTML, array('noclean' => true, 'para' => false));?>
</option>
<?php
$index++;
}
?>
</select>
</div>
<?php
}
public function set_ignoreempty($item, $ignoreempty=true) {
$item->options = str_replace(FEEDBACK_MULTICHOICE_IGNOREEMPTY, '', $item->options);
if ($ignoreempty) {
@ -855,20 +460,4 @@ class feedback_item_multichoice extends feedback_item_base {
}
return false;
}
public function can_switch_require() {
return true;
}
public function value_type() {
return PARAM_INT;
}
public function value_is_array() {
return true;
}
public function clean_input_value($value) {
return clean_param_array($value, $this->value_type());
}
}

View file

@ -43,12 +43,6 @@ class feedback_multichoice_form extends feedback_item_form {
array('size' => FEEDBACK_ITEM_LABEL_TEXTBOX_SIZE,
'maxlength' => 255));
$mform->addElement('select',
'horizontal',
get_string('adjustment', 'feedback').'&nbsp;',
array(0 => get_string('vertical', 'feedback'),
1 => get_string('horizontal', 'feedback')));
$mform->addElement('select',
'subtype',
get_string('multichoicetype', 'feedback').'&nbsp;',
@ -56,15 +50,22 @@ class feedback_multichoice_form extends feedback_item_form {
'c'=>get_string('check', 'feedback'),
'd'=>get_string('dropdown', 'feedback')));
$mform->addElement('selectyesno',
'ignoreempty',
get_string('do_not_analyse_empty_submits', 'feedback'));
$mform->addElement('select',
'horizontal',
get_string('adjustment', 'feedback').'&nbsp;',
array(0 => get_string('vertical', 'feedback'),
1 => get_string('horizontal', 'feedback')));
$mform->disabledIf('horizontal', 'subtype', 'eq', 'd');
$mform->addElement('selectyesno',
'hidenoselect',
get_string('hide_no_select_option', 'feedback'));
$mform->disabledIf('hidenoselect', 'subtype', 'ne', 'r');
$mform->addElement('selectyesno',
'ignoreempty',
get_string('do_not_analyse_empty_submits', 'feedback'));
$mform->addElement('textarea', 'values', get_string('multichoice_values', 'feedback'),
'wrap="virtual" rows="10" cols="65"');
@ -106,6 +107,9 @@ class feedback_multichoice_form extends feedback_item_form {
if (!isset($item->hidenoselect)) {
$item->hidenoselect = 1;
}
if (!isset($item->ignoreempty)) {
$item->ignoreempty = 0;
}
$item->presentation = $subtype.FEEDBACK_MULTICHOICE_TYPE_SEP.$presentation;
return $item;

View file

@ -30,13 +30,6 @@ define('FEEDBACK_MULTICHOICERATED_HIDENOSELECT', 'h');
class feedback_item_multichoicerated extends feedback_item_base {
protected $type = "multichoicerated";
private $commonparams;
private $item_form;
private $item;
public function init() {
}
public function build_editform($item, $feedback, $cm) {
global $DB, $CFG;
@ -80,22 +73,6 @@ class feedback_item_multichoicerated extends feedback_item_base {
$this->item_form = new feedback_multichoicerated_form('edit_item.php', $customdata);
}
//this function only can used after the call of build_editform()
public function show_editform() {
$this->item_form->display();
}
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
}
return false;
}
public function save_item() {
global $DB;
@ -122,9 +99,15 @@ class feedback_item_multichoicerated extends feedback_item_base {
}
//gets an array with three values(typ, name, XXX)
//XXX is an object with answertext, answercount and quotient
public function get_analysed($item, $groupid = false, $courseid = false) {
/**
* Helper function for collected data, both for analysis page and export to excel
*
* @param stdClass $item the db-object from feedback_item
* @param int $groupid
* @param int $courseid
* @return array
*/
protected function get_analysed($item, $groupid = false, $courseid = false) {
$analysed_item = array();
$analysed_item[] = $item->typ;
$analysed_item[] = $item->name;
@ -193,16 +176,6 @@ class feedback_item_multichoicerated extends feedback_item_base {
public function print_analysed($item, $itemnr = '', $groupid = false, $courseid = false) {
global $OUTPUT;
$sep_dec = get_string('separator_decimal', 'feedback');
if (substr($sep_dec, 0, 2) == '[[') {
$sep_dec = FEEDBACK_DECIMAL;
}
$sep_thous = get_string('separator_thousand', 'feedback');
if (substr($sep_thous, 0, 2) == '[[') {
$sep_thous = FEEDBACK_THOUSAND;
}
$analysed_item = $this->get_analysed($item, $groupid, $courseid);
if ($analysed_item) {
echo '<tr><th colspan="2" align="left">';
@ -218,16 +191,20 @@ class feedback_item_multichoicerated extends feedback_item_base {
foreach ($analysed_vals as $val) {
$intvalue = $pixnr % 10;
$pix = $OUTPUT->pix_url('multichoice/' . $intvalue, 'feedback');
$pixspacer = $OUTPUT->pix_url('spacer');
$pixnr++;
$pixwidth = intval($val->quotient * FEEDBACK_MAX_PIX_LENGTH);
$pixwidthspacer = FEEDBACK_MAX_PIX_LENGTH + 1 - $pixwidth;
$avg += $val->avg;
$quotient = number_format(($val->quotient * 100), 2, $sep_dec, $sep_thous);
$quotient = format_float($val->quotient * 100, 2);
echo '<tr>';
echo '<td align="left" valign="top">';
echo '-&nbsp;&nbsp;'.trim($val->answertext).' ('.$val->value.'):</td>';
echo '<td align="left" style="width: '.FEEDBACK_MAX_PIX_LENGTH.'">';
echo '<img class="feedback_bar_image" alt="'.$intvalue.'" src="'.$pix.'" height="5" width="'.$pixwidth.'" />';
echo '<td class="optionname">';
echo '<span class="weight">('.$val->value.') </span>'.
format_text(trim($val->answertext), FORMAT_HTML, array('noclean' => true, 'para' => false)).':</td>';
echo '<td class="optionvalue" style="width: '.FEEDBACK_MAX_PIX_LENGTH.'">';
echo '<img class="feedback_bar_image" alt="'.$intvalue.'" src="'.$pix.'" width="'.$pixwidth.'" />';
echo '<img class="feedback_bar_image" alt="" src="'.$pixspacer.'" width="'.$pixwidthspacer.'" /> ';
echo $val->answercount;
if ($val->quotient > 0) {
echo ' ('.$quotient.' %)';
@ -236,7 +213,7 @@ class feedback_item_multichoicerated extends feedback_item_base {
}
echo '</td></tr>';
}
$avg = number_format(($avg), 2, $sep_dec, $sep_thous);
$avg = format_float($avg, 2);
echo '<tr><td align="left" colspan="2"><b>';
echo get_string('average', 'feedback').': '.$avg.'</b>';
echo '</td></tr>';
@ -288,167 +265,70 @@ class feedback_item_multichoicerated extends feedback_item_base {
}
/**
* print the item at the edit-page of feedback
*
* @global object
* @param object $item
* @return void
* Options for the multichoice element
* @param stdClass $item
* @return array
*/
public function print_item_preview($item) {
global $OUTPUT, $DB;
$align = right_to_left() ? 'right' : 'left';
protected function get_options($item) {
$info = $this->get_info($item);
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$lines = explode(FEEDBACK_MULTICHOICERATED_LINE_SEP, $info->presentation);
$options = array();
foreach ($lines as $idx => $line) {
list($weight, $optiontext) = explode(FEEDBACK_MULTICHOICERATED_VALUE_SEP, $line);
$options[$idx + 1] = format_text("<span class=\"weight\">($weight) </span>".$optiontext,
FORMAT_HTML, array('noclean' => true, 'para' => false));
}
if ($info->subtype === 'r' && !$this->hidenoselect($item)) {
$options = array(0 => get_string('not_selected', 'feedback')) + $options;
}
$lines = explode (FEEDBACK_MULTICHOICERATED_LINE_SEP, $info->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if ($info->subtype == 'd') {
echo '<label for="'. $item->typ . '_' . $item->id .'">';
}
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($item->dependitem) {
if ($dependitem = $DB->get_record('feedback_item', array('id'=>$item->dependitem))) {
echo ' <span class="feedback_depend">';
echo '('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')';
echo '</span>';
}
}
if ($info->subtype == 'd') {
echo '</label>';
}
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
switch($info->subtype) {
case 'r':
$this->print_item_radio($item, false, $info, $align, true, $lines);
break;
case 'd':
$this->print_item_dropdown($item, false, $info, $align, true, $lines);
break;
}
echo '</div>';
return $options;
}
/**
* print the item at the complete-page of feedback
* Adds an input element to the complete form
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function print_item_complete($item, $value = '', $highlightrequire = false) {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
public function complete_form_element($item, $form) {
$info = $this->get_info($item);
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$lines = explode (FEEDBACK_MULTICHOICERATED_LINE_SEP, $info->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
$name = $this->get_display_name($item);
$class = 'multichoicerated-' . $info->subtype;
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
if ($info->subtype == 'd') {
echo '<label for="'. $inputname .'">';
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($highlightrequire AND $item->required AND intval($value) <= 0) {
echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
'</span><br id="id_error_break_'.$inputname.'" class="error" >';
}
echo '</label>';
$options = $this->get_options($item);
if ($info->subtype === 'd' || $form->is_frozen()) {
$el = $form->add_form_element($item,
['select', $inputname, $name, array('' => '') + $options, array('class' => $class)]);
} else {
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($highlightrequire AND $item->required AND intval($value) <= 0) {
echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
'</span><br id="id_error_break_'.$inputname.'" class="error" >';
$objs = array();
foreach ($options as $idx => $label) {
$objs[] = ['radio', $inputname, '', $label, $idx];
}
$separator = $info->horizontal ? ' ' : '<br>';
$class .= ' multichoicerated-' . ($info->horizontal ? 'horizontal' : 'vertical');
$el = $form->add_form_group_element($item, 'group_'.$inputname, $name, $objs, $separator, $class);
// Set previously input values.
$form->set_element_default($inputname, $form->get_item_value($item));
// Process "required" rule.
if ($item->required) {
$form->add_validation_rule(function($values, $files) use ($item) {
$inputname = $item->typ . '_' . $item->id;
return empty($values[$inputname]) ? array('group_' . $inputname => get_string('required')) : true;
});
}
}
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
switch($info->subtype) {
case 'r':
$this->print_item_radio($item, $value, $info, $align, false, $lines);
break;
case 'd':
$this->print_item_dropdown($item, $value, $info, $align, false, $lines);
break;
}
echo '</div>';
}
/**
* print the item at the complete-page of feedback
* Compares the dbvalue with the dependvalue
*
* @global object
* @param object $item
* @param string $value
* @return void
* @param stdClass $item
* @param string $dbvalue is the value input by user in the format as it is stored in the db
* @param string $dependvalue is the value that it needs to be compared against
*/
public function print_item_show_value($item, $value = '') {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$info = $this->get_info($item);
$lines = explode (FEEDBACK_MULTICHOICERATED_LINE_SEP, $info->presentation);
$requiredmark = ($item->required == 1)?'<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />':'';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
$index = 1;
foreach ($lines as $line) {
if ($value == $index) {
$item_value = explode(FEEDBACK_MULTICHOICERATED_VALUE_SEP, $line);
echo $OUTPUT->box_start('generalbox boxalign'.$align);
echo format_text($item_value[1], FORMAT_HTML, array('noclean' => true, 'para' => false));
echo $OUTPUT->box_end();
break;
}
$index++;
}
echo '</div>';
}
public function check_value($value, $item) {
if ((!isset($value) OR $value == '' OR $value == 0) AND $item->required != 1) {
return true;
}
if (intval($value) > 0) {
return true;
}
return false;
}
public function create_value($data) {
$data = trim($data);
return $data;
}
//compares the dbvalue with the dependvalue
//dbvalue is the number of one selection
//dependvalue is the presentation of one selection
public function compare_value($item, $dbvalue, $dependvalue) {
if (is_array($dbvalue)) {
@ -473,25 +353,6 @@ class feedback_item_multichoicerated extends feedback_item_base {
return false;
}
public function get_presentation($data) {
$present = $this->prepare_presentation_values_save(trim($data->itemvalues),
FEEDBACK_MULTICHOICERATED_VALUE_SEP2,
FEEDBACK_MULTICHOICERATED_VALUE_SEP);
if (!isset($data->subtype)) {
$subtype = 'r';
} else {
$subtype = substr($data->subtype, 0, 1);
}
if (isset($data->horizontal) AND $data->horizontal == 1 AND $subtype != 'd') {
$present .= FEEDBACK_MULTICHOICERATED_ADJUST_SEP.'1';
}
return $subtype.FEEDBACK_MULTICHOICERATED_TYPE_SEP.$present;
}
public function get_hasvalue() {
return 1;
}
public function get_info($item) {
$presentation = empty($item->presentation) ? '' : $item->presentation;
@ -526,112 +387,6 @@ class feedback_item_multichoicerated extends feedback_item_base {
return $info;
}
private function print_item_radio($item, $value, $info, $align, $showrating, $lines) {
$index = 1;
$checked = '';
if ($info->horizontal) {
$hv = 'h';
} else {
$hv = 'v';
}
echo '<fieldset>';
echo '<ul>';
if (!$this->hidenoselect($item)) {
?>
<li class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<span class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<?php
echo '<input type="radio" '.
'name="'.$item->typ.'_'.$item->id.'" '.
'id="'.$item->typ.'_'.$item->id.'_xxx" '.
'value="" checked="checked" />';
?>
</span>
<span class="feedback_item_radiolabel_<?php echo $hv.'_'.$align;?>">
<label for="<?php echo $item->typ . '_' . $item->id.'_xxx';?>">
<?php print_string('not_selected', 'feedback');?>&nbsp;
</label>
</span>
</li>
<?php
}
foreach ($lines as $line) {
if ($value == $index) {
$checked = 'checked="checked"';
} else {
$checked = '';
}
$radio_value = explode(FEEDBACK_MULTICHOICERATED_VALUE_SEP, $line);
$inputname = $item->typ . '_' . $item->id;
$inputid = $inputname.'_'.$index;
?>
<li class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<span class="feedback_item_radio_<?php echo $hv.'_'.$align;?>">
<?php
echo '<input type="radio" '.
'name="'.$inputname.'" '.
'id="'.$inputid.'" '.
'value="'.$index.'" '.$checked.' />';
?>
</span>
<span class="feedback_item_radiolabel_<?php echo $hv.'_'.$align;?>">
<label for="<?php echo $inputid;?>">
<?php
if ($showrating) {
$str_rating_value = '('.$radio_value[0].') '.$radio_value[1];
echo format_text($str_rating_value, FORMAT_HTML, array('noclean' => true, 'para' => false));
} else {
echo format_text($radio_value[1], FORMAT_HTML, array('noclean' => true, 'para' => false));
}
?>
</label>
</span>
</li>
<?php
$index++;
}
echo '</ul>';
echo '</fieldset>';
}
private function print_item_dropdown($item, $value, $info, $align, $showrating, $lines) {
if ($info->horizontal) {
$hv = 'h';
} else {
$hv = 'v';
}
?>
<div class="feedback_item_select_<?php echo $hv.'_'.$align;?>">
<select id="<?php echo $item->typ.'_'.$item->id;?>" name="<?php echo $item->typ.'_'.$item->id;?>">
<option value="0">&nbsp;</option>
<?php
$index = 1;
$checked = '';
foreach ($lines as $line) {
if ($value == $index) {
$selected = 'selected="selected"';
} else {
$selected = '';
}
$dropdown_value = explode(FEEDBACK_MULTICHOICERATED_VALUE_SEP, $line);
if ($showrating) {
echo '<option value="'.$index.'" '.$selected.'>';
echo format_text('(' . $dropdown_value[0] . ') ' . $dropdown_value[1], FORMAT_HTML, array('para' => false));
echo '</option>';
} else {
echo '<option value="'.$index.'" '.$selected.'>';
echo format_text($dropdown_value[1], FORMAT_HTML, array('para' => false));
echo '</option>';
}
$index++;
}
?>
</select>
</div>
<?php
}
public function prepare_presentation_values($linesep1,
$linesep2,
$valuestring,
@ -703,16 +458,4 @@ class feedback_item_multichoicerated extends feedback_item_base {
}
return false;
}
public function can_switch_require() {
return true;
}
public function value_type() {
return PARAM_INT;
}
public function clean_input_value($value) {
return clean_param($value, $this->value_type());
}
}

View file

@ -43,25 +43,28 @@ class feedback_multichoicerated_form extends feedback_item_form {
array('size'=>FEEDBACK_ITEM_LABEL_TEXTBOX_SIZE,
'maxlength'=>255));
$mform->addElement('select',
'horizontal',
get_string('adjustment', 'feedback').'&nbsp;',
array(0 => get_string('vertical', 'feedback'),
1 => get_string('horizontal', 'feedback')));
$mform->addElement('select',
'subtype',
get_string('multichoicetype', 'feedback').'&nbsp;',
array('r'=>get_string('radio', 'feedback'),
'd'=>get_string('dropdown', 'feedback')));
$mform->addElement('selectyesno',
'ignoreempty',
get_string('do_not_analyse_empty_submits', 'feedback'));
$mform->addElement('select',
'horizontal',
get_string('adjustment', 'feedback').'&nbsp;',
array(0 => get_string('vertical', 'feedback'),
1 => get_string('horizontal', 'feedback')));
$mform->disabledIf('horizontal', 'subtype', 'eq', 'd');
$mform->addElement('selectyesno',
'hidenoselect',
get_string('hide_no_select_option', 'feedback'));
$mform->disabledIf('hidenoselect', 'subtype', 'eq', 'd');
$mform->addElement('selectyesno',
'ignoreempty',
get_string('do_not_analyse_empty_submits', 'feedback'));
$mform->disabledIf('ignoreempty', 'required', 'eq', '1');
$this->values = $mform->addElement('textarea',
'values',
@ -109,6 +112,12 @@ class feedback_multichoicerated_form extends feedback_item_form {
$presentation .= FEEDBACK_MULTICHOICERATED_ADJUST_SEP.'1';
}
$item->presentation = $subtype.FEEDBACK_MULTICHOICERATED_TYPE_SEP.$presentation;
if (!isset($item->hidenoselect)) {
$item->hidenoselect = 1;
}
if (!isset($item->ignoreempty)) {
$item->ignoreempty = 0;
}
return $item;
}
}

View file

@ -19,13 +19,6 @@ require_once($CFG->dirroot.'/mod/feedback/item/feedback_item_class.php');
class feedback_item_numeric extends feedback_item_base {
protected $type = "numeric";
private $commonparams;
private $item_form;
private $item;
public function init() {
}
public function build_editform($item, $feedback, $cm) {
global $DB, $CFG;
@ -80,22 +73,6 @@ class feedback_item_numeric extends feedback_item_base {
$this->item_form = new feedback_numeric_form('edit_item.php', $customdata);
}
//this function only can used after the call of build_editform()
public function show_editform() {
$this->item_form->display();
}
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
}
return false;
}
public function save_item() {
global $DB;
@ -118,9 +95,15 @@ class feedback_item_numeric extends feedback_item_base {
return $DB->get_record('feedback_item', array('id'=>$item->id));
}
//liefert eine Struktur ->name, ->data = array(mit Antworten)
public function get_analysed($item, $groupid = false, $courseid = false) {
/**
* Helper function for collected data, both for analysis page and export to excel
*
* @param stdClass $item the db-object from feedback_item
* @param int $groupid
* @param int $courseid
* @return stdClass
*/
protected function get_analysed($item, $groupid = false, $courseid = false) {
global $DB;
$analysed = new stdClass();
@ -168,8 +151,8 @@ class feedback_item_numeric extends feedback_item_base {
echo '</th></tr>';
foreach ($values->data as $value) {
echo '<tr><td colspan="2" valign="top" align="left">';
echo '-&nbsp;&nbsp;'.$this->format_float($value);
echo '<tr><td colspan="2" class="singlevalue">';
echo $this->format_float($value);
echo '</td></tr>';
}
@ -178,7 +161,7 @@ class feedback_item_numeric extends feedback_item_base {
} else {
$avg = '-';
}
echo '<tr><td align="left" colspan="2"><b>';
echo '<tr><td colspan="2"><b>';
echo get_string('average', 'feedback').': '.$avg;
echo '</b></td></tr>';
}
@ -218,89 +201,6 @@ class feedback_item_numeric extends feedback_item_base {
return $row_offset;
}
/**
* print the item at the edit-page of feedback
*
* @global object
* @param object $item
* @return void
*/
public function print_item_preview($item) {
global $OUTPUT, $DB;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
//get the range
$range_from_to = explode('|', $item->presentation);
//get the min-value
if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
$range_from = floatval($range_from_to[0]);
} else {
$range_from = '-';
}
//get the max-value
if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
$range_to = floatval($range_from_to[1]);
} else {
$range_to = '-';
}
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
echo '<label for="'. $inputname .'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($item->dependitem) {
$params = array('id'=>$item->dependitem);
if ($dependitem = $DB->get_record('feedback_item', $params)) {
echo ' <span class="feedback_depend">';
echo '('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')';
echo '</span>';
}
}
echo '<span class="feedback_item_numinfo">';
switch(true) {
case ($range_from === '-' AND is_numeric($range_to)):
echo ' ('.get_string('maximal', 'feedback').
': '.$this->format_float($range_to).')';
break;
case (is_numeric($range_from) AND $range_to === '-'):
echo ' ('.get_string('minimal', 'feedback').
': '.$this->format_float($range_from).')';
break;
case ($range_from === '-' AND $range_to === '-'):
break;
default:
echo ' ('.$this->format_float($range_from).
' - '.$this->format_float($range_to).')';
break;
}
echo '</span>';
echo '</label>';
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<span class="feedback_item_textfield">';
echo '<input type="text" '.
'id="'.$inputname.'" '.
'name="'.$inputname.'" '.
'size="10" '.
'maxlength="10" '.
'value="" />';
echo '</span>';
echo '</div>';
}
/**
* Prints the float nicely in the localized format
*
@ -318,194 +218,79 @@ class feedback_item_numeric extends feedback_item_base {
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
* Returns human-readable boundaries (min - max)
* @param stdClass $item
* @return string
*/
public function print_item_complete($item, $value = '', $highlightrequire = false) {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
//get the range
$range_from_to = explode('|', $item->presentation);
//get the min-value
if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
$range_from = floatval($range_from_to[0]);
} else {
$range_from = '-';
protected function get_boundaries_for_display($item) {
list($rangefrom, $rangeto) = explode('|', $item->presentation);
if (!isset($rangefrom) || !is_numeric($rangefrom)) {
$rangefrom = null;
}
if (!isset($rangeto) || !is_numeric($rangeto)) {
$rangeto = null;
}
//get the max-value
if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
$range_to = floatval($range_from_to[1]);
} else {
$range_to = '-';
if (is_null($rangefrom) && is_numeric($rangeto)) {
return ' (' . get_string('maximal', 'feedback') .
': ' . $this->format_float($rangeto) . ')';
}
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
echo '<label for="'. $inputname .'">';
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '<span class="feedback_item_numinfo">';
switch(true) {
case ($range_from === '-' AND is_numeric($range_to)):
echo ' ('.get_string('maximal', 'feedback').
': '.$this->format_float($range_to).')';
break;
case (is_numeric($range_from) AND $range_to === '-'):
echo ' ('.get_string('minimal', 'feedback').
': '.$this->format_float($range_from).')';
break;
case ($range_from === '-' AND $range_to === '-'):
break;
default:
echo ' ('.$this->format_float($range_from).
' - '.$this->format_float($range_to).')';
break;
if (is_numeric($rangefrom) && is_null($rangeto)) {
return ' (' . get_string('minimal', 'feedback') .
': ' . $this->format_float($rangefrom) . ')';
}
echo '</span>';
if ($highlightrequire AND (!$this->check_value($value, $item))) {
echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
'</span><br id="id_error_break_'.$inputname.'" class="error" >';
if (is_null($rangefrom) && is_null($rangeto)) {
return '';
}
echo '</label>';
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<span class="feedback_item_textfield">';
echo '<input type="text" '.
'id="'.$inputname.'" '.
'name="'.$item->typ.'_'.$item->id.'" '.
'size="10" '.
'maxlength="10" '.
'value="'.$value.'" />';
echo '</span>';
echo '</div>';
return ' (' . $this->format_float($rangefrom) .
' - ' . $this->format_float($rangeto) . ')';
}
/**
* print the item at the complete-page of feedback
* Returns the postfix to be appended to the display name that is based on other settings
*
* @global object
* @param object $item
* @param string $value
* @return void
* @param stdClass $item
* @return string
*/
public function print_item_show_value($item, $value = '') {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
//get the range
$range_from_to = explode('|', $item->presentation);
//get the min-value
if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
$range_from = floatval($range_from_to[0]);
} else {
$range_from = '-';
}
//get the max-value
if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
$range_to = floatval($range_from_to[1]);
} else {
$range_to = '-';
}
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
switch(true) {
case ($range_from === '-' AND is_numeric($range_to)):
echo ' ('.get_string('maximal', 'feedback').
': '.$this->format_float($range_to).')';
break;
case (is_numeric($range_from) AND $range_to === '-'):
echo ' ('.get_string('minimal', 'feedback').
': '.$this->format_float($range_from).')';
break;
case ($range_from === '-' AND $range_to === '-'):
break;
default:
echo ' ('.$this->format_float($range_from).
' - '.$this->format_float($range_to).')';
break;
}
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo $OUTPUT->box_start('generalbox boxalign'.$align);
if (is_numeric($value)) {
$str_num_value = $this->format_float($value);
} else {
$str_num_value = '&nbsp;';
}
echo $str_num_value;
echo $OUTPUT->box_end();
echo '</div>';
public function get_display_name_postfix($item) {
return html_writer::span($this->get_boundaries_for_display($item), 'boundaries');
}
public function check_value($value, $item) {
$value = unformat_float($value, true);
//if the item is not required, so the check is true if no value is given
if ((!isset($value) OR $value == '') AND $item->required != 1) {
/**
* Adds an input element to the complete form
*
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function complete_form_element($item, $form) {
$name = $this->get_display_name($item);
$inputname = $item->typ . '_' . $item->id;
$form->add_form_element($item,
['text', $inputname, $name],
true,
false
);
$form->set_element_type($inputname, PARAM_NOTAGS);
$tmpvalue = $this->format_float($form->get_item_value($item));
$form->set_element_default($inputname, $tmpvalue);
// Add form validation rule to check for boundaries.
$form->add_validation_rule(function($values, $files) use ($item) {
$inputname = $item->typ . '_' . $item->id;
list($rangefrom, $rangeto) = explode('|', $item->presentation);
if (!isset($values[$inputname]) || trim($values[$inputname]) === '') {
return $item->required ? array($inputname => get_string('required')) : true;
}
$value = unformat_float($values[$inputname], true);
if ($value === false) {
return array($inputname => get_string('invalidnum', 'error'));
}
if ((is_numeric($rangefrom) && $value < floatval($rangefrom)) ||
(is_numeric($rangeto) && $value > floatval($rangeto))) {
return array($inputname => get_string('numberoutofrange', 'feedback'));
}
return true;
}
if (!is_numeric($value)) {
return false;
}
$range_from_to = explode('|', $item->presentation);
if (isset($range_from_to[0]) AND is_numeric($range_from_to[0])) {
$range_from = floatval($range_from_to[0]);
} else {
$range_from = '-';
}
if (isset($range_from_to[1]) AND is_numeric($range_from_to[1])) {
$range_to = floatval($range_from_to[1]);
} else {
$range_to = '-';
}
switch(true) {
case ($range_from === '-' AND is_numeric($range_to)):
if (floatval($value) <= $range_to) {
return true;
}
break;
case (is_numeric($range_from) AND $range_to === '-'):
if (floatval($value) >= $range_from) {
return true;
}
break;
case ($range_from === '-' AND $range_to === '-'):
return true;
break;
default:
if (floatval($value) >= $range_from AND floatval($value) <= $range_to) {
return true;
}
break;
}
return false;
});
}
public function create_value($data) {
@ -518,64 +303,4 @@ class feedback_item_numeric extends feedback_item_base {
}
return $data;
}
//compares the dbvalue with the dependvalue
//dbvalue is the number put in by the user
//dependvalue is the value that is compared
public function compare_value($item, $dbvalue, $dependvalue) {
if ($dbvalue == $dependvalue) {
return true;
}
return false;
}
public function get_presentation($data) {
$num1 = unformat_float($data->numericrangefrom, true);
if (is_numeric($num1)) {
$num1 = floatval($num1);
} else {
$num1 = '-';
}
$num2 = unformat_float($data->numericrangeto, true);
if (is_numeric($num2)) {
$num2 = floatval($num2);
} else {
$num2 = '-';
}
if ($num1 === '-' OR $num2 === '-') {
return $num1 . '|'. $num2;
}
if ($num1 > $num2) {
return $num2 . '|'. $num1;
} else {
return $num1 . '|'. $num2;
}
}
public function get_hasvalue() {
return 1;
}
public function can_switch_require() {
return true;
}
public function value_type() {
return PARAM_TEXT;
}
public function clean_input_value($value) {
$value = unformat_float($value, true);
if (!is_numeric($value)) {
if ($value == '') {
return null; //an empty string should be null
} else {
return clean_param($value, PARAM_TEXT); //we have to know the value if it is wrong
}
}
return clean_param($value, PARAM_FLOAT);
}
}

View file

@ -19,13 +19,6 @@ require_once($CFG->dirroot.'/mod/feedback/item/feedback_item_class.php');
class feedback_item_textarea extends feedback_item_base {
protected $type = "textarea";
private $commonparams;
private $item_form;
private $item;
public function init() {
}
public function build_editform($item, $feedback, $cm) {
global $DB, $CFG;
@ -80,22 +73,6 @@ class feedback_item_textarea extends feedback_item_base {
$this->item_form = new feedback_textarea_form('edit_item.php', $customdata);
}
//this function only can used after the call of build_editform()
public function show_editform() {
$this->item_form->display();
}
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
}
return false;
}
public function save_item() {
global $DB;
@ -118,9 +95,15 @@ class feedback_item_textarea extends feedback_item_base {
return $DB->get_record('feedback_item', array('id'=>$item->id));
}
//liefert eine Struktur ->name, ->data = array(mit Antworten)
public function get_analysed($item, $groupid = false, $courseid = false) {
/**
* Helper function for collected data for exporting to excel
*
* @param stdClass $item the db-object from feedback_item
* @param int $groupid
* @param int $courseid
* @return stdClass
*/
protected function get_analysed($item, $groupid = false, $courseid = false) {
global $DB;
$analysed_val = new stdClass();
@ -158,9 +141,9 @@ class feedback_item_textarea extends feedback_item_base {
echo format_text($item->name, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</th></tr>';
foreach ($values as $value) {
echo '<tr>';
echo '<td colspan="2" valign="top" align="left">';
echo '-&nbsp;&nbsp;';
$class = strlen(trim($value->value)) ? '' : ' class="isempty"';
echo '<tr'.$class.'>';
echo '<td colspan="2" class="singlevalue">';
echo str_replace("\n", '<br />', $value->value);
echo '</td>';
echo '</tr>';
@ -193,168 +176,21 @@ class feedback_item_textarea extends feedback_item_base {
}
/**
* print the item at the edit-page of feedback
* Adds an input element to the complete form
*
* @global object
* @param object $item
* @return void
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function print_item_preview($item) {
global $OUTPUT, $DB;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$presentation = explode ("|", $item->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
public function complete_form_element($item, $form) {
$name = $this->get_display_name($item);
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
echo '<label for="'. $inputname .'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($item->dependitem) {
if ($dependitem = $DB->get_record('feedback_item', array('id'=>$item->dependitem))) {
echo ' <span class="feedback_depend">';
echo '('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')';
echo '</span>';
}
}
echo '</label>';
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<span class="feedback_item_textarea">';
echo '<textarea id="'.$inputname.'" '.
'name="'.$inputname.'" '.
'cols="'.$presentation[0].'" '.
'rows="'.$presentation[1].'">';
echo '</textarea>';
echo '</span>';
echo '</div>';
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
*/
public function print_item_complete($item, $value = '', $highlightrequire = false) {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$presentation = explode ("|", $item->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark :'';
//print the question and label
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
echo '<label for="'. $inputname .'">';
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($highlightrequire AND $item->required AND strval($value) == '') {
echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
'</span><br id="id_error_break_'.$inputname.'" class="error" >';
}
echo '</label>';
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<span class="feedback_item_textarea">';
echo '<textarea id="'.$inputname.'" '.
'name="'.$inputname.'" '.
'cols="'.$presentation[0].'" '.
'rows="'.$presentation[1].'">';
echo $value;
echo '</textarea>';
echo '</span>';
echo '</div>';
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @return void
*/
public function print_item_show_value($item, $value = '') {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$presentation = explode ("|", $item->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
//print the presentation
echo $OUTPUT->box_start('generalbox boxalign'.$align);
echo $value ? str_replace("\n", '<br />', $value) : '&nbsp;';
echo $OUTPUT->box_end();
}
public function check_value($value, $item) {
//if the item is not required, so the check is true if no value is given
if ((!isset($value) OR $value == '') AND $item->required != 1) {
return true;
}
if ($value == "") {
return false;
}
return true;
list($cols, $rows) = explode ("|", $item->presentation);
$form->add_form_element($item,
['textarea', $inputname, $name, array('rows' => $rows, 'cols' => $cols)]);
$form->set_element_type($inputname, PARAM_NOTAGS);
}
public function create_value($data) {
$data = s($data);
return $data;
}
//compares the dbvalue with the dependvalue
//dbvalue is the value put in by the user
//dependvalue is the value that is compared
public function compare_value($item, $dbvalue, $dependvalue) {
if ($dbvalue == $dependvalue) {
return true;
}
return false;
}
public function get_presentation($data) {
return $data->itemwidth.'|'.$data->itemheight;
}
public function get_hasvalue() {
return 1;
}
public function can_switch_require() {
return true;
}
public function value_type() {
return PARAM_RAW;
}
public function clean_input_value($value) {
return s($value);
return s($data);
}
}

View file

@ -19,13 +19,6 @@ require_once($CFG->dirroot.'/mod/feedback/item/feedback_item_class.php');
class feedback_item_textfield extends feedback_item_base {
protected $type = "textfield";
private $commonparams;
private $item_form;
private $item;
public function init() {
}
public function build_editform($item, $feedback, $cm) {
global $DB, $CFG;
@ -77,22 +70,6 @@ class feedback_item_textfield extends feedback_item_base {
$this->item_form = new feedback_textfield_form('edit_item.php', $customdata);
}
//this function only can used after the call of build_editform()
public function show_editform() {
$this->item_form->display();
}
public function is_cancelled() {
return $this->item_form->is_cancelled();
}
public function get_data() {
if ($this->item = $this->item_form->get_data()) {
return true;
}
return false;
}
public function save_item() {
global $DB;
@ -116,9 +93,15 @@ class feedback_item_textfield extends feedback_item_base {
}
//liefert eine Struktur ->name, ->data = array(mit Antworten)
public function get_analysed($item, $groupid = false, $courseid = false) {
global $DB;
/**
* Helper function for collected data for exporting to excel
*
* @param stdClass $item the db-object from feedback_item
* @param int $groupid
* @param int $courseid
* @return stdClass
*/
protected function get_analysed($item, $groupid = false, $courseid = false) {
$analysed_val = new stdClass();
$analysed_val->data = null;
@ -151,11 +134,12 @@ class feedback_item_textfield extends feedback_item_base {
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo $this->get_display_name($item);
echo '</th></tr>';
foreach ($values as $value) {
echo '<tr><td colspan="2" valign="top" align="left">';
echo '-&nbsp;&nbsp;'.str_replace("\n", '<br />', $value->value);
$class = strlen(trim($value->value)) ? '' : ' class="isempty"';
echo '<tr'.$class.'><td colspan="2" class="singlevalue">';
echo str_replace("\n", '<br />', $value->value);
echo '</td></tr>';
}
}
@ -184,166 +168,28 @@ class feedback_item_textfield extends feedback_item_base {
}
/**
* print the item at the edit-page of feedback
* Adds an input element to the complete form
*
* @global object
* @param object $item
* @return void
* @param stdClass $item
* @param mod_feedback_complete_form $form
*/
public function print_item_preview($item) {
global $OUTPUT, $DB;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$presentation = explode ("|", $item->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
public function complete_form_element($item, $form) {
$name = $this->get_display_name($item);
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
echo '<label for="'. $inputname .'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($item->dependitem) {
if ($dependitem = $DB->get_record('feedback_item', array('id'=>$item->dependitem))) {
echo ' <span class="feedback_depend">';
echo '('.format_string($dependitem->label).'-&gt;'.$item->dependvalue.')';
echo '</span>';
}
}
echo '</label>';
echo '</div>';
list($size, $maxlength) = explode ("|", $item->presentation);
$form->add_form_element($item,
['text', $inputname, $name, ['maxlength' => $maxlength, 'size' => $size]]);
$form->set_element_type($inputname, PARAM_NOTAGS);
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<span class="feedback_item_textfield">';
echo '<input type="text" '.
'id="'.$inputname.'" '.
'name="'.$inputname.'" '.
'size="'.$presentation[0].'" '.
'maxlength="'.$presentation[1].'" '.
'value="" />';
echo '</span>';
echo '</div>';
$form->add_element_rule($inputname, get_string('maximumchars', '', $maxlength), 'maxlength', $maxlength, 'client');
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @param bool $highlightrequire
* @return void
* Converts the value from complete_form data to the string value that is stored in the db.
* @param mixed $value element from mod_feedback_complete_form::get_data() with the name $item->typ.'_'.$item->id
* @return string
*/
public function print_item_complete($item, $value = '', $highlightrequire = false) {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$presentation = explode ("|", $item->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
$inputname = $item->typ . '_' . $item->id;
echo '<div class="feedback_item_label_'.$align.'">';
echo '<label for="'. $inputname .'">';
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
if ($highlightrequire AND $item->required AND strval($value) == '') {
echo '<br class="error"><span id="id_error_'.$inputname.'" class="error"> '.get_string('err_required', 'form').
'</span><br id="id_error_break_'.$inputname.'" class="error" >';
}
echo '</label>';
echo '</div>';
//print the presentation
echo '<div class="feedback_item_presentation_'.$align.'">';
echo '<span class="feedback_item_textfield">';
echo '<input type="text" '.
'id="'.$inputname.'" '.
'name="'.$inputname.'" '.
'size="'.$presentation[0].'" '.
'maxlength="'.$presentation[1].'" '.
'value="'.$value.'" />';
echo '</span>';
echo '</div>';
}
/**
* print the item at the complete-page of feedback
*
* @global object
* @param object $item
* @param string $value
* @return void
*/
public function print_item_show_value($item, $value = '') {
global $OUTPUT;
$align = right_to_left() ? 'right' : 'left';
$strrequiredmark = '<img class="req" title="'.get_string('requiredelement', 'form').'" alt="'.
get_string('requiredelement', 'form').'" src="'.$OUTPUT->pix_url('req') .'" />';
$presentation = explode ("|", $item->presentation);
$requiredmark = ($item->required == 1) ? $strrequiredmark : '';
//print the question and label
echo '<div class="feedback_item_label_'.$align.'">';
if (strval($item->label) !== '') {
echo '('. format_string($item->label).') ';
}
echo format_text($item->name . $requiredmark, FORMAT_HTML, array('noclean' => true, 'para' => false));
echo '</div>';
echo $OUTPUT->box_start('generalbox boxalign'.$align);
echo $value ? $value : '&nbsp;';
echo $OUTPUT->box_end();
}
public function check_value($value, $item) {
//if the item is not required, so the check is true if no value is given
if ((!isset($value) OR $value == '') AND $item->required != 1) {
return true;
}
if ($value == "") {
return false;
}
return true;
}
public function create_value($data) {
$data = s($data);
return $data;
}
//compares the dbvalue with the dependvalue
//dbvalue is the value put in by the user
//dependvalue is the value that is compared
public function compare_value($item, $dbvalue, $dependvalue) {
if ($dbvalue == $dependvalue) {
return true;
}
return false;
}
public function get_presentation($data) {
return $data->itemsize . '|'. $data->itemmaxlength;
}
public function get_hasvalue() {
return 1;
}
public function can_switch_require() {
return true;
}
public function value_type() {
return PARAM_RAW;
}
public function clean_input_value($value) {
public function create_value($value) {
return s($value);
}
}

View file

@ -1,2 +1,28 @@
cancel_moving,mod_feedback
cannotunmap,mod_feedback
cannotmapfeedback,mod_feedback
completed,mod_feedback
line_values,mod_feedback
mapcourses_help,mod_feedback
max_args_exceeded,mod_feedback
movedown_item,mod_feedback
move_here,mod_feedback
moveup_item,mod_feedback
notavailable,mod_feedback
not_completed_yet,mod_feedback
parameters_missing,mod_feedback
picture,mod_feedback
picture_file_list,mod_feedback
picture_values,mod_feedback
preview,mod_feedback
preview_help,mod_feedback
radiorated,mod_feedback
radiobutton,mod_feedback
radiobutton_rated,mod_feedback
relateditemsdeleted,mod_feedback
separator_decimal,mod_feedback
separator_thousand,mod_feedback
saving_failed_because_missing_or_false_values,mod_feedback
switch_group,mod_feedback
viewcompleted,mod_feedback
viewcompleted_help,mod_feedback

View file

@ -37,11 +37,8 @@ $string['autonumbering'] = 'Auto number questions';
$string['autonumbering_help'] = 'Enables or disables automated numbers for each question';
$string['average'] = 'Average';
$string['bold'] = 'Bold';
$string['cancel_moving'] = 'Cancel moving';
$string['cannotaccess'] = 'You can only access this feedback from a course';
$string['cannotmapfeedback'] = 'Database problem, unable to map feedback to course';
$string['cannotsavetempl'] = 'saving templates is not allowed';
$string['cannotunmap'] = 'Database problem, unable to unmap';
$string['captcha'] = 'Captcha';
$string['captchanotset'] = 'Captcha hasn\'t been set.';
$string['completed_feedbacks'] = 'Submitted answers';
@ -59,6 +56,7 @@ $string['creating_templates'] = 'Save these questions as a new template';
$string['delete_entry'] = 'Delete entry';
$string['delete_item'] = 'Delete question';
$string['delete_old_items'] = 'Delete old items';
$string['delete_pagebreak'] = 'Delete page break';
$string['delete_template'] = 'Delete template';
$string['delete_templates'] = 'Delete template...';
$string['depending'] = 'Dependencies';
@ -131,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';
@ -145,7 +144,6 @@ $string['item_label'] = 'Label';
$string['item_name'] = 'Question';
$string['label'] = 'Label';
$string['labelcontents'] = 'Contents';
$string['line_values'] = 'Rating';
$string['mapcourseinfo'] = 'This is a site-wide feedback that is available to all courses using the feedback block. You can however limit the courses to which it will appear by mapping them. Search the course and map it to this feedback.';
$string['mapcoursenone'] = 'No courses mapped. Feedback available to all courses';
$string['mapcourse'] = 'Map feedback to courses';
@ -154,7 +152,6 @@ and will appear in all courses using the feedback block. You can force the feedb
$string['mapcourses'] = 'Map feedback to courses';
$string['mappedcourses'] = 'Mapped courses';
$string['mappingchanged'] = 'Course mapping has been changed';
$string['max_args_exceeded'] = 'Max 6 arguments can be handled, too many arguments for';
$string['minimal'] = 'minimum';
$string['maximal'] = 'maximum';
$string['messageprovider:message'] = 'Feedback reminder';
@ -173,10 +170,7 @@ Feedback activities may be used
* For anti-bullying surveys in which students can report incidents anonymously';
$string['modulename_link'] = 'mod/feedback/view';
$string['modulenameplural'] = 'Feedback';
$string['movedown_item'] = 'Move this question down';
$string['move_here'] = 'Move here';
$string['move_item'] = 'Move this question';
$string['moveup_item'] = 'Move this question up';
$string['multichoice'] = 'Multiple choice';
$string['multichoicerated'] = 'Multiple choice (rated)';
$string['multichoicetype'] = 'Multiple choice type';
@ -193,11 +187,10 @@ $string['no_items_available_yet'] = 'No questions have been set up yet';
$string['non_anonymous'] = 'User\'s name will be logged and shown with answers';
$string['non_anonymous_entries'] = 'Non anonymous entries ({$a})';
$string['non_respondents_students'] = 'Non respondents students ({$a})';
$string['notavailable'] = 'this feedback is not available';
$string['not_completed_yet'] = 'Not completed yet';
$string['not_started'] = 'not started';
$string['no_templates_available_yet'] = 'No templates available yet';
$string['not_selected'] = 'Not selected';
$string['numberoutofrange'] = 'Number out of range';
$string['numeric'] = 'Numeric answer';
$string['numeric_range_from'] = 'Range from';
$string['numeric_range_to'] = 'Range to';
@ -210,27 +203,17 @@ $string['page'] = 'Page';
$string['page-mod-feedback-x'] = 'Any feedback module page';
$string['page_after_submit'] = 'Completion message';
$string['pagebreak'] = 'Page break';
$string['parameters_missing'] = 'Parameters missing from';
$string['picture'] = 'Picture';
$string['picture_file_list'] = 'List of pictures';
$string['picture_values'] = 'Choose one or more<br />picture files from the list:';
$string['pluginadministration'] = 'Feedback administration';
$string['pluginname'] = 'Feedback';
$string['position'] = 'Position';
$string['preview'] = 'Preview';
$string['preview_help'] = 'In the preview you can change the order of questions.';
$string['previous_page'] = 'Previous page';
$string['public'] = 'Public';
$string['question'] = 'Question';
$string['questionandsubmission'] = 'Question and submission settings';
$string['questions'] = 'Questions';
$string['radio'] = 'Multiple choice - single answer';
$string['radiobutton'] = 'Multiple choice - single answer allowed (radio buttons)';
$string['radiobutton_rated'] = 'Radiobutton (rated)';
$string['radiorated'] = 'Radiobutton (rated)';
$string['radio_values'] = 'Responses';
$string['ready_feedbacks'] = 'Ready feedbacks';
$string['relateditemsdeleted'] = 'All your user\'s responses for this question will also be deleted';
$string['required'] = 'Required';
$string['resetting_data'] = 'Reset feedback responses';
$string['resetting_feedbacks'] = 'Resetting feedbacks';
@ -242,7 +225,6 @@ $string['save_as_new_template'] = 'Save as new template';
$string['save_entries'] = 'Submit your answers';
$string['save_item'] = 'Save question';
$string['saving_failed'] = 'Saving failed';
$string['saving_failed_because_missing_or_false_values'] = 'Saving failed because missing or false values';
$string['search:activity'] = 'Feedback activities';
$string['search_course'] = 'Search course';
$string['searchcourses'] = 'Search courses';
@ -250,8 +232,6 @@ $string['searchcourses_help'] = 'Search for the code or name of the course(s) th
$string['selected_dump'] = 'Selected indexes of $SESSION variable are dumped below:';
$string['send'] = 'send';
$string['send_message'] = 'send message';
$string['separator_decimal'] = '.';
$string['separator_thousand'] = ',';
$string['show_all'] = 'Show all';
$string['show_analysepage_after_submit'] = 'Show analysis page';
$string['show_entries'] = 'Show responses';
@ -263,9 +243,8 @@ $string['start'] = 'Start';
$string['started'] = 'started';
$string['stop'] = 'End';
$string['subject'] = 'Subject';
$string['switch_group'] = 'Switch group';
$string['switch_item_to_not_required'] = 'switch to: answer not required';
$string['switch_item_to_required'] = 'switch to: answer required';
$string['switch_item_to_not_required'] = 'Set as not required';
$string['switch_item_to_required'] = 'Set as required';
$string['template'] = 'Template';
$string['templates'] = 'Templates';
$string['template_deleted'] = 'Template deleted';
@ -282,15 +261,39 @@ $string['typemissing'] = 'missing value "type"';
$string['update_item'] = 'Save changes to question';
$string['url_for_continue'] = 'Link to next activity';
$string['url_for_continue_help'] = 'After submitting the feedback, a continue button is displayed, which links to the course page. Alternatively, it may link to the next activity if the URL of the activity is entered here.';
$string['use_one_line_for_each_value'] = '<br />Use one line for each answer!';
$string['use_one_line_for_each_value'] = 'Use one line for each answer!';
$string['use_this_template'] = 'Use this template';
$string['using_templates'] = 'Use a template';
$string['vertical'] = 'vertical';
$string['viewcompleted'] = 'completed feedbacks';
$string['viewcompleted_help'] = 'You may view completed feedback forms, searchable by course and/or by question.
Feedback responses may be exported to Excel.';
// Deprecated since Moodle 3.0.
$string['completed'] = 'completed';
// Deprecated since Moodle 3.1.
$string['cannotmapfeedback'] = 'Database problem, unable to map feedback to course';
$string['line_values'] = 'Rating';
$string['mapcourses_help'] = 'Once you have selected the relevant course(s) from your search,
you can associate them with this feedback using map course(s). Multiple courses may be selected by holding down the Apple or Ctrl key whilst clicking on the course names. A course may be disassociated from a feedback at any time.';
$string['max_args_exceeded'] = 'Max 6 arguments can be handled, too many arguments for';
$string['cancel_moving'] = 'Cancel moving';
$string['movedown_item'] = 'Move this question down';
$string['move_here'] = 'Move here';
$string['moveup_item'] = 'Move this question up';
$string['not_completed_yet'] = 'Not completed yet';
$string['notavailable'] = 'this feedback is not available';
$string['saving_failed_because_missing_or_false_values'] = 'Saving failed because missing or false values';
$string['cannotunmap'] = 'Database problem, unable to unmap';
$string['viewcompleted'] = 'completed feedbacks';
$string['viewcompleted_help'] = 'You may view completed feedback forms, searchable by course and/or by question.
Feedback responses may be exported to Excel.';
$string['parameters_missing'] = 'Parameters missing from';
$string['picture'] = 'Picture';
$string['picture_file_list'] = 'List of pictures';
$string['picture_values'] = 'Choose one or more<br />picture files from the list:';
$string['preview'] = 'Preview';
$string['preview_help'] = 'In the preview you can change the order of questions.';
$string['switch_group'] = 'Switch group';
$string['separator_decimal'] = '.';
$string['separator_thousand'] = ',';
$string['relateditemsdeleted'] = 'All your user\'s responses for this question will also be deleted';
$string['radiorated'] = 'Radiobutton (rated)';
$string['radiobutton'] = 'Multiple choice - single answer allowed (radio buttons)';
$string['radiobutton_rated'] = 'Radiobutton (rated)';

View file

@ -301,9 +301,6 @@ function feedback_delete_instance($id) {
}
}
//deleting the referenced tracking data
$DB->delete_records('feedback_tracking', array('feedback'=>$id));
//deleting the completeds
$DB->delete_records("feedback_completed", array("feedback"=>$id));
@ -525,7 +522,7 @@ function feedback_get_completion_state($course, $cm, $userid, $type) {
// If completion option is enabled, evaluate it and return true/false
if ($feedback->completionsubmit) {
$params = array('userid'=>$userid, 'feedback'=>$feedback->id);
return $DB->record_exists('feedback_tracking', $params);
return $DB->record_exists('feedback_completed', $params);
} else {
// Completion option is not enabled so just return $type
return $type;
@ -645,7 +642,7 @@ function feedback_reset_userdata($data) {
//reset the selected feedbacks
foreach ($resetfeedbacks as $id) {
$feedback = $DB->get_record('feedback', array('id'=>$id));
feedback_delete_all_completeds($id);
feedback_delete_all_completeds($feedback);
$status[] = array('component'=>$componentstr.':'.$feedback->name,
'item'=>get_string('resetting_data', 'feedback'),
'error'=>false);
@ -826,11 +823,14 @@ function feedback_delete_course_module($id) {
/**
* returns the context-id related to the given coursemodule-id
*
* @deprecated since 3.1
* @staticvar object $context
* @param int $cmid the coursemodule-id
* @return object $context
*/
function feedback_get_context($cmid) {
debugging('Function feedback_get_context() is deprecated because it was not used.',
DEBUG_DEVELOPER);
static $context;
if (isset($context)) {
@ -1024,31 +1024,6 @@ function feedback_get_complete_users($cm,
return $DB->get_records_sql($sql, $params, $startpage, $pagecount);
}
/**
* If there are any new responses to the anonymous feedback, re-shuffle all
* responses and assign response number to each of them.
*
* @param stdClass $feedback
*/
function feedback_shuffle_anonym_responses($feedback) {
global $DB;
$params = array('feedback' => $feedback->id,
'random_response' => 0,
'anonymous_response' => FEEDBACK_ANONYMOUS_YES);
if ($DB->count_records('feedback_completed', $params, 'random_response')) {
// Get all of the anonymous records, go through them and assign a response id.
unset($params['random_response']);
$feedbackcompleteds = $DB->get_records('feedback_completed', $params, 'id');
shuffle($feedbackcompleteds);
$num = 1;
foreach ($feedbackcompleteds as $compl) {
$compl->random_response = $num++;
$DB->update_record('feedback_completed', $compl);
}
}
}
/**
* get users which have the viewreports-capability
*
@ -1277,8 +1252,6 @@ function feedback_items_from_template($feedback, $templateid, $deleteold = false
foreach ($feedbackitems as $item) {
feedback_delete_item($item->id, false);
}
//delete tracking-data
$DB->delete_records('feedback_tracking', array('feedback'=>$feedback->id));
$params = array('feedback'=>$feedback->id);
if ($completeds = $DB->get_records('feedback_completed', $params)) {
@ -1386,9 +1359,8 @@ function feedback_get_template_list($course, $onlyownorpublic = '') {
/**
* load the lib.php from item-plugin-dir and returns the instance of the itemclass
*
* @global object
* @param object $item
* @return object the instanz of itemclass
* @param string $typ
* @return feedback_item_base the instance of itemclass
*/
function feedback_get_item_class($typ) {
global $CFG;
@ -1485,11 +1457,13 @@ function feedback_get_depend_candidates_for_item($feedback, $item) {
/**
* creates a new item-record
*
* @global object
* @deprecated since 3.1
* @param object $data the data from edit_item_form
* @return int the new itemid
*/
function feedback_create_item($data) {
debugging('Function feedback_create_item() is deprecated because it was not used.',
DEBUG_DEVELOPER);
global $DB;
$item = new stdClass();
@ -1799,57 +1773,43 @@ function feedback_move_item($moveitem, $pos) {
* prints the given item as a preview.
* each item-class has an own print_item_preview function implemented.
*
* @deprecated since Moodle 3.1
* @global object
* @param object $item the item what we want to print out
* @return void
*/
function feedback_print_item_preview($item) {
global $CFG;
if ($item->typ == 'pagebreak') {
return;
}
//get the instance of the item-class
$itemobj = feedback_get_item_class($item->typ);
$itemobj->print_item_preview($item);
debugging('Function feedback_print_item_preview() is deprecated and does nothing. '
. 'Items must implement complete_form_element()', DEBUG_DEVELOPER);
}
/**
* prints the given item in the completion form.
* each item-class has an own print_item_complete function implemented.
*
* @deprecated since Moodle 3.1
* @param object $item the item what we want to print out
* @param mixed $value the value
* @param boolean $highlightrequire if this set true and the value are false on completing so the item will be highlighted
* @return void
*/
function feedback_print_item_complete($item, $value = false, $highlightrequire = false) {
global $CFG;
if ($item->typ == 'pagebreak') {
return;
}
//get the instance of the item-class
$itemobj = feedback_get_item_class($item->typ);
$itemobj->print_item_complete($item, $value, $highlightrequire);
debugging('Function feedback_print_item_complete() is deprecated and does nothing. '
. 'Items must implement complete_form_element()', DEBUG_DEVELOPER);
}
/**
* prints the given item in the show entries page.
* each item-class has an own print_item_show_value function implemented.
*
* @deprecated since Moodle 3.1
* @param object $item the item what we want to print out
* @param mixed $value
* @return void
*/
function feedback_print_item_show_value($item, $value = false) {
global $CFG;
if ($item->typ == 'pagebreak') {
return;
}
//get the instance of the item-class
$itemobj = feedback_get_item_class($item->typ);
$itemobj->print_item_show_value($item, $value);
debugging('Function feedback_print_item_show_value() is deprecated and does nothing. '
. 'Items must implement complete_form_element()', DEBUG_DEVELOPER);
}
/**
@ -1862,6 +1822,8 @@ function feedback_print_item_show_value($item, $value = false) {
*/
function feedback_set_tmp_values($feedbackcompleted) {
global $DB;
debugging('Function feedback_set_tmp_values() is deprecated and since it is '
. 'no longer used in mod_feedback', DEBUG_DEVELOPER);
//first we create a completedtmp
$tmpcpl = new stdClass();
@ -1889,10 +1851,9 @@ function feedback_set_tmp_values($feedbackcompleted) {
* @global object
* @param object $feedbackcompletedtmp the temporary completed
* @param object $feedbackcompleted the target completed
* @param int $userid
* @return int the id of the completed
*/
function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted, $userid) {
function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted) {
global $DB;
$tmpcplid = $feedbackcompletedtmp->id;
@ -1905,23 +1866,22 @@ function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted, $us
} else {
$feedbackcompleted = clone($feedbackcompletedtmp);
$feedbackcompleted->id = '';
$feedbackcompleted->userid = $userid;
$feedbackcompleted->timemodified = time();
$feedbackcompleted->id = $DB->insert_record('feedback_completed', $feedbackcompleted);
}
$allitems = $DB->get_records('feedback_item', array('feedback' => $feedbackcompleted->feedback));
//save all the new values from feedback_valuetmp
//get all values of tmp-completed
$params = array('completed'=>$feedbackcompletedtmp->id);
if (!$values = $DB->get_records('feedback_valuetmp', $params)) {
return false;
}
$values = $DB->get_records('feedback_valuetmp', $params);
foreach ($values as $value) {
//check if there are depend items
$item = $DB->get_record('feedback_item', array('id'=>$value->item));
if ($item->dependitem > 0) {
if ($item->dependitem > 0 && isset($allitems[$item->dependitem])) {
$check = feedback_compare_item_value($tmpcplid,
$item->dependitem,
$allitems[$item->dependitem],
$item->dependvalue,
true);
} else {
@ -1939,20 +1899,7 @@ function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted, $us
// Trigger event for the delete action we performed.
$cm = get_coursemodule_from_instance('feedback', $feedbackcompleted->feedback);
$event = \mod_feedback\event\response_submitted::create(array(
'relateduserid' => $userid,
'objectid' => $feedbackcompleted->id,
'context' => context_module::instance($cm->id),
'anonymous' => ($feedbackcompleted->anonymous_response == FEEDBACK_ANONYMOUS_YES),
'other' => array(
'cmid' => $cm->id,
'instanceid' => $feedbackcompleted->feedback,
'anonymous' => $feedbackcompleted->anonymous_response // Deprecated.
)
));
$event->add_record_snapshot('feedback_completed', $feedbackcompleted);
$event = \mod_feedback\event\response_submitted::create_from_record($feedbackcompleted, $cm);
$event->trigger();
return $feedbackcompleted->id;
@ -1961,13 +1908,17 @@ function feedback_save_tmp_values($feedbackcompletedtmp, $feedbackcompleted, $us
/**
* deletes the given temporary completed and all related temporary values
*
* @global object
* @deprecated since Moodle 3.1
*
* @param int $tmpcplid
* @return void
*/
function feedback_delete_completedtmp($tmpcplid) {
global $DB;
debugging('Function feedback_delete_completedtmp() is deprecated because it is no longer used',
DEBUG_DEVELOPER);
$DB->delete_records('feedback_valuetmp', array('completed'=>$tmpcplid));
$DB->delete_records('feedback_completedtmp', array('id'=>$tmpcplid));
}
@ -2047,6 +1998,7 @@ function feedback_get_last_break_position($feedbackid) {
/**
* this returns the position where the user can continue the completing.
*
* @deprecated since Moodle 3.1
* @global object
* @global object
* @global object
@ -2058,6 +2010,9 @@ function feedback_get_last_break_position($feedbackid) {
function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid = false) {
global $CFG, $USER, $DB;
debugging('Function feedback_get_page_to_continue() is deprecated and since it is '
. 'no longer used in mod_feedback', DEBUG_DEVELOPER);
//is there any break?
if (!$allbreaks = feedback_get_all_break_positions($feedbackid)) {
@ -2112,12 +2067,13 @@ function feedback_get_page_to_continue($feedbackid, $courseid = false, $guestid
/**
* cleans the userinput while submitting the form.
*
* @deprecated since Moodle 3.1
* @param mixed $value
* @return mixed
*/
function feedback_clean_input_value($item, $value) {
$itemobj = feedback_get_item_class($item->typ);
return $itemobj->clean_input_value($value);
debugging('Function feedback_clean_input_value() is deprecated and does nothing. '
. 'Items must implement complete_form_element()', DEBUG_DEVELOPER);
}
/**
@ -2126,16 +2082,20 @@ function feedback_clean_input_value($item, $value) {
* if there is already a completed and the userid is set so the values are updated.
* on all other things new value records will be created.
*
* @global object
* @param int $userid
* @deprecated since Moodle 3.1
*
* @param int $usrid
* @param boolean $tmp
* @return mixed false on error or the completeid
*/
function feedback_save_values($usrid, $tmp = false) {
global $DB;
$completedid = optional_param('completedid', 0, PARAM_INT);
debugging('Function feedback_save_values() was deprecated because it did not have '.
'enough arguments, was not suitable for non-temporary table and was taking '.
'data directly from input', DEBUG_DEVELOPER);
$completedid = optional_param('completedid', 0, PARAM_INT);
$tmpstr = $tmp ? 'tmp' : '';
$time = time();
$timemodified = mktime(0, 0, 0, date('m', $time), date('d', $time), date('Y', $time));
@ -2155,13 +2115,18 @@ function feedback_save_values($usrid, $tmp = false) {
/**
* this saves the values from anonymous user such as guest on the main-site
*
* @global object
* @deprecated since Moodle 3.1
*
* @param string $guestid the unique guestidentifier
* @return mixed false on error or the completeid
*/
function feedback_save_guest_values($guestid) {
global $DB;
debugging('Function feedback_save_guest_values() was deprecated because it did not have '.
'enough arguments, was not suitable for non-temporary table and was taking '.
'data directly from input', DEBUG_DEVELOPER);
$completedid = optional_param('completedid', false, PARAM_INT);
$timemodified = time();
@ -2196,23 +2161,21 @@ function feedback_get_item_value($completedid, $itemid, $tmp = false) {
* this is used if a depend item is set.
* the value can come as temporary or as permanently value. the deciding is done by $tmp.
*
* @global object
* @global object
* @param int $completeid
* @param int $itemid
* @param int $completedid
* @param stdClass|int $item
* @param mixed $dependvalue
* @param boolean $tmp
* @param bool $tmp
* @return bool
*/
function feedback_compare_item_value($completedid, $itemid, $dependvalue, $tmp = false) {
global $DB, $CFG;
function feedback_compare_item_value($completedid, $item, $dependvalue, $tmp = false) {
global $DB;
$dbvalue = feedback_get_item_value($completedid, $itemid, $tmp);
if (is_int($item)) {
$item = $DB->get_record('feedback_item', array('id' => $item));
}
//get the class of the given item-typ
$item = $DB->get_record('feedback_item', array('id'=>$itemid));
$dbvalue = feedback_get_item_value($completedid, $item->id, $tmp);
//get the instance of the item-class
$itemobj = feedback_get_item_class($item->typ);
return $itemobj->compare_value($item, $dbvalue, $dependvalue); //true or false
}
@ -2229,66 +2192,8 @@ function feedback_compare_item_value($completedid, $itemid, $dependvalue, $tmp =
* @return boolean
*/
function feedback_check_values($firstitem, $lastitem) {
global $DB, $CFG;
$feedbackid = optional_param('feedbackid', 0, PARAM_INT);
//get all items between the first- and lastitem
$select = "feedback = ?
AND position >= ?
AND position <= ?
AND hasvalue = 1";
$params = array($feedbackid, $firstitem, $lastitem);
if (!$feedbackitems = $DB->get_records_select('feedback_item', $select, $params)) {
//if no values are given so no values can be wrong ;-)
return true;
}
foreach ($feedbackitems as $item) {
//get the instance of the item-class
$itemobj = feedback_get_item_class($item->typ);
//the name of the input field of the completeform is given in a special form:
//<item-typ>_<item-id> eg. numeric_234
//this is the key to get the value for the correct item
$formvalname = $item->typ . '_' . $item->id;
if ($itemobj->value_is_array()) {
//get the raw value here. It is cleaned after that by the object itself
$value = optional_param_array($formvalname, null, PARAM_RAW);
} else {
//get the raw value here. It is cleaned after that by the object itself
$value = optional_param($formvalname, null, PARAM_RAW);
}
$value = $itemobj->clean_input_value($value);
// If the item is not visible due to its dependency so it shouldn't be required.
// Many thanks to Pau Ferrer Ocaña.
if ($item->dependitem > 0 AND $item->required == 1) {
$comparevalue = false;
if ($feedbackcompletedtmp = feedback_get_current_completed($item->feedback, true)) {
$comparevalue = feedback_compare_item_value($feedbackcompletedtmp->id,
$item->dependitem,
$item->dependvalue,
true);
}
if (!$comparevalue) {
$item->required = 0; // Override the required property.
}
}
//check if the value is set
if (is_null($value) AND $item->required == 1) {
return false;
}
//now we let check the value by the item-class
if (!$itemobj->check_value($value, $item)) {
return false;
}
}
//if no wrong values so we can return true
debugging('Function feedback_check_values() is deprecated and does nothing. '
. 'Items must implement complete_form_element()', DEBUG_DEVELOPER);
return true;
}
@ -2296,7 +2201,8 @@ function feedback_check_values($firstitem, $lastitem) {
* this function create a complete-record and the related value-records.
* depending on the $tmp (true/false) the values are saved temporary or permanently
*
* @global object
* @deprecated since Moodle 3.1
*
* @param int $userid
* @param int $timemodified
* @param boolean $tmp
@ -2306,9 +2212,9 @@ function feedback_check_values($firstitem, $lastitem) {
function feedback_create_values($usrid, $timemodified, $tmp = false, $guestid = false) {
global $DB;
$feedbackid = optional_param('feedbackid', false, PARAM_INT);
$anonymous_response = optional_param('anonymous_response', false, PARAM_INT);
$courseid = optional_param('courseid', false, PARAM_INT);
debugging('Function feedback_create_values() was deprecated because it did not have '.
'enough arguments, was not suitable for non-temporary table and was taking '.
'data directly from input', DEBUG_DEVELOPER);
$tmpstr = $tmp ? 'tmp' : '';
//first we create a new completed record
@ -2339,10 +2245,10 @@ function feedback_create_values($usrid, $timemodified, $tmp = false, $guestid =
$keyname = $item->typ.'_'.$item->id;
if ($itemobj->value_is_array()) {
$itemvalue = optional_param_array($keyname, null, $itemobj->value_type());
if ($item->typ === 'multichoice') {
$itemvalue = optional_param_array($keyname, null, PARAM_INT);
} else {
$itemvalue = optional_param($keyname, null, $itemobj->value_type());
$itemvalue = optional_param($keyname, null, PARAM_NOTAGS);
}
if (is_null($itemvalue)) {
@ -2374,6 +2280,10 @@ function feedback_create_values($usrid, $timemodified, $tmp = false, $guestid =
function feedback_update_values($completed, $tmp = false) {
global $DB;
debugging('Function feedback_update_values() was deprecated because it did not have '.
'enough arguments, was not suitable for non-temporary table and was taking '.
'data directly from input', DEBUG_DEVELOPER);
$courseid = optional_param('courseid', false, PARAM_INT);
$tmpstr = $tmp ? 'tmp' : '';
@ -2394,10 +2304,10 @@ function feedback_update_values($completed, $tmp = false) {
$keyname = $item->typ.'_'.$item->id;
if ($itemobj->value_is_array()) {
$itemvalue = optional_param_array($keyname, null, $itemobj->value_type());
if ($item->typ === 'multichoice') {
$itemvalue = optional_param_array($keyname, null, PARAM_INT);
} else {
$itemvalue = optional_param($keyname, null, $itemobj->value_type());
$itemvalue = optional_param($keyname, null, PARAM_NOTAGS);
}
//is the itemvalue set (could be a subset of items because pagebreak)?
@ -2516,19 +2426,15 @@ function feedback_get_group_values($item,
function feedback_is_already_submitted($feedbackid, $courseid = false) {
global $USER, $DB;
$params = array('userid'=>$USER->id, 'feedback'=>$feedbackid);
if (!$trackings = $DB->get_records_menu('feedback_tracking', $params, '', 'id, completed')) {
if (!isloggedin() || isguestuser()) {
return false;
}
$params = array('userid' => $USER->id, 'feedback' => $feedbackid);
if ($courseid) {
$select = 'completed IN ('.implode(',', $trackings).') AND course_id = ?';
if (!$values = $DB->get_records_select('feedback_value', $select, array($courseid))) {
return false;
}
$params['courseid'] = $courseid;
}
return true;
return $DB->record_exists('feedback_completed', $params);
}
/**
@ -2536,9 +2442,7 @@ function feedback_is_already_submitted($feedbackid, $courseid = false) {
* by pagebreak or by multiple submit so the complete must be found.
* if the param $tmp is set true so all things are related to temporary completeds
*
* @global object
* @global object
* @global object
* @deprecated since Moodle 3.1
* @param int $feedbackid
* @param boolean $tmp
* @param int $courseid
@ -2550,6 +2454,10 @@ function feedback_get_current_completed($feedbackid,
$courseid = false,
$guestid = false) {
debugging('Function feedback_get_current_completed() is deprecated. Please use either '.
'feedback_get_current_completed_tmp() or feedback_get_last_completed()',
DEBUG_DEVELOPER);
global $USER, $CFG, $DB;
$tmpstr = $tmp ? 'tmp' : '';
@ -2674,18 +2582,32 @@ function feedback_get_completeds_group_count($feedback, $groupid = false, $cours
* deletes all completed-recordsets from a feedback.
* all related data such as values also will be deleted
*
* @global object
* @param int $feedbackid
* @param stdClass|int $feedback
* @param stdClass|cm_info $cm
* @param stdClass $course
* @return void
*/
function feedback_delete_all_completeds($feedbackid) {
function feedback_delete_all_completeds($feedback, $cm = null, $course = null) {
global $DB;
if (!$completeds = $DB->get_records('feedback_completed', array('feedback'=>$feedbackid))) {
if (is_int($feedback)) {
$feedback = $DB->get_record('feedback', array('id' => $feedback));
}
if (!$completeds = $DB->get_records('feedback_completed', array('feedback' => $feedback->id))) {
return;
}
if (!$course && !($course = $DB->get_record('course', array('id' => $feedback->course)))) {
return false;
}
if (!$cm && !($cm = get_coursemodule_from_instance('feedback', $feedback->id))) {
return false;
}
foreach ($completeds as $completed) {
feedback_delete_completed($completed->id);
feedback_delete_completed($completed, $feedback, $cm, $course);
}
}
@ -2693,38 +2615,36 @@ function feedback_delete_all_completeds($feedbackid) {
* deletes a completed given by completedid.
* all related data such values or tracking data also will be deleted
*
* @global object
* @param int $completedid
* @param int|stdClass $completed
* @param stdClass $feedback
* @param stdClass|cm_info $cm
* @param stdClass $course
* @return boolean
*/
function feedback_delete_completed($completedid) {
function feedback_delete_completed($completed, $feedback = null, $cm = null, $course = null) {
global $DB, $CFG;
require_once($CFG->libdir.'/completionlib.php');
if (!$completed = $DB->get_record('feedback_completed', array('id'=>$completedid))) {
if (!isset($completed->id)) {
if (!$completed = $DB->get_record('feedback_completed', array('id' => $completed))) {
return false;
}
}
if (!$feedback && !($feedback = $DB->get_record('feedback', array('id' => $completed->feedback)))) {
return false;
}
if (!$feedback = $DB->get_record('feedback', array('id'=>$completed->feedback))) {
if (!$course && !($course = $DB->get_record('course', array('id' => $feedback->course)))) {
return false;
}
if (!$course = $DB->get_record('course', array('id'=>$feedback->course))) {
return false;
}
if (!$cm = get_coursemodule_from_instance('feedback', $feedback->id)) {
if (!$cm && !($cm = get_coursemodule_from_instance('feedback', $feedback->id))) {
return false;
}
//first we delete all related values
$DB->delete_records('feedback_value', array('completed'=>$completed->id));
//now we delete all tracking data
$params = array('completed'=>$completed->id, 'feedback'=>$completed->feedback);
if ($tracking = $DB->get_record('feedback_tracking', $params)) {
$DB->delete_records('feedback_tracking', array('completed'=>$completed->id));
}
$DB->delete_records('feedback_value', array('completed' => $completed->id));
// Update completion state
$completion = new completion_info($course);
@ -2732,25 +2652,10 @@ function feedback_delete_completed($completedid) {
$completion->update_state($cm, COMPLETION_INCOMPLETE, $completed->userid);
}
// Last we delete the completed-record.
$return = $DB->delete_records('feedback_completed', array('id'=>$completed->id));
$return = $DB->delete_records('feedback_completed', array('id' => $completed->id));
// Trigger event for the delete action we performed.
$event = \mod_feedback\event\response_deleted::create(array(
'relateduserid' => $completed->userid,
'objectid' => $completedid,
'courseid' => $course->id,
'context' => context_module::instance($cm->id),
'anonymous' => ($completed->anonymous_response == FEEDBACK_ANONYMOUS_YES),
'other' => array(
'cmid' => $cm->id,
'instanceid' => $feedback->id,
'anonymous' => $completed->anonymous_response) // Deprecated.
));
$event->add_record_snapshot('feedback_completed', $completed);
$event->add_record_snapshot('course', $course);
$event->add_record_snapshot('feedback', $feedback);
$event = \mod_feedback\event\response_deleted::create_from_record($completed, $cm, $feedback);
$event->trigger();
return $return;
@ -2765,12 +2670,14 @@ function feedback_delete_completed($completedid) {
/**
* checks if the course and the feedback is in the table feedback_sitecourse_map.
*
* @global object
* @deprecated since 3.1
* @param int $feedbackid
* @param int $courseid
* @return int the count of records
*/
function feedback_is_course_in_sitecourse_map($feedbackid, $courseid) {
debugging('Function feedback_is_course_in_sitecourse_map() is deprecated because it was not used.',
DEBUG_DEVELOPER);
global $DB;
$params = array('feedbackid'=>$feedbackid, 'courseid'=>$courseid);
return $DB->count_records('feedback_sitecourse_map', $params);
@ -2779,11 +2686,13 @@ function feedback_is_course_in_sitecourse_map($feedbackid, $courseid) {
/**
* checks if the feedback is in the table feedback_sitecourse_map.
*
* @global object
* @deprecated since 3.1
* @param int $feedbackid
* @return boolean
*/
function feedback_is_feedback_in_sitecourse_map($feedbackid) {
debugging('Function feedback_is_feedback_in_sitecourse_map() is deprecated because it was not used.',
DEBUG_DEVELOPER);
global $DB;
return $DB->record_exists('feedback_sitecourse_map', array('feedbackid'=>$feedbackid));
}
@ -2895,11 +2804,14 @@ function feedback_update_sitecourse_map($feedback, $courses) {
* it shouldn't be called all too often
* a good place for it could be the mapcourse.php or unmapcourse.php
*
* @deprecated since 3.1
* @global object
* @return void
*/
function feedback_clean_up_sitecourse_map() {
global $DB;
debugging('Function feedback_clean_up_sitecourse_map() is deprecated because it was not used.',
DEBUG_DEVELOPER);
$maps = $DB->get_records('feedback_sitecourse_map');
foreach ($maps as $map) {
@ -2925,6 +2837,7 @@ function feedback_clean_up_sitecourse_map() {
/**
* prints the option items of a selection-input item (dropdownlist).
* @deprecated since 3.1
* @param int $startval the first value of the list
* @param int $endval the last value of the list
* @param int $selectval which item should be selected
@ -2932,6 +2845,8 @@ function feedback_clean_up_sitecourse_map() {
* @return void
*/
function feedback_print_numeric_option_list($startval, $endval, $selectval = '', $interval = 1) {
debugging('Function feedback_print_numeric_option_list() is deprecated because it was not used.',
DEBUG_DEVELOPER);
for ($i = $startval; $i <= $endval; $i += $interval) {
if ($selectval == ($i)) {
$selected = 'selected="selected"';
@ -2952,17 +2867,19 @@ function feedback_print_numeric_option_list($startval, $endval, $selectval = '',
* @param object $cm the coursemodule-record
* @param object $feedback
* @param object $course
* @param int $userid
* @param stdClass|int $user
* @return void
*/
function feedback_send_email($cm, $feedback, $course, $userid) {
function feedback_send_email($cm, $feedback, $course, $user) {
global $CFG, $DB;
if ($feedback->email_notification == 0) { // No need to do anything
return;
}
$user = $DB->get_record('user', array('id'=>$userid));
if (is_int($user)) {
$user = $DB->get_record('user', array('id' => $user));
}
if (isset($cm->groupmode) && empty($course->groupmodeforce)) {
$groupmode = $cm->groupmode;
@ -2976,7 +2893,7 @@ function feedback_send_email($cm, $feedback, $course, $userid) {
WHERE g.courseid = ?
AND g.id = m.groupid
AND m.userid = ?
ORDER BY name ASC", array($course->id, $userid));
ORDER BY name ASC", array($course->id, $user->id));
$groups = array_values($groups);
$teachers = feedback_get_receivemail_users($cm->id, $groups);
@ -3001,7 +2918,7 @@ function feedback_send_email($cm, $feedback, $course, $userid) {
$info->feedback = format_string($feedback->name, true);
$info->url = $CFG->wwwroot.'/mod/feedback/show_entries.php?'.
'id='.$cm->id.'&'.
'userid=' . $userid;
'userid=' . $user->id;
$a = array('username' => $info->username, 'feedbackname' => $feedback->name);

View file

@ -34,10 +34,11 @@ list($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
require_course_login($course, true, $cm);
$feedback = $PAGE->activityrecord;
$feedbackstructure = new mod_feedback_structure($feedback, $cm, $courseid);
$PAGE->set_pagelayout('embedded');
$PAGE->set_pagelayout('popup');
/// Print the page header
// Print the page header.
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
@ -49,68 +50,20 @@ $PAGE->set_title($feedback->name);
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
/// Print the main part of the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
echo $OUTPUT->heading(format_text($feedback->name));
// Print the main part of the page.
echo $OUTPUT->heading(format_string($feedback->name));
$continueurl = new moodle_url('/mod/feedback/view.php', array('id' => $id));
if ($courseid) {
$continueurl->param('courseid', $courseid);
}
$feedbackitems = $DB->get_records('feedback_item', array('feedback'=>$feedback->id), 'position');
echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide');
$form = new mod_feedback_complete_form(mod_feedback_complete_form::MODE_PRINT,
$feedbackstructure, 'feedback_print_form');
echo $OUTPUT->continue_button($continueurl);
if (is_array($feedbackitems)) {
$itemnr = 0;
$align = right_to_left() ? 'right' : 'left';
echo $OUTPUT->box_start('feedback_items printview');
//check, if there exists required-elements
$params = array('feedback'=>$feedback->id, 'required'=>1);
$countreq = $DB->count_records('feedback_item', $params);
if ($countreq > 0) {
echo '<div class="fdescription required">';
echo get_string('somefieldsrequired', 'form', '<img alt="'.get_string('requiredelement', 'form').
'" src="'.$OUTPUT->pix_url('req') .'" class="req" />');
echo '</div>';
}
//print the inserted items
$itempos = 0;
foreach ($feedbackitems as $feedbackitem) {
echo $OUTPUT->box_start('feedback_item_box_'.$align);
$itempos++;
//Items without value only are labels
if ($feedbackitem->hasvalue == 1 AND $feedback->autonumbering) {
$itemnr++;
echo $OUTPUT->box_start('feedback_item_number_'.$align);
echo $itemnr;
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_start('box generalbox boxalign_'.$align);
if ($feedbackitem->typ != 'pagebreak') {
feedback_print_item_complete($feedbackitem, false, false);
} else {
echo $OUTPUT->box_start('feedback_pagebreak');
echo '<hr class="feedback_pagebreak" />';
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
} else {
echo $OUTPUT->box(get_string('no_items_available_yet', 'feedback'),
'generalbox boxaligncenter boxwidthwide');
}
$form->display();
echo $OUTPUT->continue_button($continueurl);
echo $OUTPUT->box_end();
/// Finish the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Finish the page.
echo $OUTPUT->footer();

View file

@ -24,7 +24,6 @@
require_once("../../config.php");
require_once("lib.php");
require_once($CFG->libdir.'/tablelib.php');
////////////////////////////////////////////////////////
//get the params
@ -33,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
@ -51,18 +51,37 @@ $feedback = $PAGE->activityrecord;
require_capability('mod/feedback:viewreports', $context);
// Process delete template result.
if ($deleteid && optional_param('confirm', 0, PARAM_BOOL) && confirm_sesskey()) {
if ($deleteid) {
// This is a request to delete a reponse.
require_capability('mod/feedback:deletesubmissions', $context);
$completed = $DB->get_record('feedback_completed', array('id' => $deleteid), '*', MUST_EXIST);
feedback_delete_completed($deleteid);
require_sesskey();
$feedbackstructure = new mod_feedback_completion($feedback, $cm, 0, true, $deleteid);
feedback_delete_completed($feedbackstructure->get_completed(), $feedback, $cm);
redirect($baseurl);
} else if ($showcompleted || $userid) {
// Viewing individual response.
$feedbackstructure = new mod_feedback_completion($feedback, $cm, 0, true, $showcompleted, $userid);
} else {
// Viewing list of reponses.
$feedbackstructure = new mod_feedback_structure($feedback, $cm, $courseid);
}
/// Print the page header
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
$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);
$PAGE->set_title($feedback->name);
@ -77,109 +96,54 @@ require('tabs.php');
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Print the list of responses.
if (!$showcompleted && !$deleteid && !$userid) {
// Show non-anonymous responses.
$responsestable = new mod_feedback_responses_table($cm);
$totalrows = $responsestable->get_total_responses_count();
if ($feedback->anonymous == FEEDBACK_ANONYMOUS_NO || $totalrows) {
echo $OUTPUT->heading(get_string('non_anonymous_entries', 'feedback', $totalrows), 4);
$responsestable->display();
}
// Show anonymous responses.
feedback_shuffle_anonym_responses($feedback);
$anonresponsestable = new mod_feedback_responses_anon_table($cm);
$totalrows = $anonresponsestable->get_total_responses_count();
if ($feedback->anonymous == FEEDBACK_ANONYMOUS_YES || $totalrows) {
echo $OUTPUT->heading(get_string('anonymous_entries', 'feedback', $totalrows), 4);
$anonresponsestable->display();
}
}
// Print the response of the given user.
if ($userid || $showcompleted) {
//get the feedbackitems
$feedbackitems = $DB->get_records('feedback_item', array('feedback' => $feedback->id), 'position');
// Print the response of the given user.
$completedrecord = $feedbackstructure->get_completed();
if ($userid) {
$user = $DB->get_record('user', array('id' => $userid, 'deleted' => 0), '*', MUST_EXIST);
$params = ['feedback' => $feedback->id, 'userid' => $userid, 'anonymous_response' => FEEDBACK_ANONYMOUS_NO];
if ($showcompleted) {
$params['id'] = $showcompleted;
}
$feedbackcompleted = $DB->get_record('feedback_completed', $params);
$responsetitle = userdate($feedbackcompleted->timemodified) . ' (' . fullname($user) . ')';
} else if ($showcompleted) {
$feedbackcompleted = $DB->get_record('feedback_completed',
array('feedback' => $feedback->id, 'id' => $showcompleted,
'anonymous_response' => FEEDBACK_ANONYMOUS_YES), '*', MUST_EXIST);
$usr = $DB->get_record('user', array('id' => $userid), '*', MUST_EXIST);
$responsetitle = userdate($completedrecord->timemodified) . ' (' . fullname($usr) . ')';
} else {
$responsetitle = get_string('response_nr', 'feedback') . ': ' .
$feedbackcompleted->random_response . ' (' . get_string('anonymous', 'feedback') . ')';
$completedrecord->random_response . ' (' . get_string('anonymous', 'feedback') . ')';
}
echo $OUTPUT->heading($responsetitle, 4);
// Print the items.
if (is_array($feedbackitems)) {
$align = right_to_left() ? 'right' : 'left';
$form = new mod_feedback_complete_form(mod_feedback_complete_form::MODE_VIEW_RESPONSE,
$feedbackstructure, 'feedback_viewresponse_form');
$form->display();
echo $OUTPUT->box_start('feedback_items');
$itemnr = 0;
foreach ($feedbackitems as $feedbackitem) {
//get the values
$params = array('completed'=>$feedbackcompleted->id, 'item'=>$feedbackitem->id);
$value = $DB->get_record('feedback_value', $params);
echo $OUTPUT->box_start('feedback_item_box_'.$align);
if ($feedbackitem->hasvalue == 1 AND $feedback->autonumbering) {
$itemnr++;
echo $OUTPUT->box_start('feedback_item_number_'.$align);
echo $itemnr;
echo $OUTPUT->box_end();
}
if ($feedbackitem->typ != 'pagebreak') {
echo $OUTPUT->box_start('box generalbox boxalign_'.$align);
if (isset($value->value)) {
feedback_print_item_show_value($feedbackitem, $value->value);
} else {
feedback_print_item_show_value($feedbackitem, false);
}
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
}
// Show navigation to previous/next reponse.
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($feedbackcompleted);
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']) : '';
echo html_writer::link($returnurl, get_string('back'), ['class' => 'back_to_list']);
echo $nextresponseurl ? html_writer::link($nextresponseurl, get_string('next'), ['class' => 'next_response']) : '';
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).
$totalrows = $responsestable->get_total_responses_count();
if (!$feedbackstructure->is_anonymous() || $totalrows) {
echo $OUTPUT->heading(get_string('non_anonymous_entries', 'feedback', $totalrows), 4);
$responsestable->display();
}
// Show anonymous responses (always retrieve them even if current feedback is not anonymous).
$feedbackstructure->shuffle_anonym_responses();
$totalrows = $anonresponsestable->get_total_responses_count();
if ($feedbackstructure->is_anonymous() || $totalrows) {
echo $OUTPUT->heading(get_string('anonymous_entries', 'feedback', $totalrows), 4);
$anonresponsestable->display();
}
}
// Print confirmation form to delete a response.
if ($deleteid) {
$continueurl = new moodle_url($baseurl, array('delete' => $deleteid, 'confirm' => 1, 'sesskey' => sesskey()));
echo $OUTPUT->confirm(get_string('confirmdeleteentry', 'feedback'), $continueurl, $baseurl);
}
/// Finish the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
// Finish the page.
echo $OUTPUT->footer();

View file

@ -1,133 +1,190 @@
/* styles using by feedback */
.feedback_switchrequired img{
}
span.feedback_info {
.path-mod-feedback span.feedback_info {
font-weight:bold;
}
div.feedback_item_box_left, div.feedback_item_box_right {
}
div.feedback_item_box_left div.feedback_item_label_left, div.feedback_item_box_left div.feedback_item_presentation_left {
margin-left: 15px;
}
div.feedback_item_box_right div.feedback_item_label_right, div.feedback_item_box_right div.feedback_item_presentation_right {
margin-right: 15px;
}
div.feedback_depend {
.path-mod-feedback div.feedback_is_dependent {
background:#DDDDDD;
}
div.feedback_complete_depend {
background:#EEEEEE;
}
span.feedback_depend {
.path-mod-feedback span.feedback_depend {
color:#ff0000;
}
div.feedback_item_number_left, div.feedback_item_left {
float:left;
}
div.feedback_item_number_right, div.feedback_item_right {
float:right;
}
div.feedback_item_commands_left {
float:right;
text-align:right;
}
div.feedback_item_commands_right {
float:left;
text-align:left;
}
li.feedback_item_check_h_left,
li.feedback_item_check_h_right,
li.feedback_item_radio_h_left,
li.feedback_item_radio_h_right {
list-style-type:none;
display:inline;
}
div.feedback_item_select_h_left,
div.feedback_item_select_h_right {
display:block;
}
li.feedback_item_check_v_left,
li.feedback_item_check_v_right,
li.feedback_item_radio_v_left,
li.feedback_item_radio_v_right {
list-style-type:none;
display:block;
}
div.feedback_item_select_v_left,
div.feedback_item_select_v_right {
display:block;
}
div.feedback_items label{
display: inline;
}
div.feedback_item_captcha_text_left,
div.feedback_item_captcha_img_left {
display:inline;
margin: 5px;
}
div.feedback_item_captcha_text_right,
div.feedback_item_captcha_img_right {
display:inline;
margin: 5px;
}
hr.feedback_pagebreak {
height:8px;
.path-mod-feedback hr.feedback_pagebreak {
height:4px;
color:#aaaaaa;
background-color:#aaaaaa;
border:0px;
border: 0;
margin: 0;
}
.drag_target_active {
opacity: .25;
.path-mod-feedback .drag_target_active {
opacity: .25;
}
.drag_item_active {
opacity: .5;
.path-mod-feedback .drag_item_active {
opacity: .5;
}
ul#feedback_draglist {
list-style: none;
padding: 0;
margin: 0;
}
div#feedback_dragarea {
width:95%;
}
div img.feedback_bar_image {
.path-mod-feedback .feedback_bar_image {
height: 10px;
}
.path-mod-feedback input,
.path-mod-feedback textarea,
.path-mod-feedback .uneditable-input {
width: auto;
}
.path-mod-feedback #analysis-form label { display: inline; }
.path-mod-feedback .mform.feedback_form .fitem .fitemtitle {
display: block;
margin-top: 4px;
margin-bottom: 4px;
text-align: left;
width: 100%;
}
.path-mod-feedback .mform.feedback_form .fitem .felement {
margin-left: 0;
width: 100%;
float: left;
padding-left: 0;
padding-right: 0;
}
.path-mod-feedback .mform.feedback_form .fitem .fstatic:empty {
display: none;
}
.path-mod-feedback .mform.feedback_form .fitem .fcheckbox > span,
.path-mod-feedback .mform.feedback_form .fitem .fradio > span,
.path-mod-feedback .mform.feedback_form .fitem .fgroup > span {
margin-top: 4px;
}
body.path-mod-feedback #region-main .mform.feedback_form .femptylabel .fitemtitle {
display: inline-block;
width: auto;
margin-right: 0;
}
.path-mod-feedback .mform.feedback_form .femptylabel .felement {
display: inline-block;
margin-top: 4px;
padding-top: 5px;
width: auto;
}
body.path-mod-feedback #region-main .mform.feedback_form .feedback-item-pagebreak .felement {
width: 100%;
}
.path-mod-feedback .mform.feedback_form .fitem_fcheckbox .fitemtitle,
.path-mod-feedback .mform.feedback_form .fitem_fcheckbox .felement {
display: inline-block;
width: auto;
}
.path-mod-feedback .mform.feedback_form .fitem_fcheckbox .felement {
padding: 6px;
}
body.dir-rtl.path-mod-feedback #region-main .mform.feedback_form .femptylabel .fitemtitle {
margin-right: 0px;
margin-left: 0;
}
.dir-rtl.path-mod-feedback .mform.feedback_form .fitem .fitemtitle {
text-align: right;
}
.dir-rtl.path-mod-feedback .mform.feedback_form .fitem .felement {
margin-right: 0;
float: right;
padding-right: 0;
padding-left: 0;
}
.dir-rtl.path-mod-feedback .mform.feedback_form .fitem_fcheckbox .felement {
float: right;
}
.path-mod-feedback .mform.feedback_form#feedback_viewresponse_form .fitem.feedback_hasvalue:not(.feedback-item-captcha) .felement {
background: #FBFBF1;
min-height: 1em;
box-sizing: border-box;
padding: 3px;
border: 1px solid #ddd
}
.path-mod-feedback .mform.feedback_form .fitem.feedback_hasvalue .fstatic:empty {
display: inherit;
}
.path-mod-feedback .mform.feedback_form#feedback_edit_form .fitem:hover {
background: #f5f5f5;
}
.path-mod-feedback .mform.feedback_form#feedback_edit_form .fitem .fitemtitle label {
width: 100%;
}
.path-mod-feedback .mform.feedback_form#feedback_edit_form .fitem .fitemtitle .itemtitle {
position: relative;
width: 100%;
}
.path-mod-feedback .mform.feedback_form#feedback_edit_form .fitem .fitemtitle .itemtitle .itemdd,
.path-mod-feedback .mform.feedback_form#feedback_edit_form .fitem .fitemtitle .itemtitle .itemname {
float: left;
}
.path-mod-feedback .mform.feedback_form#feedback_edit_form .fitem .fitemtitle .itemtitle .itemactions {
float: right;
}
.path-mod-feedback .templateslist td.cell.action,
.path-mod-feedback .templateslist th.header.action {
width: 10%;
}
/* Analysis page */
.path-mod-feedback table.analysis {
width: 100%;
border-top: 1px solid #aaaaaa;
margin-top: 10px;
}
.path-mod-feedback table.analysis tr:first-child th {
padding-top:10px;
}
.path-mod-feedback table.analysis tr:hover {
background: #f5f5f5;
}
.path-mod-feedback table.analysis td.singlevalue:before,
.path-mod-feedback table.analysis td.optionname:before {
content:'- ';
}
.path-mod-feedback table.analysis.itemtype_textarea td {
padding: 4px 0;
}
.path-mod-feedback table.analysis tr.isempty {
display:none;
}
/* Responses list */
.path-mod-feedback #showentrytable td.cell.completed_timemodified,
.path-mod-feedback #showentryanontable td.cell.random_response {
font-weight: bold;
}
.path-mod-feedback #showentrytable td.cell.userpic,
.path-mod-feedback #showentrytable td.cell.deleteentry,
.path-mod-feedback #showentryanontable td.cell.deleteentry {
width: 10px;
}
/* Responses navigation */
.path-mod-feedback .response_navigation {
margin: .5em 0;

View file

@ -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'));

View file

@ -0,0 +1,67 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template mod_feedback/summary
Displays feedback summary
Classes required for JS:
* none
Data attributes required for JS:
* none
Context variables required for this template:
* none
Example context (json):
{
"completedcount" : 15,
"itemscount" : 5,
"timeopen" : "May 15, 2016"
}
}}
<div class="feedback_info">
<span
class="feedback_info">{{#str}}completed_feedbacks, mod_feedback{{/str}}: </span><span
class="feedback_info_value">{{completedcount}}</span>
</div>
<div class="feedback_info">
<span
class="feedback_info">{{#str}}questions, mod_feedback{{/str}}: </span><span
class="feedback_info_value">{{itemscount}}</span>
</div>
{{#timeopen}}
<div class="feedback_info">
<span
class="feedback_info">{{#str}}feedbackopen, mod_feedback{{/str}}: </span><span
class="feedback_info_value">{{timeopen}}</span>
</div>
{{/timeopen}}
{{#timeclose}}
<div class="feedback_info">
<span
class="feedback_info">{{#str}}feedbackclose, mod_feedback{{/str}}: </span><span
class="feedback_info_value">{{timeclose}}</span>
</div>
{{/timeclose}}

View file

@ -22,10 +22,6 @@ Feature: Anonymous feedback
And the following "system role assigns" exist:
| user | course | role |
| manager | Acceptance test site | manager |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber | anonymous | publish_stats |
| feedback | Site feedback | Acceptance test site | feedback0 | 1 | 1 |
@ -106,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
@ -168,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
@ -226,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"
@ -237,8 +233,6 @@ Feature: Anonymous feedback
And I follow "Back"
# Delete anonymous response
And I click on "Delete entry" "link" in the "Response number: 1" "table_row"
And I should see "Are you sure you want to delete this entry?"
And I press "Continue"
And I should see "Anonymous entries (1)"
And I should not see "Response number: 1"
And I should see "Response number: 2"

View file

@ -30,12 +30,6 @@ Feature: Mapping courses in a feedback
And the following "system role assigns" exist:
| user | course | role |
| manager | Acceptance test site | manager |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I navigate to "Manage blocks" node in "Site administration > Plugins > Blocks"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber | anonymous | publish_stats |
| feedback | Course feedback | Acceptance test site | feedback0 | 1 | 1 |
@ -121,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"
@ -130,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"
@ -200,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"
@ -209,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"

View file

@ -16,10 +16,6 @@ Feature: Exporting and importing feedbacks
| user | course | role |
| teacher | C1 | editingteacher |
| teacher | C1 | editingteacher |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber |
| feedback | Learning experience | C1 | feedback0 |

View file

@ -45,10 +45,6 @@ Feature: Feedbacks in courses with groups
And the following "system role assigns" exist:
| user | course | role |
| manager | Acceptance test site | manager |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber | anonymous | publish_stats | groupmode |
| feedback | Site feedback | Acceptance test site | feedback0 | 2 | 1 | 1 |

View file

@ -18,10 +18,6 @@ Feature: Testing multichoice questions in feedback
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber |
| feedback | Learning experience | C1 | feedback0 |
@ -90,7 +86,7 @@ Feature: Testing multichoice questions in feedback
And I should not see "this is the third page of the feedback"
And I press "Next page"
# We are still on the second page because the field is required
And I should see "Saving failed because missing or false values" in the ".error" "css_element"
And I should see "Required" in the ".error" "css_element"
And I should see "this is the second page of the feedback"
And I set the field "option e" to "1"
And the following fields match these values:
@ -159,7 +155,7 @@ Feature: Testing multichoice questions in feedback
And I should see "1 (100.00 %)" in the "option i:" "table_row"
# Change the settings so we don't analyse empty submits
And I follow "Edit questions"
And I click on "Edit question" "link" in the "//li[contains(@class, 'feedback_itemlist') and contains(.,'multichoice1')]" "xpath_element"
And I click on "Edit question" "link" in the "//div[contains(@class, 'feedback_itemlist') and contains(.,'multichoice1')]" "xpath_element"
And I set the field "Do not analyse empty submits" to "Yes"
And I press "Save changes to question"
And I follow "Analysis"
@ -168,6 +164,7 @@ Feature: Testing multichoice questions in feedback
And I should not see "%" in the "option c:" "table_row"
And I log out
@javascript
Scenario: Non-rated multiple-answers multiple choice questions in feedback
# Create a feedback with three pages, required and dependent questions.
When I add a "Multiple choice" question to the feedback with:
@ -227,7 +224,7 @@ Feature: Testing multichoice questions in feedback
And I should not see "this is the third page of the feedback"
And I press "Next page"
# We are still on the second page because the field is required
And I should see "Saving failed because missing or false values" in the ".error" "css_element"
And I should see "Required" in the ".error" "css_element"
And I should see "this is the second page of the feedback"
And I set the field "option e" to "1"
And I set the field "option f" to "1"
@ -297,7 +294,7 @@ Feature: Testing multichoice questions in feedback
And I should see "1 (100.00 %)" in the "option i:" "table_row"
# Change the settings so we don't analyse empty submits
And I follow "Edit questions"
And I click on "Edit question" "link" in the "//li[contains(@class, 'feedback_itemlist') and contains(.,'multichoice1')]" "xpath_element"
And I click on "Edit question" "link" in the "//div[contains(@class, 'feedback_itemlist') and contains(.,'multichoice1')]" "xpath_element"
And I set the field "Do not analyse empty submits" to "Yes"
And I press "Save changes to question"
And I follow "Analysis"
@ -357,7 +354,7 @@ Feature: Testing multichoice questions in feedback
And I should not see "this is the third page of the feedback"
And I press "Next page"
# We are still on the second page because the field is required
And I should see "Saving failed because missing or false values" in the ".error" "css_element"
And I should see "Required" in the ".error" "css_element"
And I should see "this is the second page of the feedback"
And I set the field "this is a multiple choice 2" to "option e"
And I press "Next page"
@ -414,7 +411,7 @@ Feature: Testing multichoice questions in feedback
And I should see "1 (100.00 %)" in the "option i:" "table_row"
# Change the settings so we don't analyse empty submits
And I follow "Edit questions"
And I click on "Edit question" "link" in the "//li[contains(@class, 'feedback_itemlist') and contains(.,'multichoice1')]" "xpath_element"
And I click on "Edit question" "link" in the "//div[contains(@class, 'feedback_itemlist') and contains(.,'multichoice1')]" "xpath_element"
And I set the field "Do not analyse empty submits" to "Yes"
And I press "Save changes to question"
And I follow "Analysis"

View file

@ -22,10 +22,6 @@ Feature: Non anonymous feedback
And the following "system role assigns" exist:
| user | course | role |
| manager | Acceptance test site | manager |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber | anonymous | publish_stats |
| feedback | Site feedback | Acceptance test site | feedback0 | 2 | 1 |
@ -166,8 +162,6 @@ Feature: Non anonymous feedback
And I follow "Back"
# Delete non anonymous response
And I click on "Delete entry" "link" in the "Username 1" "table_row"
And I should see "Are you sure you want to delete this entry?"
And I press "Continue"
And I should see "Non anonymous entries (1)"
And I should not see "Username 1"
And I should see "Username 2"

View file

@ -18,10 +18,6 @@ Feature: Test creating different types of feedback questions
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber |
| feedback | Learning experience | C1 | feedback0 |
@ -120,10 +116,10 @@ Feature: Test creating different types of feedback questions
And I should not see "%" in the "option g:" "table_row"
And I should see "1 (50.00 %)" in the "option h:" "table_row"
And I should see "1 (50.00 %)" in the "option i:" "table_row"
And I should see "0" in the "option k (0):" "table_row"
And I should not see "%" in the "option k (0):" "table_row"
And I should see "1 (50.00 %)" in the "option l (1):" "table_row"
And I should see "1 (50.00 %)" in the "option m (5):" "table_row"
And I should see "0" in the "(0) option k" "table_row"
And I should not see "%" in the "(0) option k" "table_row"
And I should see "1 (50.00 %)" in the "(1) option l" "table_row"
And I should see "1 (50.00 %)" in the "(5) option m:" "table_row"
And I should see "Average: 3.00" in the "(multichoice4)" "table"
And I should see "35" in the "(numeric)" "table"
And I should see "71" in the "(numeric)" "table"

View file

@ -33,10 +33,6 @@ Feature: Show users who have not responded to the feedback survey
And the following "grouping groups" exist:
| grouping | group |
| GXI1 | GI1 |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
@javascript
Scenario: See users who have not responded

View file

@ -20,10 +20,6 @@ Feature: Saving, using and deleting feedback templates
And the following "system role assigns" exist:
| user | course | role |
| manager | Acceptance test site | manager |
And I log in as "admin"
And I navigate to "Manage activities" node in "Site administration > Plugins > Activity modules"
And I click on "Show" "link" in the "Feedback" "table_row"
And I log out
And the following "activities" exist:
| activity | name | course | idnumber |
| feedback | Learning experience course 1 | C1 | feedback1 |
@ -157,9 +153,7 @@ Feature: Saving, using and deleting feedback templates
Then I should not see "My public template"
And ".publictemplates" "css_element" should not exist
And "My course template" "text" should exist in the ".coursetemplates" "css_element"
And I click on "Delete" "button" in the "My course template" "table_row"
And I should see "Are you sure you want to delete this template?"
And I press "Continue"
And I click on "Delete" "link" in the "My course template" "table_row"
And I should see "Template deleted"
And "My course template" "text" should not exist in the ".coursetemplates" "css_element"
And "No templates available yet" "text" should exist in the ".coursetemplates" "css_element"
@ -168,6 +162,7 @@ Feature: Saving, using and deleting feedback templates
And the "Use a template" select box should contain "My public template"
And I log out
@javascript
Scenario: Manager can delete both course and public templates
# Save feedback as both public and course template
When I log in as "manager"
@ -184,17 +179,17 @@ Feature: Saving, using and deleting feedback templates
And I follow "Delete template..."
Then "My public template" "text" should exist in the ".publictemplates" "css_element"
And "My course template" "text" should exist in the ".coursetemplates" "css_element"
And I click on "Delete" "button" in the "My course template" "table_row"
And I click on "Delete" "link" in the "My course template" "table_row"
And I should see "Are you sure you want to delete this template?"
And I press "Continue"
And I press "Yes"
And I should see "Template deleted"
And "My course template" "text" should not exist in the ".coursetemplates" "css_element"
And "No templates available yet" "text" should exist in the ".coursetemplates" "css_element"
# Delete public template
And "My public template" "text" should exist in the ".publictemplates" "css_element"
And I click on "Delete" "button" in the "My public template" "table_row"
And I click on "Delete" "link" in the "My public template" "table_row"
And I should see "Are you sure you want to delete this template?"
And I press "Continue"
And I press "Yes"
And I should see "Template deleted"
And "My public template" "text" should not exist in the ".publictemplates" "css_element"
And "No templates available yet" "text" should exist in the ".publictemplates" "css_element"

View file

@ -218,7 +218,7 @@ class mod_feedback_events_testcase extends advanced_testcase {
// Save the feedback.
$sink = $this->redirectEvents();
$id = feedback_save_tmp_values($completed, false, $USER->id);
$id = feedback_save_tmp_values($completed, false);
$events = $sink->get_events();
$event = array_pop($events); // Response submitted feedback event.
$sink->close();
@ -257,14 +257,14 @@ class mod_feedback_events_testcase extends advanced_testcase {
// Save the feedback.
$sink = $this->redirectEvents();
feedback_save_tmp_values($completed, false, $USER->id);
feedback_save_tmp_values($completed, false);
$events = $sink->get_events();
$event = array_pop($events); // Response submitted feedback event.
$sink->close();
// Test legacy data.
$arr = array($this->eventcourse->id, 'feedback', 'submit', 'view.php?id=' . $this->eventcm->id, $this->eventfeedback->id,
$this->eventcm->id, $USER->id);
$this->eventcm->id, $this->eventuser->id);
$this->assertEventLegacyLogData($arr, $event);
// Test can_view().

View file

@ -0,0 +1,175 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests for functions in db/upgradelib.php
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/feedback/db/upgradelib.php');
/**
* Tests for functions in db/upgradelib.php
*
* @package mod_feedback
* @copyright 2016 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_feedback_upgradelib_testcase extends advanced_testcase {
/** @var string */
protected $testsql = "SELECT COUNT(v.id) FROM {feedback_completed} c, {feedback_value} v
WHERE c.id = v.completed AND c.courseid <> v.course_id";
/** @var string */
protected $testsqltmp = "SELECT COUNT(v.id) FROM {feedback_completedtmp} c, {feedback_valuetmp} v
WHERE c.id = v.completed AND c.courseid <> v.course_id";
/** @var int */
protected $course1;
/** @var int */
protected $course2;
/** @var stdClass */
protected $feedback;
/** @var stdClass */
protected $user;
/**
* Sets up the fixture
* This method is called before a test is executed.
*/
public function setUp() {
parent::setUp();
$this->resetAfterTest(true);
$this->course1 = $this->getDataGenerator()->create_course();
$this->course2 = $this->getDataGenerator()->create_course();
$this->feedback = $this->getDataGenerator()->create_module('feedback', array('course' => SITEID));
$this->user = $this->getDataGenerator()->create_user();
}
public function test_upgrade_courseid_completed() {
global $DB;
// Case 1. No errors in the data.
$completed1 = $DB->insert_record('feedback_completed',
['feedback' => $this->feedback->id, 'userid' => $this->user->id]);
$DB->insert_record('feedback_value',
['completed' => $completed1, 'course_id' => $this->course1->id,
'item' => 1, 'value' => 1]);
$DB->insert_record('feedback_value',
['completed' => $completed1, 'course_id' => $this->course1->id,
'item' => 1, 'value' => 2]);
$this->assertCount(1, $DB->get_records('feedback_completed'));
$this->assertEquals(2, $DB->count_records_sql($this->testsql)); // We have errors!
mod_feedback_upgrade_courseid(true); // Running script for temp tables.
$this->assertCount(1, $DB->get_records('feedback_completed'));
$this->assertEquals(2, $DB->count_records_sql($this->testsql)); // Nothing changed.
mod_feedback_upgrade_courseid();
$this->assertCount(1, $DB->get_records('feedback_completed')); // Number of records is the same.
$this->assertEquals(0, $DB->count_records_sql($this->testsql)); // All errors are fixed!
}
public function test_upgrade_courseid_completed_with_errors() {
global $DB;
// Case 2. Errors in data (same feedback_completed has values for different courses).
$completed1 = $DB->insert_record('feedback_completed',
['feedback' => $this->feedback->id, 'userid' => $this->user->id]);
$DB->insert_record('feedback_value',
['completed' => $completed1, 'course_id' => $this->course1->id,
'item' => 1, 'value' => 1]);
$DB->insert_record('feedback_value',
['completed' => $completed1, 'course_id' => $this->course2->id,
'item' => 1, 'value' => 2]);
$this->assertCount(1, $DB->get_records('feedback_completed'));
$this->assertEquals(2, $DB->count_records_sql($this->testsql)); // We have errors!
mod_feedback_upgrade_courseid(true); // Running script for temp tables.
$this->assertCount(1, $DB->get_records('feedback_completed'));
$this->assertEquals(2, $DB->count_records_sql($this->testsql)); // Nothing changed.
mod_feedback_upgrade_courseid();
$this->assertCount(2, $DB->get_records('feedback_completed')); // Extra record inserted.
$this->assertEquals(0, $DB->count_records_sql($this->testsql)); // All errors are fixed!
}
public function test_upgrade_courseid_completedtmp() {
global $DB;
// Case 1. No errors in the data.
$completed1 = $DB->insert_record('feedback_completedtmp',
['feedback' => $this->feedback->id, 'userid' => $this->user->id]);
$DB->insert_record('feedback_valuetmp',
['completed' => $completed1, 'course_id' => $this->course1->id,
'item' => 1, 'value' => 1]);
$DB->insert_record('feedback_valuetmp',
['completed' => $completed1, 'course_id' => $this->course1->id,
'item' => 1, 'value' => 2]);
$this->assertCount(1, $DB->get_records('feedback_completedtmp'));
$this->assertEquals(2, $DB->count_records_sql($this->testsqltmp)); // We have errors!
mod_feedback_upgrade_courseid(); // Running script for non-temp tables.
$this->assertCount(1, $DB->get_records('feedback_completedtmp'));
$this->assertEquals(2, $DB->count_records_sql($this->testsqltmp)); // Nothing changed.
mod_feedback_upgrade_courseid(true);
$this->assertCount(1, $DB->get_records('feedback_completedtmp')); // Number of records is the same.
$this->assertEquals(0, $DB->count_records_sql($this->testsqltmp)); // All errors are fixed!
}
public function test_upgrade_courseid_completedtmp_with_errors() {
global $DB;
// Case 2. Errors in data (same feedback_completed has values for different courses).
$completed1 = $DB->insert_record('feedback_completedtmp',
['feedback' => $this->feedback->id, 'userid' => $this->user->id]);
$DB->insert_record('feedback_valuetmp',
['completed' => $completed1, 'course_id' => $this->course1->id,
'item' => 1, 'value' => 1]);
$DB->insert_record('feedback_valuetmp',
['completed' => $completed1, 'course_id' => $this->course2->id,
'item' => 1, 'value' => 2]);
$this->assertCount(1, $DB->get_records('feedback_completedtmp'));
$this->assertEquals(2, $DB->count_records_sql($this->testsqltmp)); // We have errors!
mod_feedback_upgrade_courseid(); // Running script for non-temp tables.
$this->assertCount(1, $DB->get_records('feedback_completedtmp'));
$this->assertEquals(2, $DB->count_records_sql($this->testsqltmp)); // Nothing changed.
mod_feedback_upgrade_courseid(true);
$this->assertCount(2, $DB->get_records('feedback_completedtmp')); // Extra record inserted.
$this->assertEquals(0, $DB->count_records_sql($this->testsqltmp)); // All errors are fixed!
}
public function test_upgrade_courseid_empty_completed() {
global $DB;
// Record in 'feedback_completed' does not have corresponding values.
$DB->insert_record('feedback_completed',
['feedback' => $this->feedback->id, 'userid' => $this->user->id]);
$this->assertCount(1, $DB->get_records('feedback_completed'));
$record1 = $DB->get_record('feedback_completed', []);
mod_feedback_upgrade_courseid();
$this->assertCount(1, $DB->get_records('feedback_completed')); // Number of records is the same.
$record2 = $DB->get_record('feedback_completed', []);
$this->assertEquals($record1, $record2);
}
}

View file

@ -1,6 +1,30 @@
=== 3.1 ===
* feedback_get_courses_from_sitecourse_map() now returns course id as 'id' attribute
* Base class for feedback items - feedback_item_base - has been significantly changed, all item types now
must implement method complete_form_element() instead of print_item_preview(), print_item_complete(),
print_item_show_value(), check_values(), clean_input_value() and value_is_array(). Rendering the items
on complete form, feedback preview, feedback edit and when viewing response is done using moodleform.
* The following functions have been deprecated:
* feedback_print_item_preview()
* feedback_print_item_complete()
* feedback_print_item_show_value
* feedback_check_values()
* feedback_clean_input_value()
* feedback_get_context()
* feedback_create_item()
* feedback_set_tmp_values()
* feedback_delete_completedtmp()
* feedback_get_page_to_continue()
* feedback_save_values()
* feedback_save_guest_values()
* feedback_create_values()
* feedback_update_values()
* feedback_get_current_completed()
* feedback_is_course_in_sitecourse_map()
* feedback_is_feedback_in_sitecourse_map()
* feedback_clean_up_sitecourse_map()
* feedback_print_numeric_option_list()
=== 2.7 ===

View file

@ -42,6 +42,7 @@ $context = context_module::instance($cm->id);
require_login($course, true, $cm);
$feedback = $PAGE->activityrecord;
$feedbackstructure = new mod_feedback_structure($feedback, $cm, 0, $templateid);
require_capability('mod/feedback:edititems', $context);
@ -75,40 +76,9 @@ echo $OUTPUT->heading(get_string('confirmusetemplate', 'feedback'), 4);
$mform->display();
$templateitems = $DB->get_records('feedback_item', array('template'=>$templateid), 'position');
if (is_array($templateitems)) {
$templateitems = array_values($templateitems);
}
if (is_array($templateitems)) {
$itemnr = 0;
$align = right_to_left() ? 'right' : 'left';
echo $OUTPUT->box_start('feedback_items');
foreach ($templateitems as $templateitem) {
echo $OUTPUT->box_start('feedback_item_box_'.$align);
if ($templateitem->hasvalue == 1 AND $feedback->autonumbering) {
$itemnr++;
echo $OUTPUT->box_start('feedback_item_number_'.$align);
echo $itemnr;
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_start('box generalbox boxalign_'.$align);
if ($templateitem->typ != 'pagebreak') {
// echo '<div class="feedback_item_'.$align.'">';
feedback_print_item_preview($templateitem);
} else {
echo $OUTPUT->box_start('feedback_pagebreak');
echo get_string('pagebreak', 'feedback').'<hr class="feedback_pagebreak" />';
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
} else {
echo $OUTPUT->box(get_string('no_items_available_at_this_template', 'feedback'),
'generalbox boxaligncenter boxwidthwide');
}
$form = new mod_feedback_complete_form(mod_feedback_complete_form::MODE_VIEW_TEMPLATE,
$feedbackstructure, 'feedback_preview_form', ['templateid' => $templateid]);
$form->display();
echo $OUTPUT->footer();

View file

@ -24,7 +24,7 @@
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2016040100; // The current module version (Date: YYYYMMDDXX)
$plugin->version = 2016040300; // The current module version (Date: YYYYMMDDXX)
$plugin->requires = 2015111000; // Requires this Moodle version
$plugin->component = 'mod_feedback'; // Full name of the plugin (used for diagnostics)
$plugin->cron = 0;

View file

@ -21,102 +21,48 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package mod_feedback
*/
require_once("../../config.php");
require_once("lib.php");
require_once(__DIR__ . '/../../config.php');
require_once($CFG->dirroot . '/mod/feedback/lib.php');
$id = required_param('id', PARAM_INT);
$courseid = optional_param('courseid', false, PARAM_INT);
$current_tab = 'view';
if (! $cm = get_coursemodule_from_id('feedback', $id)) {
print_error('invalidcoursemodule');
}
list($course, $cm) = get_course_and_cm_from_cmid($id, 'feedback');
require_course_login($course, true, $cm);
$feedback = $PAGE->activityrecord;
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');
}
$feedbackcompletion = new mod_feedback_completion($feedback, $cm, $courseid);
$context = context_module::instance($cm->id);
$feedback_complete_cap = false;
if (has_capability('mod/feedback:complete', $context)) {
$feedback_complete_cap = true;
}
if (!empty($CFG->feedback_allowfullanonymous)
AND $course->id == SITEID
AND $feedback->anonymous == FEEDBACK_ANONYMOUS_YES
AND (!isloggedin() OR isguestuser())) {
// Guests are allowed to complete fully anonymous feedback without having 'mod/feedback:complete' capability.
$feedback_complete_cap = true;
}
//check whether the feedback is located and! started from the mainsite
if ($course->id == SITEID AND !$courseid) {
$courseid = SITEID;
}
require_course_login($course, true, $cm);
if ($course->id == SITEID) {
$PAGE->set_context($context);
$PAGE->set_cm($cm, $course);
$PAGE->set_pagelayout('incourse');
}
$PAGE->set_url('/mod/feedback/view.php', array('id' => $cm->id));
$PAGE->set_title($feedback->name);
$PAGE->set_heading($course->fullname);
// Check whether the feedback is mapped to the given courseid.
if ($course->id == SITEID AND !has_capability('mod/feedback:edititems', $context)) {
if ($DB->get_records('feedback_sitecourse_map', array('feedbackid' => $feedback->id))) {
$params = array('feedbackid' => $feedback->id, 'courseid' => $courseid);
if (!$DB->get_record('feedback_sitecourse_map', $params)) {
if ($courseid == SITEID) {
echo $OUTPUT->header();
echo $OUTPUT->notification(get_string('cannotaccess', 'mod_feedback'));
echo $OUTPUT->footer();
exit;
} else {
print_error('invalidcoursemodule');
}
}
}
// Check access to the given courseid.
if ($courseid AND $courseid != SITEID) {
require_course_login(get_course($courseid)); // This overwrites the object $COURSE .
}
//check whether the given courseid exists
if ($courseid AND $courseid != SITEID) {
if ($course2 = $DB->get_record('course', array('id'=>$courseid))) {
require_course_login($course2); //this overwrites the object $course :-(
$course = $DB->get_record("course", array("id"=>$cm->course)); // the workaround
} else {
print_error('invalidcourseid');
}
// Check whether the feedback is mapped to the given courseid.
if (!has_capability('mod/feedback:edititems', $context) &&
!$feedbackcompletion->check_course_is_mapped()) {
echo $OUTPUT->header();
echo $OUTPUT->notification(get_string('cannotaccess', 'mod_feedback'));
echo $OUTPUT->footer();
exit;
}
// Trigger module viewed event.
$event = \mod_feedback\event\course_module_viewed::create(array(
'objectid' => $feedback->id,
'context' => $context,
'anonymous' => ($feedback->anonymous == FEEDBACK_ANONYMOUS_YES),
'other' => array(
'anonymous' => $feedback->anonymous // Deprecated.
)
));
$event->add_record_snapshot('course_modules', $cm);
$event->add_record_snapshot('course', $course);
$event->add_record_snapshot('feedback', $feedback);
$event = \mod_feedback\event\course_module_viewed::create_from_record($feedback, $cm, $course);
$event->trigger();
/// Print the page header
$strfeedbacks = get_string("modulenameplural", "feedback");
$strfeedback = get_string("modulename", "feedback");
echo $OUTPUT->header();
/// Print the main part of the page
@ -151,80 +97,24 @@ if (has_capability('mod/feedback:edititems', $context)) {
$groupselect = groups_print_activity_menu($cm, $CFG->wwwroot.'/mod/feedback/view.php?id='.$cm->id, true);
$mygroupid = groups_get_activity_group($cm);
echo $OUTPUT->box_start('boxaligncenter');
echo $groupselect.'<div class="clearer">&nbsp;</div>';
$completedscount = feedback_get_completeds_group_count($feedback, $mygroupid);
echo $OUTPUT->box_start('feedback_info');
echo '<span class="feedback_info">';
echo get_string('completed_feedbacks', 'feedback').': ';
echo '</span>';
echo '<span class="feedback_info_value">';
echo $completedscount;
echo '</span>';
echo $OUTPUT->box_end();
$summary = new mod_feedback\output\summary($feedbackcompletion, $mygroupid, true);
echo $OUTPUT->render_from_template('mod_feedback/summary', $summary->export_for_template($OUTPUT));
$params = array('feedback'=>$feedback->id, 'hasvalue'=>1);
$itemscount = $DB->count_records('feedback_item', $params);
echo $OUTPUT->box_start('feedback_info');
echo '<span class="feedback_info">';
echo get_string('questions', 'feedback').': ';
echo '</span>';
echo '<span class="feedback_info_value">';
echo $itemscount;
echo '</span>';
echo $OUTPUT->box_end();
if ($feedback->timeopen) {
echo $OUTPUT->box_start('feedback_info');
echo '<span class="feedback_info">';
echo get_string('feedbackopen', 'feedback').': ';
echo '</span>';
echo '<span class="feedback_info_value">';
echo userdate($feedback->timeopen);
echo '</span>';
echo $OUTPUT->box_end();
if ($pageaftersubmit = $feedbackcompletion->page_after_submit()) {
echo $OUTPUT->heading(get_string("page_after_submit", "feedback"), 3);
echo $OUTPUT->box($pageaftersubmit, 'generalbox feedback_after_submit');
}
if ($feedback->timeclose) {
echo $OUTPUT->box_start('feedback_info');
echo '<span class="feedback_info">';
echo get_string('feedbackclose', 'feedback').': ';
echo '</span>';
echo '<span class="feedback_info_value">';
echo userdate($feedback->timeclose);
echo '</span>';
echo $OUTPUT->box_end();
}
echo $OUTPUT->box_end();
}
if (has_capability('mod/feedback:edititems', $context)) {
require_once($CFG->libdir . '/filelib.php');
$page_after_submit_output = file_rewrite_pluginfile_urls($feedback->page_after_submit,
'pluginfile.php',
$context->id,
'mod_feedback',
'page_after_submit',
0);
echo $OUTPUT->heading(get_string("page_after_submit", "feedback"), 3);
echo $OUTPUT->box_start('generalbox feedback_after_submit');
echo format_text($page_after_submit_output,
$feedback->page_after_submitformat,
array('overflowdiv'=>true));
echo $OUTPUT->box_end();
}
if (!has_capability('mod/feedback:viewreports', $context) &&
feedback_can_view_analysis($feedback, $context, $courseid)) {
$feedbackcompletion->can_view_analysis()) {
$analysisurl = new moodle_url('/mod/feedback/analysis.php', array('id' => $id));
echo '<div class="mdl-align"><a href="'.$analysisurl->out().'">';
echo get_string('completed_feedbacks', 'feedback').'</a>';
echo '</div>';
}
//####### mapcourse-start
if (has_capability('mod/feedback:mapcourse', $context) && $feedback->course == SITEID) {
echo $OUTPUT->box_start('generalbox feedback_mapped_courses');
echo $OUTPUT->heading(get_string("mappedcourses", "feedback"), 3);
@ -233,65 +123,31 @@ if (has_capability('mod/feedback:mapcourse', $context) && $feedback->course == S
echo '<p class="mdl-align">' . html_writer::link($mapurl, get_string('mapcourses', 'feedback')) . '</p>';
echo $OUTPUT->box_end();
}
//####### mapcourse-end
//####### completed-start
if ($feedback_complete_cap) {
echo $OUTPUT->box_start('generalbox boxaligncenter boxwidthwide');
//check, whether the feedback is open (timeopen, timeclose)
$checktime = time();
if (($feedback->timeopen > $checktime) OR
($feedback->timeclose < $checktime AND $feedback->timeclose > 0)) {
if ($feedbackcompletion->can_complete()) {
echo $OUTPUT->box_start('generalbox boxaligncenter');
if (!$feedbackcompletion->is_open()) {
// Feedback is not yet open or is already closed.
echo $OUTPUT->notification(get_string('feedback_is_not_open', 'feedback'));
echo $OUTPUT->continue_button($CFG->wwwroot.'/course/view.php?id='.$course->id);
echo $OUTPUT->box_end();
echo $OUTPUT->footer();
exit;
}
//check multiple Submit
$feedback_can_submit = true;
if ($feedback->multiple_submit == 0 ) {
if (feedback_is_already_submitted($feedback->id, $courseid)) {
$feedback_can_submit = false;
}
}
if ($feedback_can_submit) {
//if the user is not known so we cannot save the values temporarly
if (!isloggedin() or isguestuser()) {
$guestid = sesskey();
echo $OUTPUT->continue_button(course_get_url($courseid ?: $course->id));
} else if ($feedbackcompletion->can_submit()) {
// Display a link to complete feedback or resume.
$completeurl = new moodle_url('/mod/feedback/complete.php',
['id' => $id, 'courseid' => $courseid]);
if ($startpage = $feedbackcompletion->get_resume_page()) {
$completeurl->param('gopage', $startpage);
$label = get_string('continue_the_form', 'feedback');
} else {
$guestid = false;
}
$url_params = array('id'=>$id, 'courseid'=>$courseid, 'gopage'=>0);
$completeurl = new moodle_url('/mod/feedback/complete.php', $url_params);
$feedbackcompletedtmp = feedback_get_current_completed($feedback->id, true, $courseid, $guestid);
if ($feedbackcompletedtmp) {
if ($startpage = feedback_get_page_to_continue($feedback->id, $courseid, $guestid)) {
$completeurl->param('gopage', $startpage);
}
echo '<a href="'.$completeurl->out().'">'.get_string('continue_the_form', 'feedback').'</a>';
} else {
echo '<a href="'.$completeurl->out().'">'.get_string('complete_the_form', 'feedback').'</a>';
$label = get_string('complete_the_form', 'feedback');
}
echo html_writer::div(html_writer::link($completeurl, $label), 'complete-feedback');
} else {
// Feedback was already submitted.
echo $OUTPUT->notification(get_string('this_feedback_is_already_submitted', 'feedback'));
if ($courseid) {
echo $OUTPUT->continue_button($CFG->wwwroot.'/course/view.php?id='.$courseid);
} else {
echo $OUTPUT->continue_button($CFG->wwwroot.'/course/view.php?id='.$course->id);
}
$OUTPUT->continue_button(course_get_url($courseid ?: $course->id));
}
echo $OUTPUT->box_end();
}
//####### completed-end
/// Finish the page
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
echo $OUTPUT->footer();

View file

@ -1,13 +1,10 @@
YUI.add('moodle-mod_feedback-dragdrop', function(Y) {
var DRAGDROPNAME = 'mod_feedback_dragdrop';
var CSS = {
OLDMOVE : 'span.feedback_item_command_move',
OLDMOVEUP : 'span.feedback_item_command_moveup',
OLDMOVEDOWN : 'span.feedback_item_command_movedown',
DRAGAREA : '#feedback_dragarea',
DRAGITEM : 'li.feedback_itemlist',
DRAGLIST : '#feedback_dragarea ul#feedback_draglist',
POSITIONLABEL : '.feedback_item_commands.position',
DRAGITEMCLASS : 'feedback_itemlist',
DRAGITEM : 'div.feedback_itemlist',
DRAGLIST : '#feedback_dragarea form > fieldset > div',
ITEMBOX : '#feedback_item_box_',
DRAGHANDLE : 'itemhandle'
};
@ -31,9 +28,9 @@ YUI.add('moodle-mod_feedback-dragdrop', function(Y) {
//Get the list of li's in the lists and add the drag handle.
basenode = Y.Node.one(CSS.DRAGLIST);
listitems = basenode.all(CSS.DRAGITEM).each(function(v) {
item_id = this.get_node_id(v.get('id')); //Get the id of the feedback item.
item_box = Y.Node.one(CSS.ITEMBOX + item_id); //Get the current item box so we can add the drag handle.
v.insert(this.mydraghandle.cloneNode(true), item_box); //Insert the new handle into the item box.
var item_id = this.get_node_id(v.get('id')); //Get the id of the feedback item.
var item_box = Y.Node.one(CSS.ITEMBOX + item_id); //Get the current item box so we can add the drag handle.
item_box.append(this.mydraghandle.cloneNode(true)); // Insert the new handle into the item box.
}, this);
//We use a delegate to make all items draggable
@ -72,11 +69,6 @@ YUI.add('moodle-mod_feedback-dragdrop', function(Y) {
//Listen for all drag:dropmiss events
del.on('drag:dropmiss', this.drag_dropmiss_handler, this);
// Remove all legacy move icons.
Y.all(CSS.OLDMOVEUP).remove();
Y.all(CSS.OLDMOVEDOWN).remove();
Y.all(CSS.OLDMOVE).remove();
//Create targets for drop.
var droparea = Y.Node.one(CSS.DRAGLIST);
var tar = new Y.DD.Drop({
@ -98,7 +90,7 @@ YUI.add('moodle-mod_feedback-dragdrop', function(Y) {
drop = e.drop.get('node');
//Are we dropping on an li node?
if (drop.get('tagName').toLowerCase() === 'li') {
if (drop.hasClass(CSS.DRAGITEMCLASS)) {
//Are we not going up?
if (!this.goingUp) {
drop = drop.get('nextSibling');
@ -173,19 +165,13 @@ YUI.add('moodle-mod_feedback-dragdrop', function(Y) {
var drop = e.drop.get('node'),
drag = e.drag.get('node');
dragnode = Y.one(drag);
//If we are not on an li, we must have been dropped on a ul.
if (drop.get('tagName').toLowerCase() !== 'li') {
if (!drop.hasClass(CSS.DRAGITEMCLASS)) {
if (!drop.contains(drag)) {
drop.appendChild(drag);
}
myElements = '';
counter = 1;
drop.get('children').each(function(v) {
poslabeltext = '(' + M.util.get_string('position', 'feedback') + ':' + counter + ')';
poslabel = v.one(CSS.POSITIONLABEL);
poslabel.setHTML(poslabeltext);
drop.all(CSS.DRAGITEM).each(function(v) {
myElements = myElements + ',' + this.get_node_id(v.get('id'));
counter++;
}, this);
var spinner = M.util.add_spinner(Y, dragnode);
this.save_item_order(this.cmid, myElements, spinner);
@ -245,7 +231,7 @@ YUI.add('moodle-mod_feedback-dragdrop', function(Y) {
* @return int
*/
get_node_id : function(id) {
return Number(id.replace(/feedback_item_/i, ''));
return Number(id.replace(/^.*feedback_item_/i, ''));
}
}, {

View file

@ -73,10 +73,6 @@ select {
}
}
.path-mod-feedback .feedback_bar_image {
height: 5px; // we should remove the bar height specification in core
}
.forumpost {
.well;
padding: 6px;

File diff suppressed because one or more lines are too long