diff --git a/main/exercice/Draggable.php b/main/exercice/Draggable.php
new file mode 100644
index 0000000000..98891099ae
--- /dev/null
+++ b/main/exercice/Draggable.php
@@ -0,0 +1,245 @@
+
+ */
+class Draggable extends Matching
+{
+
+ static $typePicture = 'matching.png';
+ static $explanationLangVar = 'Draggable';
+
+ /**
+ * Class constructor
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ $this->type = DRAGGABLE;
+ $this->isContent = $this->getIsContent();
+ }
+
+ /**
+ * Function which redefines Question::createAnswersForm
+ * @param FormValidator $form
+ */
+ public function createAnswersForm($form)
+ {
+ $defaults = array();
+ $nb_matches = $nb_options = 2;
+ $matches = array();
+
+ $answer = null;
+ $counter = 1;
+
+ if (isset($this->id)) {
+ $answer = new Answer($this->id);
+ $answer->read();
+
+ if (count($answer->nbrAnswers) > 0) {
+ for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
+ $correct = $answer->isCorrect($i);
+ if (empty($correct)) {
+ $matches[$answer->selectAutoId($i)] = chr(64 + $counter);
+ $counter++;
+ }
+ }
+ }
+ }
+
+ if ($form->isSubmitted()) {
+ $nb_matches = $form->getSubmitValue('nb_matches');
+ $nb_options = $form->getSubmitValue('nb_options');
+
+ if (isset($_POST['lessMatches'])) {
+ $nb_matches--;
+ }
+
+ if (isset($_POST['moreMatches'])) {
+ $nb_matches++;
+ }
+
+ if (isset($_POST['lessOptions'])) {
+ $nb_options--;
+ }
+
+ if (isset($_POST['moreOptions'])) {
+ $nb_options++;
+ }
+ } else if (!empty($this->id)) {
+ if (count($answer->nbrAnswers) > 0) {
+ $nb_matches = $nb_options = 0;
+
+ for ($i = 1; $i <= $answer->nbrAnswers; $i++) {
+ if ($answer->isCorrect($i)) {
+ $nb_matches++;
+ $defaults['answer[' . $nb_matches . ']'] = $answer->selectAnswer($i);
+ $defaults['weighting[' . $nb_matches . ']'] = float_format($answer->selectWeighting($i), 1);
+ $defaults['matches[' . $nb_matches . ']'] = $answer->correct[$i];
+ } else {
+ $nb_options++;
+ $defaults['option[' . $nb_options . ']'] = $answer->selectAnswer($i);
+ }
+ }
+ }
+ } else {
+ $defaults['answer[1]'] = get_lang('DefaultMakeCorrespond1');
+ $defaults['answer[2]'] = get_lang('DefaultMakeCorrespond2');
+ $defaults['matches[2]'] = '2';
+ $defaults['option[1]'] = get_lang('DefaultMatchingOptA');
+ $defaults['option[2]'] = get_lang('DefaultMatchingOptB');
+ }
+
+ if (empty($matches)) {
+ for ($i = 1; $i <= $nb_options; ++$i) {
+ // fill the array with A, B, C.....
+ $matches[$i] = chr(64 + $i);
+ }
+ } else {
+ for ($i = $counter; $i <= $nb_options; ++$i) {
+ // fill the array with A, B, C.....
+ $matches[$i] = chr(64 + $i);
+ }
+ }
+
+ $form->addElement('hidden', 'nb_matches', $nb_matches);
+ $form->addElement('hidden', 'nb_options', $nb_options);
+
+ // DISPLAY MATCHES
+ $html = '
+
+
+ | ' . get_lang('Answer') . ' |
+ ' . get_lang('MatchesTo') . ' |
+ ' . get_lang('Weighting') . ' |
+
+
+ ';
+
+ $form->addHeader(get_lang('MakeCorrespond'));
+ $form->addHtml($html);
+
+ if ($nb_matches < 1) {
+ $nb_matches = 1;
+ Display::display_normal_message(get_lang('YouHaveToCreateAtLeastOneAnswer'));
+ }
+
+ for ($i = 1; $i <= $nb_matches; ++$i) {
+ $renderer = &$form->defaultRenderer();
+
+ $renderer->setElementTemplate(
+ '{error}{element} | ',
+ "answer[$i]"
+ );
+
+ $renderer->setElementTemplate(
+ '{error}{element} | ',
+ "matches[$i]"
+ );
+
+ $renderer->setElementTemplate(
+ '{error}{element} | ',
+ "weighting[$i]"
+ );
+
+ $form->addHtml('');
+ $form->addText("answer[$i]", null);
+ $form->addSelect("matches[$i]", null, $matches);
+ $form->addText("weighting[$i]", null, true, ['value' => 10]);
+ $form->addHtml('
');
+ }
+
+ $form->addHtml('
');
+ $group = array();
+
+ $renderer->setElementTemplate(
+ '', 'moreMatches');
+
+ global $text;
+
+ $group = [
+ $form->addButtonDelete(get_lang('DelElem'), 'lessMatches', true),
+ $form->addButtonCreate(get_lang('AddElem'), 'moreMatches', true),
+ $form->addButtonSave($text, 'submitQuestion', true)
+ ];
+
+ $form->addGroup($group);
+
+ if (!empty($this->id)) {
+ $form->setDefaults($defaults);
+ } else {
+ if ($this->isContent == 1) {
+ $form->setDefaults($defaults);
+ }
+ }
+
+ $form->setConstants(
+ [
+ 'nb_matches' => $nb_matches,
+ 'nb_options' => $nb_options
+ ]
+ );
+ }
+
+ /**
+ * Abstract function which creates the form to create / edit the answers of the question
+ * @param FormValidator $form
+ */
+ public function processAnswersCreation($form)
+ {
+ $nb_matches = $form->getSubmitValue('nb_matches');
+ $this->weighting = 0;
+ $position = 0;
+
+ $objAnswer = new Answer($this->id);
+
+ // Insert the options
+ for ($i = 1; $i <= $nb_matches; ++$i) {
+ $position++;
+
+ $objAnswer->createAnswer($position, 0, '', 0, $position);
+ }
+
+ // Insert the answers
+ for ($i = 1; $i <= $nb_matches; ++$i) {
+ $position++;
+
+ $answer = $form->getSubmitValue('answer[' . $i . ']');
+ $matches = $form->getSubmitValue('matches[' . $i . ']');
+ $weighting = $form->getSubmitValue('weighting[' . $i . ']');
+ $this->weighting += $weighting;
+ $objAnswer->createAnswer($answer, $matches, '', $weighting, $position);
+ }
+
+ $objAnswer->save();
+ $this->save();
+ }
+
+ /**
+ * Shows question title an description
+ * @param string $feedback_type
+ * @param int $counter
+ * @param float $score
+ * @return string
+ */
+ public function return_header($feedback_type = null, $counter = null, $score = null)
+ {
+ $header = parent::return_header($feedback_type, $counter, $score);
+ $header .= '
+
+ | ' . get_lang('ElementList') . ' |
+ ' . get_lang('CorrespondsTo') . ' |
+
';
+
+ return $header;
+ }
+
+}
diff --git a/main/exercice/question.class.php b/main/exercice/question.class.php
index b21b55279c..fa55d43668 100755
--- a/main/exercice/question.class.php
+++ b/main/exercice/question.class.php
@@ -49,7 +49,8 @@ abstract class Question
),
GLOBAL_MULTIPLE_ANSWER => array('global_multiple_answer.class.php' , 'GlobalMultipleAnswer'),
CALCULATED_ANSWER => array('calculated_answer.class.php' , 'CalculatedAnswer'),
- UNIQUE_ANSWER_IMAGE => ['UniqueAnswerImage.php', 'UniqueAnswerImage']
+ UNIQUE_ANSWER_IMAGE => ['UniqueAnswerImage.php', 'UniqueAnswerImage'],
+ DRAGGABLE => ['Draggable.php', 'Draggable']
//MEDIA_QUESTION => array('media_question.class.php' , 'MediaQuestion')
);
diff --git a/main/inc/lib/api.lib.php b/main/inc/lib/api.lib.php
index 315422e11a..c07ac58b6d 100644
--- a/main/inc/lib/api.lib.php
+++ b/main/inc/lib/api.lib.php
@@ -473,6 +473,7 @@ define('GLOBAL_MULTIPLE_ANSWER', 14);
define('MEDIA_QUESTION', 15);
define('CALCULATED_ANSWER', 16);
define('UNIQUE_ANSWER_IMAGE', 17);
+define('DRAGGABLE', 18);
//Some alias used in the QTI exports
define('MCUA', 1);