Autoría | Ultima modificación | Ver Log |
<?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/>.
/**
* This page handles the main question editing screen.
*
* @package mod_questionnaire
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright 2016 Mike Churchward (mike.churchward@poetopensource.org)
*/
require_once("../../config.php");
require_once($CFG->dirroot.'/mod/questionnaire/questionnaire.class.php');
require_once($CFG->dirroot.'/mod/questionnaire/classes/question/question.php'); // Needed for question type constants.
$id = required_param('id', PARAM_INT); // Course module ID.
$action = optional_param('action', 'main', PARAM_ALPHA); // Screen.
$qid = optional_param('qid', 0, PARAM_INT); // Question id.
$moveq = optional_param('moveq', 0, PARAM_INT); // Question id to move.
$delq = optional_param('delq', 0, PARAM_INT); // Question id to delete.
$qtype = optional_param('type_id', 0, PARAM_INT); // Question type.
$currentgroupid = optional_param('group', 0, PARAM_INT); // Group id.
if (! $cm = get_coursemodule_from_id('questionnaire', $id)) {
throw new \moodle_exception('invalidcoursemodule', 'mod_questionnaire');
}
if (! $course = $DB->get_record("course", array("id" => $cm->course))) {
throw new \moodle_exception('coursemisconf', 'mod_questionnaire');
}
if (! $questionnaire = $DB->get_record("questionnaire", array("id" => $cm->instance))) {
throw new \moodle_exception('invalidcoursemodule', 'mod_questionnaire');
}
require_course_login($course, true, $cm);
$context = context_module::instance($cm->id);
$url = new moodle_url($CFG->wwwroot.'/mod/questionnaire/questions.php');
$url->param('id', $id);
if ($qid) {
$url->param('qid', $qid);
}
$PAGE->set_url($url);
$PAGE->set_context($context);
$questionnaire = new questionnaire($course, $cm, 0, $questionnaire);
// Add renderer and page objects to the questionnaire object for display use.
$questionnaire->add_renderer($PAGE->get_renderer('mod_questionnaire'));
$questionnaire->add_page(new \mod_questionnaire\output\questionspage());
if (!$questionnaire->capabilities->editquestions) {
throw new \moodle_exception('nopermissions', 'mod_questionnaire');
}
$questionnairehasdependencies = $questionnaire->has_dependencies();
$dependants = null;
if (!isset($SESSION->questionnaire)) {
$SESSION->questionnaire = new stdClass();
}
$SESSION->questionnaire->current_tab = 'questions';
$reload = false;
$sid = $questionnaire->survey->id;
// Process form data.
// Delete question button has been pressed in questions_form AND deletion has been confirmed on the confirmation page.
if ($delq) {
$qid = $delq;
$sid = $questionnaire->survey->id;
$questionnaireid = $questionnaire->id;
// Need to reload questions before setting deleted question to 'y'.
$questions = $DB->get_records('questionnaire_question', ['surveyid' => $sid, 'deleted' => 'n'], 'id') ?? [];
$DB->set_field('questionnaire_question', 'deleted', 'y', ['id' => $qid, 'surveyid' => $sid]);
// Delete all dependency records for this question.
questionnaire_delete_dependencies($qid);
// Just in case the page is refreshed (F5) after a question has been deleted.
if (isset($questions[$qid])) {
$select = 'surveyid = '.$sid.' AND deleted = \'n\' AND position > '.
$questions[$qid]->position;
} else {
redirect($CFG->wwwroot.'/mod/questionnaire/questions.php?id='.$questionnaire->cm->id);
}
if ($records = $DB->get_records_select('questionnaire_question', $select, null, 'position ASC')) {
foreach ($records as $record) {
$DB->set_field('questionnaire_question', 'position', $record->position - 1, array('id' => $record->id));
}
}
// Delete section breaks without asking for confirmation.
// No need to delete responses to those "question types" which are not real questions.
if (!$questionnaire->questions[$qid]->supports_responses()) {
$reload = true;
} else {
// Delete responses to that deleted question.
questionnaire_delete_responses($qid);
// If no questions left in this questionnaire, remove all responses.
if ($DB->count_records('questionnaire_question', ['surveyid' => $sid, 'deleted' => 'n']) == 0) {
$DB->delete_records('questionnaire_response', ['questionnaireid' => $qid]);
}
}
// Log question deleted event.
$context = context_module::instance($questionnaire->cm->id);
$questiontype = \mod_questionnaire\question\question::qtypename($questionnaire->questions[$qid]->type_id);
$params = array(
'context' => $context,
'courseid' => $questionnaire->course->id,
'other' => array('questiontype' => $questiontype)
);
$event = \mod_questionnaire\event\question_deleted::create($params);
$event->trigger();
if ($questionnairehasdependencies) {
$SESSION->questionnaire->validateresults = questionnaire_check_page_breaks($questionnaire);
}
$reload = true;
}
if ($action == 'main') {
$questionsform = new \mod_questionnaire\questions_form('questions.php', $moveq);
$sdata = clone($questionnaire->survey);
$sdata->sid = $questionnaire->survey->id;
$sdata->id = $cm->id;
if (!empty($questionnaire->questions)) {
$pos = 1;
foreach ($questionnaire->questions as $qidx => $question) {
$sdata->{'pos_'.$qidx} = $pos;
$pos++;
}
}
$questionsform->set_data($sdata);
if ($questionsform->is_cancelled()) {
// Switch to main screen.
$action = 'main';
redirect($CFG->wwwroot.'/mod/questionnaire/questions.php?id='.$questionnaire->cm->id);
$reload = true;
}
if ($qformdata = $questionsform->get_data()) {
// Quickforms doesn't return values for 'image' input types using 'exportValue', so we need to grab
// it from the raw submitted data.
$exformdata = data_submitted();
if (isset($exformdata->movebutton)) {
$qformdata->movebutton = $exformdata->movebutton;
} else if (isset($exformdata->moveherebutton)) {
$qformdata->moveherebutton = $exformdata->moveherebutton;
} else if (isset($exformdata->editbutton)) {
$qformdata->editbutton = $exformdata->editbutton;
} else if (isset($exformdata->removebutton)) {
$qformdata->removebutton = $exformdata->removebutton;
} else if (isset($exformdata->requiredbutton)) {
$qformdata->requiredbutton = $exformdata->requiredbutton;
}
// Insert a section break.
if (isset($qformdata->removebutton)) {
// Need to use the key, since IE returns the image position as the value rather than the specified
// value in the <input> tag.
$qid = key($qformdata->removebutton);
$qtype = $questionnaire->questions[$qid]->type_id;
// Delete section breaks without asking for confirmation.
if ($qtype == QUESPAGEBREAK) {
redirect($CFG->wwwroot.'/mod/questionnaire/questions.php?id='.$questionnaire->cm->id.'&delq='.$qid);
}
$action = "confirmdelquestion";
if ($questionnairehasdependencies) {
// Important: due to possibly multiple parents per question
// just remove the dependency and inform the user about it.
$dependants = $questionnaire->get_all_dependants($qid);
if (!(empty($dependants->directs) && empty($dependants->indirects))) {
$action = "confirmdelquestionparent";
}
}
} else if (isset($qformdata->editbutton)) {
// Switch to edit question screen.
$action = 'question';
// Need to use the key, since IE returns the image position as the value rather than the specified
// value in the <input> tag.
$qid = key($qformdata->editbutton);
$reload = true;
} else if (isset($qformdata->requiredbutton)) {
// Need to use the key, since IE returns the image position as the value rather than the specified
// value in the <input> tag.
$qid = key($qformdata->requiredbutton);
if ($questionnaire->questions[$qid]->required()) {
$questionnaire->questions[$qid]->set_required(false);
} else {
$questionnaire->questions[$qid]->set_required(true);
}
$reload = true;
} else if (isset($qformdata->addqbutton)) {
if ($qformdata->type_id == QUESPAGEBREAK) { // Adding section break is handled right away....
$questionrec = new stdClass();
$questionrec->surveyid = $qformdata->sid;
$questionrec->type_id = QUESPAGEBREAK;
$questionrec->content = 'break';
$question = \mod_questionnaire\question\question::question_builder(QUESPAGEBREAK);
$question->add($questionrec);
$reload = true;
} else {
// Switch to edit question screen.
$action = 'question';
$qtype = $qformdata->type_id;
$qid = 0;
$reload = true;
}
} else if (isset($qformdata->movebutton)) {
// Nothing I do will seem to reload the form with new data, except for moving away from the page, so...
redirect($CFG->wwwroot.'/mod/questionnaire/questions.php?id='.$questionnaire->cm->id.
'&moveq='.key($qformdata->movebutton));
$reload = true;
} else if (isset($qformdata->moveherebutton)) {
// Need to use the key, since IE returns the image position as the value rather than the specified
// value in the <input> tag.
// No need to move question if new position = old position!
$qpos = key($qformdata->moveherebutton);
if ($qformdata->moveq != $qpos) {
$questionnaire->move_question($qformdata->moveq, $qpos);
}
if ($questionnairehasdependencies) {
$SESSION->questionnaire->validateresults = questionnaire_check_page_breaks($questionnaire);
}
// Nothing I do will seem to reload the form with new data, except for moving away from the page, so...
redirect($CFG->wwwroot.'/mod/questionnaire/questions.php?id='.$questionnaire->cm->id);
$reload = true;
} else if (isset($qformdata->validate)) {
// Validates page breaks for depend questions.
$SESSION->questionnaire->validateresults = questionnaire_check_page_breaks($questionnaire);
$reload = true;
}
}
} else if ($action == 'question') {
$question = questionnaire_prep_for_questionform($questionnaire, $qid, $qtype);
$questionsform = new \mod_questionnaire\edit_question_form('questions.php');
$questionsform->set_data($question);
if ($questionsform->is_cancelled()) {
// Switch to main screen.
$action = 'main';
$reload = true;
} else if ($qformdata = $questionsform->get_data()) {
// Saving question data.
if (isset($qformdata->makecopy)) {
$qformdata->qid = 0;
}
$question->form_update($qformdata, $questionnaire);
// Make these field values 'sticky' for further new questions.
if (!isset($qformdata->required)) {
$qformdata->required = 'n';
}
questionnaire_check_page_breaks($questionnaire);
$SESSION->questionnaire->required = $qformdata->required;
$SESSION->questionnaire->type_id = $qformdata->type_id;
// Switch to main screen.
$action = 'main';
$reload = true;
}
// Log question created event.
if (isset($qformdata)) {
$context = context_module::instance($questionnaire->cm->id);
$questiontype = \mod_questionnaire\question\question::qtypename($qformdata->type_id);
$params = array(
'context' => $context,
'courseid' => $questionnaire->course->id,
'other' => array('questiontype' => $questiontype)
);
$event = \mod_questionnaire\event\question_created::create($params);
$event->trigger();
}
$questionsform->set_data($question);
}
// Reload the form data if called for...
if ($reload) {
unset($questionsform);
$questionnaire = new questionnaire($course, $cm, $questionnaire->id, null);
// Add renderer and page objects to the questionnaire object for display use.
$questionnaire->add_renderer($PAGE->get_renderer('mod_questionnaire'));
$questionnaire->add_page(new \mod_questionnaire\output\questionspage());
if ($action == 'main') {
$questionsform = new \mod_questionnaire\questions_form('questions.php', $moveq);
$sdata = clone($questionnaire->survey);
$sdata->sid = $questionnaire->survey->id;
$sdata->id = $cm->id;
if (!empty($questionnaire->questions)) {
$pos = 1;
foreach ($questionnaire->questions as $qidx => $question) {
$sdata->{'pos_'.$qidx} = $pos;
$pos++;
}
}
$questionsform->set_data($sdata);
} else if ($action == 'question') {
$question = questionnaire_prep_for_questionform($questionnaire, $qid, $qtype);
$questionsform = new \mod_questionnaire\edit_question_form('questions.php');
$questionsform->set_data($question);
}
}
// Print the page header.
if ($action == 'question') {
if (isset($question->qid)) {
$streditquestion = get_string('editquestion', 'questionnaire', questionnaire_get_type($question->type_id));
} else {
$streditquestion = get_string('addnewquestion', 'questionnaire', questionnaire_get_type($question->type_id));
}
} else {
$streditquestion = get_string('managequestions', 'questionnaire');
}
$PAGE->set_title($streditquestion);
$PAGE->set_heading(format_string($course->fullname));
$PAGE->navbar->add($streditquestion);
echo $questionnaire->renderer->header();
require('tabs.php');
if ($action == "confirmdelquestion" || $action == "confirmdelquestionparent") {
$qid = key($qformdata->removebutton);
$question = $questionnaire->questions[$qid];
$qtype = $question->type_id;
// Count responses already saved for that question.
$countresps = 0;
if ($qtype != QUESSECTIONTEXT) {
$responsetable = $DB->get_field('questionnaire_question_type', 'response_table', array('typeid' => $qtype));
if (!empty($responsetable)) {
$countresps = $DB->count_records('questionnaire_'.$responsetable, array('question_id' => $qid));
}
}
// Needed to print potential media in question text.
// If question text is "empty", i.e. 2 non-breaking spaces were inserted, do not display any question text.
if ($question->content == '<p> </p>') {
$question->content = '';
}
$qname = '';
if ($question->name) {
$qname = ' ('.$question->name.')';
}
$num = get_string('position', 'questionnaire');
$pos = $question->position.$qname;
$msg = '<div class="warning centerpara"><p>'.get_string('confirmdelquestion', 'questionnaire', $pos).'</p>';
if ($countresps !== 0) {
$msg .= '<p>'.get_string('confirmdelquestionresps', 'questionnaire', $countresps).'</p>';
}
$msg .= '</div>';
$msg .= '<div class = "qn-container">'.$num.' '.$pos.'<div class="qn-question">'.$question->content.'</div></div>';
$args = "id={$questionnaire->cm->id}";
$urlno = new moodle_url("/mod/questionnaire/questions.php?{$args}");
$args .= "&delq={$qid}";
$urlyes = new moodle_url("/mod/questionnaire/questions.php?{$args}");
$buttonyes = new single_button($urlyes, get_string('yes'));
$buttonno = new single_button($urlno, get_string('no'));
if ($action == "confirmdelquestionparent") {
$strnum = get_string('position', 'questionnaire');
$qid = key($qformdata->removebutton);
if ($dependants) {
// Show the dependencies and inform about the dependencies to be removed.
// Split dependencies in direct and indirect ones to separate for the confirm-dialogue.
// Only direct ones will be deleted. List direct dependencies.
$msg .= $questionnaire->renderer->dependency_warnings($dependants->directs, 'directwarnings', $strnum);
// List indirect dependencies.
$msg .= $questionnaire->renderer->dependency_warnings($dependants->indirects, 'indirectwarnings', $strnum);
}
}
$questionnaire->page->add_to_page('formarea', $questionnaire->renderer->confirm($msg, $buttonyes, $buttonno));
} else {
$questionnaire->page->add_to_page('formarea', $questionsform->render());
}
echo $questionnaire->renderer->render($questionnaire->page);
echo $questionnaire->renderer->footer();