imlement task oditing for Questtype ?Multiplechoice? (Issue #36)
This commit is contained in:
parent
f85649a6c0
commit
2577779f80
6 changed files with 384 additions and 5 deletions
|
|
@ -226,6 +226,10 @@
|
|||
'choice' => array(
|
||||
'minlength' => 1,
|
||||
'maxlength' => 128
|
||||
),
|
||||
'answer' => array(
|
||||
'minlength' => 1,
|
||||
'maxlength' => 255
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,8 +1,8 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: The Legend of Z\n"
|
||||
"POT-Creation-Date: 2014-08-17 20:38+0100\n"
|
||||
"PO-Revision-Date: 2014-08-17 20:39+0100\n"
|
||||
"POT-Creation-Date: 2014-08-29 15:17+0100\n"
|
||||
"PO-Revision-Date: 2014-08-29 15:17+0100\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: de_DE\n"
|
||||
|
|
@ -106,7 +106,7 @@ msgid "Choice input invalid"
|
|||
msgstr "Die Auswahleingabe ist ungültig"
|
||||
|
||||
#: questtypes/choiceinput/html/edittask.tpl:29
|
||||
#: questtypes/choiceinput/html/edittask.tpl:57
|
||||
#: questtypes/choiceinput/html/edittask.tpl:58
|
||||
#, php-format
|
||||
msgid "Please select correct choice"
|
||||
msgstr "Bitte wähle die richtige Auswahleingabe aus"
|
||||
|
|
@ -133,6 +133,7 @@ msgid "Preview"
|
|||
msgstr "Vorschau"
|
||||
|
||||
#: questtypes/choiceinput/html/edittask.tpl:83
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:79
|
||||
#: questtypes/textinput/html/edittask.tpl:44
|
||||
#: views/html/achievements/conditions.tpl:151
|
||||
#: views/html/achievements/create.tpl:109 views/html/achievements/edit.tpl:112
|
||||
|
|
@ -153,6 +154,41 @@ msgstr "vertikal"
|
|||
msgid "horizontal"
|
||||
msgstr "horizontal"
|
||||
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:12
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:44
|
||||
#, php-format
|
||||
msgid "Answer input is too short (min. %d chars)"
|
||||
msgstr "Die Antwort ist zu kurz (min. %d Zeichen)"
|
||||
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:14
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:46
|
||||
#, php-format
|
||||
msgid "Answer input is too long (max. %d chars)"
|
||||
msgstr "Die Antwort ist zu lang (max. %d Zeichen)"
|
||||
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:16
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:48
|
||||
msgid "Answer input invalid"
|
||||
msgstr "Die Anwort ist ungültig"
|
||||
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:30
|
||||
msgid "Questions"
|
||||
msgstr "Fragen"
|
||||
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:34
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:88
|
||||
msgid "Question"
|
||||
msgstr "Frage"
|
||||
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:71
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:90
|
||||
msgid "Remove question"
|
||||
msgstr "Frage entfernen"
|
||||
|
||||
#: questtypes/multiplechoice/html/edittask.tpl:75
|
||||
msgid "Add question"
|
||||
msgstr "Frage hinzufügen"
|
||||
|
||||
#: questtypes/multiplechoice/html/quest.tpl:3
|
||||
#, php-format
|
||||
msgid "Question %d of %d"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,12 @@
|
|||
*/
|
||||
class MultiplechoiceQuesttypeController extends \hhu\z\controllers\QuesttypeController
|
||||
{
|
||||
/**
|
||||
* Required components
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $components = array('validation');
|
||||
|
||||
|
||||
|
||||
|
|
@ -219,7 +225,7 @@
|
|||
|
||||
|
||||
/**
|
||||
* TODO Action: edittask.
|
||||
* Action: edittask.
|
||||
*
|
||||
* Edit the task of a Quest.
|
||||
*
|
||||
|
|
@ -229,6 +235,94 @@
|
|||
*/
|
||||
public function edittask($seminary, $questgroup, $quest)
|
||||
{
|
||||
// Get questions
|
||||
$questions = $this->Multiplechoice->getQuestionsOfQuest($quest['id']);
|
||||
foreach($questions as &$question) {
|
||||
$question['answers'] = $this->Multiplechoice->getAnswersOfQuestion($question['id']);
|
||||
}
|
||||
|
||||
// Values
|
||||
$validations = array();
|
||||
|
||||
// Save data
|
||||
if($this->request->getRequestMethod() == 'POST' && !is_null($this->request->getPostParam('save')))
|
||||
{
|
||||
// Get params and validate them
|
||||
$questions = $this->request->getPostParam('questions');
|
||||
if(is_null($questions)) {
|
||||
$questions = array();
|
||||
}
|
||||
$questions = array_values($questions);
|
||||
foreach($questions as $questionIndex => &$question)
|
||||
{
|
||||
// Validate answers
|
||||
$question['answers'] = array_values($question['answers']);
|
||||
foreach($question['answers'] as $answerIndex => &$answer)
|
||||
{
|
||||
$answerValidation = $this->Validation->validate($answer['answer'], \nre\configs\AppConfig::$validation['answer']);
|
||||
if($answerValidation !== true)
|
||||
{
|
||||
if(!array_key_exists($questionIndex, $validations) || !is_array($validations[$questionIndex])) {
|
||||
$validations[$questionIndex] = array();
|
||||
}
|
||||
if(!array_key_exists('answers', $validations[$questionIndex])) {
|
||||
$validations[$questionIndex]['answers'] = array();
|
||||
}
|
||||
$validations[$questionIndex]['answers'][$answerIndex] = $answerValidation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save and redirect
|
||||
if(empty($validations))
|
||||
{
|
||||
// Save questions
|
||||
foreach($questions as $questionIndex => &$question)
|
||||
{
|
||||
// Save question
|
||||
$this->Multiplechoice->setQuestionForQuest(
|
||||
$this->Auth->getUserId(),
|
||||
$quest['id'],
|
||||
$questionIndex + 1,
|
||||
$question['question']
|
||||
);
|
||||
|
||||
// Save answers
|
||||
foreach($question['answers'] as $answerIndex => &$answer)
|
||||
{
|
||||
$this->Multiplechoice->setAnswerForQuestion(
|
||||
$this->Auth->getUserId(),
|
||||
$quest['id'],
|
||||
$questionIndex + 1,
|
||||
$answerIndex + 1,
|
||||
$answer['answer'],
|
||||
array_key_exists('tick', $answer)
|
||||
);
|
||||
}
|
||||
|
||||
// Delete deleted answers
|
||||
$this->Multiplechoice->deleteAnswersOfQuestion(
|
||||
$quest['id'],
|
||||
$questionIndex + 1,
|
||||
count($question['answers'])
|
||||
);
|
||||
}
|
||||
|
||||
// Delete deleted questions
|
||||
$this->Multiplechoice->deleteQuestionsOfQuest(
|
||||
$quest['id'],
|
||||
count($questions)
|
||||
);
|
||||
|
||||
// Redirect
|
||||
$this->redirect($this->linker->link(array('quest', $seminary['url'], $questgroup['url'], $quest['url']), 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pass data to view
|
||||
$this->set('questions', $questions);
|
||||
$this->set('validations', $validations);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -153,6 +153,115 @@
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a question for a multiplechoice Quest.
|
||||
*
|
||||
* @param int $userId ID of user
|
||||
* @param int $questId ID of Quest to set question for
|
||||
* @param int $pos Position of question
|
||||
* @param string $question Question text
|
||||
*/
|
||||
public function setQuestionForQuest($userId, $questId, $pos, $question)
|
||||
{
|
||||
$this->db->query(
|
||||
'INSERT INTO questtypes_multiplechoice '.
|
||||
'(created_user_id, quest_id, pos, question) '.
|
||||
'VALUES '.
|
||||
'(?, ?, ?, ?) '.
|
||||
'ON DUPLICATE KEY UPDATE '.
|
||||
'question = ?',
|
||||
'iiiss',
|
||||
$userId,
|
||||
$questId,
|
||||
$pos,
|
||||
$question,
|
||||
$question
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete questions of a Quest.
|
||||
*
|
||||
* @param int $questId ID of Quest to delete question of
|
||||
* @param int $offset Only delete questions after this position
|
||||
*/
|
||||
public function deleteQuestionsOfQuest($questId, $offset)
|
||||
{
|
||||
$this->db->query(
|
||||
'DELETE FROM questtypes_multiplechoice '.
|
||||
'WHERE quest_id = ? AND pos > ?',
|
||||
'ii',
|
||||
$questId,
|
||||
$offset
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set an answer for a question.
|
||||
*
|
||||
* @param int $userId ID of user
|
||||
* @param int $questId ID of Quest to set answer for
|
||||
* @param int $questionPos Position of question
|
||||
* @param int $answerPos Position of answer
|
||||
* @param string $answer Answer text
|
||||
* @param boolean $tick Whether answer is correct or not
|
||||
*/
|
||||
public function setAnswerForQuestion($userId, $questId, $questionPos, $answerPos, $answer, $tick)
|
||||
{
|
||||
// Get question
|
||||
$question = $this->getQuestionOfQuest($questId, $questionPos);
|
||||
if(is_null($question)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add answer
|
||||
$this->db->query(
|
||||
'INSERT INTO questtypes_multiplechoice_answers '.
|
||||
'(created_user_id, questtypes_multiplechoice_id, pos, answer, tick) '.
|
||||
'VALUES '.
|
||||
'(?, ?, ?, ?, ?) '.
|
||||
'ON DUPLICATE KEY UPDATE '.
|
||||
'answer = ?, tick = ?',
|
||||
'iiisisi',
|
||||
$userId,
|
||||
$question['id'],
|
||||
$answerPos,
|
||||
$answer,
|
||||
$tick,
|
||||
$answer,
|
||||
$tick
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete answers of a question.
|
||||
*
|
||||
* @param int $questId ID of Quest to delete answers for
|
||||
* @param int $questionPos Position of question
|
||||
* @param int $offset Only delete answers after this position
|
||||
*/
|
||||
public function deleteAnswersOfQuestion($questId, $questionPos, $offset)
|
||||
{
|
||||
// Get question
|
||||
$question = $this->getQuestionOfQuest($questId, $questionPos);
|
||||
if(is_null($question)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete answer
|
||||
$this->db->query(
|
||||
'DELETE FROM questtypes_multiplechoice_answers '.
|
||||
'WHERE questtypes_multiplechoice_id = ? AND pos > ?',
|
||||
'ii',
|
||||
$question['id'],
|
||||
$offset
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1,137 @@
|
|||
<p>TODO</p>
|
||||
<?php if(!empty($validations)) : ?>
|
||||
<ul>
|
||||
<?php foreach($validations as &$question) : ?>
|
||||
<li>
|
||||
<?php if(!empty($question['answers'])) : ?>
|
||||
<?php foreach($question['answers'] as &$answer) : ?>
|
||||
<ul>
|
||||
<?php foreach($answer as $setting => $value) : ?>
|
||||
<li>
|
||||
<?php
|
||||
switch($setting) {
|
||||
case 'minlength': printf(_('Answer input is too short (min. %d chars)'), $value);
|
||||
break;
|
||||
case 'maxlength': printf(_('Answer input is too long (max. %d chars)'), $value);
|
||||
break;
|
||||
default: echo _('Answer input invalid');
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
<form method="post">
|
||||
<fieldset>
|
||||
<legend><?=_('Questions')?></legend>
|
||||
<ol id="questions">
|
||||
<?php foreach($questions as $questionIndex => &$question) : ?>
|
||||
<li id="question-<?=$questionIndex?>">
|
||||
<?=_('Question')?>:
|
||||
<textarea id="question-<?=$questionIndex?>-question" name="questions[<?=$questionIndex?>][question]"><?=$question['question']?></textarea>
|
||||
|
||||
<?php if(!empty($validations) && array_key_exists($questionIndex, $validations) && !empty($validations[$questionIndex]) && $validations[$questionIndex]['answers'] !== true) : ?>
|
||||
<ul>
|
||||
<?php foreach($validations[$questionIndex]['answers'] as &$answer) : ?>
|
||||
<?php foreach($answer as $setting => $value) : ?>
|
||||
<li>
|
||||
<?php
|
||||
switch($setting) {
|
||||
case 'minlength': printf(_('Answer input is too short (min. %d chars)'), $value);
|
||||
break;
|
||||
case 'maxlength': printf(_('Answer input is too long (max. %d chars)'), $value);
|
||||
break;
|
||||
default: echo _('Answer input invalid');
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
<?php endforeach ?>
|
||||
</ul>
|
||||
<?php endif ?>
|
||||
|
||||
<ul>
|
||||
<?php foreach($question['answers'] as $answerIndex => &$answer) : ?>
|
||||
<li>
|
||||
<input id="question-<?=$questionIndex?>-answer-<?=$answerIndex?>-tick" type="checkbox" name="questions[<?=$questionIndex?>][answers][<?=$answerIndex?>][tick]" <?php if(array_key_exists('tick', $answer) && $answer['tick']) : ?>checked="checked"<?php endif ?> />
|
||||
<label for="questions[<?=$questionIndex?>][answers][<?=$answerIndex?>][tick]">
|
||||
<input id="question-<?=$questionIndex?>-answer-<?=$answerIndex?>" type="text" name="questions[<?=$questionIndex?>][answers][<?=$answerIndex?>][answer]" value="<?=$answer['answer']?>" <?php if(!empty($validations) && array_key_exists($questionIndex, $validations) && !empty($validations[$questionIndex]) && array_key_exists($answerIndex, $validations[$questionIndex]['answers']) && $validations[$questionIndex]['answers'][$answerIndex] !== true) : ?>class="invalid"<?php endif ?> />
|
||||
</label>
|
||||
<button class="remove-answer" type="button">−</button>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
<li>
|
||||
<button class="add-answer" type="button">+</button>
|
||||
</li>
|
||||
</ul>
|
||||
<button class="remove-question" type="button"><?=_('Remove question')?></button>
|
||||
</li>
|
||||
<?php endforeach ?>
|
||||
<li>
|
||||
<button class="add-question" type="button"><?=_('Add question')?></button>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
<input type="submit" name="save" value="<?=_('save')?>" />
|
||||
</form>
|
||||
|
||||
<script>
|
||||
var questionIndex = <?=count($questions)?>;
|
||||
var answerIndices = new Array(<?=count($questions)?>);
|
||||
<?php foreach($questions as $index => &$question) : ?>
|
||||
answerIndices[<?=$index?>] = <?=count($question['answers'])?>;
|
||||
<?php endforeach?>
|
||||
var questionElement = '<?=_('Question')?>: <textarea name="questions[QUESTIONINDEX][question]"></textarea>' +
|
||||
'<ul><li><button class="add-answer" type="button">+</button></li></ul>' +
|
||||
'<button class="remove-question" type="button"><?=_('Remove question')?></button>';
|
||||
var answerElement = '<input id="question-QUESTIONINDEX-answer-ANSWERINDEX-tick" type="checkbox" name="questions[QUESTIONINDEX][answers][ANSWERINDEX][tick]" />' +
|
||||
'<label for="questions[QUESTIONINDEX][answers][ANSWERINDEX][tick]">' +
|
||||
'<input id="question-QUESTIONINDEX-answer-ANSWERINDEX" type="text" name="questions[QUESTIONINDEX][answers][ANSWERINDEX][answer]" value="" />' +
|
||||
'</label>' +
|
||||
'<button class="remove-answer" type="button">−</button>';
|
||||
|
||||
$(".add-question").click(addQuestion);
|
||||
$(".remove-question").click(removeQuestion);
|
||||
$(".add-answer").click(addAnswer);
|
||||
$(".remove-answer").click(removeAnswer);
|
||||
|
||||
function addQuestion(event)
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
answerIndices.push(0);
|
||||
var element = '<li id="question-'+questionIndex+'">' + questionElement.replace(/QUESTIONINDEX/g, questionIndex) + '</li>';
|
||||
$(event.target).parent().before(element);
|
||||
$("#question-"+questionIndex+" .remove-question").click(removeQuestion);
|
||||
$("#question-"+questionIndex+" .add-answer").click(addAnswer);
|
||||
$("#question-"+questionIndex+" .remove-answer").click(removeAnswer);
|
||||
|
||||
questionIndex++;
|
||||
}
|
||||
function removeQuestion(event)
|
||||
{
|
||||
event.preventDefault();
|
||||
$(event.target).parent().remove();
|
||||
}
|
||||
function addAnswer(event)
|
||||
{
|
||||
event.preventDefault();
|
||||
|
||||
var parent = $(event.target).parent();
|
||||
var index = parent.parent().parent().attr('id').substring(9);
|
||||
var element = '<li>' + answerElement.replace(/QUESTIONINDEX/g, index).replace(/ANSWERINDEX/g, answerIndices[index]) + '</li>';
|
||||
$(event.target).parent().before(element);
|
||||
$(".remove-answer").click(removeAnswer);
|
||||
|
||||
answerIndices[index]++;
|
||||
}
|
||||
function removeAnswer(event)
|
||||
{
|
||||
event.preventDefault();
|
||||
$(event.target).parent().remove();
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue