From 6bdb7323ae9cf0d849cb56c3dece55915a03aa4a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 28 Feb 2012 13:05:45 +0700 Subject: [PATCH 01/28] MDL-47494 ddmarker: NOBUG admin page that lists contexts and categories and the number of questions contained in them. --- .../type/ddmarker/imagetargetconverter.php | 224 ++++++++++++++++++ .../type/ddmarker/lang/en/qtype_ddmarker.php | 3 + question/type/ddmarker/settings.php | 32 +++ 3 files changed, 259 insertions(+) create mode 100644 question/type/ddmarker/imagetargetconverter.php create mode 100644 question/type/ddmarker/settings.php diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php new file mode 100644 index 00000000000..155ddcb2084 --- /dev/null +++ b/question/type/ddmarker/imagetargetconverter.php @@ -0,0 +1,224 @@ +. + +/** + * This page lets admins check the environment requirements for this question type. + * + * @package qtype + * @subpackage pmatch + * @copyright 2012 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +require_once(dirname(__FILE__) . '/../../../config.php'); +require_once($CFG->libdir . '/adminlib.php'); + +abstract class qtype_ddmarker_list_item { + /** + * @var count of questions contained in this item and sub items. + */ + protected $qcount = 0; + /** + * @var children array of pointers to list_items either category_list_items or context_list_items + */ + protected $children = array(); + + protected $record; + + + public function add_child($child) { + $this->children[] = $child; + $this->children = array_unique($this->children); + } + + abstract protected function parent_node (); + + abstract public function render (); + + public function leaf_to_root($qcount) { + $this->qcount += $qcount; + $parent = $this->parent_node(); + if ($parent !== null) { + $parent->add_child($this); + $parent->leaf_to_root($qcount); + } + } + + protected function render_children() { + $children = array(); + foreach ($this->children as $child) { + $children[] = $child->render(); + } + return html_writer::alist($children); + } + + public function __toString() { + return get_class($this).' '.$this->record->id; + } + +} +class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { + + function __construct($record, $list, $parentlist) { + $this->record = $record; + $this->list = $list; + $this->parentlist = $parentlist; + } + + public function parent_node() { + if ($this->record->parent == 0) { + return $this->parentlist->get_instance($this->record->contextid); + } else { + return $this->list->get_instance($this->record->parent); + } + } + + public function render () { + $a = new stdClass(); + $a->qcount = $this->qcount; + $a->name = $this->record->name; + return get_string('categorylistitem', 'qtype_ddmarker', $a).$this->render_children(); + } +} +class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { + + protected $list; + protected $parentlist = null; + + function __construct($record, $list) { + $this->record = $record; + $this->list = $list; + } + + public function parent_node() { + $pathids = explode('/', $this->record->path); + if (count($pathids) >= 3) { + return $this->list->get_instance($pathids[count($pathids)-2]); + } else { + return null; + } + } + + public function render () { + $a = new stdClass(); + $a->qcount = $this->qcount; + $a->name = $this->record->get_context_name(); + return get_string('contextlistitem', 'qtype_ddmarker', $a).$this->render_children(); + } +} +/** + * Describes a nested list of listitems. This class and sub classes contain the functionality to build the nested list. + **/ +abstract class qtype_ddmarker_list { + abstract protected function new_list_item($record); + protected function make_list_item_instances_from_records ($contextids) { + if (!empty($this->records)) { + foreach ($this->records as $id => $record) { + $this->instances[$id] = $this->new_list_item($record); + } + } + } + public function get_instance($id) { + return $this->instances[$id]; + } + + public function leaf_node ($id, $qcount) { + $instance = $this->get_instance($id); + $instance->leaf_to_root($qcount); + } + +} + +class qtype_ddmarker_context_list extends qtype_ddmarker_list { + protected $records = array(); + protected $instances = array(); + + protected function new_list_item($record) { + return new qtype_ddmarker_context_list_item($record, $this); + } + + public function __construct($contextids) { + global $DB; + $this->records = array(); + foreach ($contextids as $contextid) { + if (!isset($records[$contextid])) { + $this->records[$contextid] = context::instance_by_id($contextid); + } + $this->records += $this->records[$contextid]->get_parent_contexts(); + } + parent::make_list_item_instances_from_records ($contextids); + } + public function render() { + $rootitem = html_writer::tag('li', $this->root_node()->render()); + return html_writer::tag('ul', $rootitem); + } + public function root_node () { + return $this->get_instance(get_context_instance(CONTEXT_SYSTEM)->id); + } +} + +class qtype_ddmarker_category_list extends qtype_ddmarker_list { + protected $records = array(); + protected $instances = array(); + protected $contextlist; + protected function new_list_item($record) { + return new qtype_ddmarker_category_list_item($record, $this, $this->contextlist); + } + public function __construct($contextids, $contextlist) { + global $DB; + $this->contextlist = $contextlist; + //probably most efficient way to reconstruct question category tree is to load all q cats in relevant contexts + list($sql, $params) = $DB->get_in_or_equal($contextids); + $this->records = $DB->get_records_select('question_categories', "contextid ".$sql, $params); + parent::make_list_item_instances_from_records ($contextids); + } +} +// Check the user is logged in. +require_login(); +$context = get_context_instance(CONTEXT_SYSTEM); +require_capability('moodle/question:config', $context); + +admin_externalpage_setup('qtypeddmarkerfromimagetarget'); + +// Header. +echo $OUTPUT->header(); +echo $OUTPUT->heading_with_help(get_string('imagetargetconverter', 'qtype_ddmarker'), '', 'qtype_ddmarker'); + +$catswithquestions = $DB->get_records_sql('SELECT cat.id, cat.contextid, COUNT(1) AS qcount '. + 'FROM {question_categories} cat, {question} q '. + 'WHERE q.category = cat.id '. + 'GROUP BY cat.id, cat.contextid'); +//print_object($catswithquestions); + +$contextids = array(); +foreach ($catswithquestions as $catwithquestions) { + $contextids[] = $catwithquestions->contextid; +} + +$contexts = new qtype_ddmarker_context_list($contextids); +$categories = new qtype_ddmarker_category_list($contextids, $contexts); + +foreach ($catswithquestions as $catwithquestions) { + $categories->leaf_node($catwithquestions->id, $catwithquestions->qcount); +} +//print_object($contexts->root_node()); + +echo $contexts->render(); + + +// Footer. +echo $OUTPUT->footer(); diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index ec9afc7ca3a..581fd492cc0 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -27,6 +27,8 @@ $string['addmoreitems'] = 'Blanks for {no} more markers'; $string['alttext'] = 'Alt text'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background image'; +$string['categorylistitem'] = 'Category "{$a->name}" (contains {$a->qcount} questions)'; +$string['contextlistitem'] = 'Context "{$a->name}" (contains {$a->qcount} questions)'; $string['coords'] = 'Coords'; $string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddmarker'] = 'Drag and drop markers'; @@ -53,6 +55,7 @@ $string['formerror_shapeoutsideboundsofbgimage'] = 'The shape you have defined g $string['formerror_toomanysemicolons'] = 'There are too many semi colon separated parts to the coordinates you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.'; $string['formerror_unrecognisedwidthheightpart'] = 'We do not recognise the width and height you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.'; $string['formerror_unrecognisedxypart'] = 'We do not recognise the x,y coordinates you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.'; +$string['imagetargetconverter'] = 'Convert image target questions to drag and drop marker'; $string['infinite'] = 'Infinite'; $string['marker'] = 'Marker'; $string['marker_n'] = 'Marker {no}'; diff --git a/question/type/ddmarker/settings.php b/question/type/ddmarker/settings.php new file mode 100644 index 00000000000..a523f7128df --- /dev/null +++ b/question/type/ddmarker/settings.php @@ -0,0 +1,32 @@ +. + +/** + * Admin settings for the Opaque question type. + * + * @package qtype + * @subpackage opaque + * @copyright 2011 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + +$settings = new admin_externalpage('qtypeddmarkerfromimagetarget', + get_string('imagetargetconverter', 'qtype_ddmarker'), + new moodle_url('/question/type/ddmarker/imagetargetconverter.php'), + 'moodle/question:config'); From 5e37b1f0f743a4423ca50779501eba0c50e21361 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 22 Mar 2012 09:52:56 +0700 Subject: [PATCH 02/28] MDL-47494 ddmarker: NOBUG further work on adminpage --- .../type/ddmarker/imagetargetconverter.php | 88 +++++++++++++++---- .../type/ddmarker/lang/en/qtype_ddmarker.php | 7 +- 2 files changed, 78 insertions(+), 17 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 155ddcb2084..7eb3f997920 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -42,12 +42,14 @@ abstract class qtype_ddmarker_list_item { public function add_child($child) { $this->children[] = $child; + //array_unique relies on __toString() returning a unique string to determine if objects in array + //are the same or not $this->children = array_unique($this->children); } abstract protected function parent_node (); - abstract public function render (); + abstract public function render($stringidentifier, $link); public function leaf_to_root($qcount) { $this->qcount += $qcount; @@ -58,10 +60,10 @@ abstract class qtype_ddmarker_list_item { } } - protected function render_children() { + protected function render_children($stringidentifier, $link) { $children = array(); foreach ($this->children as $child) { - $children[] = $child->render(); + $children[] = $child->render($stringidentifier, $link); } return html_writer::alist($children); } @@ -87,11 +89,18 @@ class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { } } - public function render () { + public function render ($stringidentifier, $link) { + global $PAGE; $a = new stdClass(); $a->qcount = $this->qcount; $a->name = $this->record->name; - return get_string('categorylistitem', 'qtype_ddmarker', $a).$this->render_children(); + $thisitem = get_string($stringidentifier.'category', 'qtype_ddmarker', $a); + if ($link) { + $actionurl = new moodle_url($PAGE->url, array('categoryid'=> $this->record->id)); + $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); + } + + return $thisitem.$this->render_children($stringidentifier, $link); } } class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { @@ -113,11 +122,17 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { } } - public function render () { + public function render ($stringidentifier, $link) { + global $PAGE; $a = new stdClass(); $a->qcount = $this->qcount; $a->name = $this->record->get_context_name(); - return get_string('contextlistitem', 'qtype_ddmarker', $a).$this->render_children(); + $thisitem = get_string($stringidentifier.'context', 'qtype_ddmarker', $a); + if ($link) { + $actionurl = new moodle_url($PAGE->url, array('contextid'=> $this->record->id)); + $thisitem = html_writer::tag('a', $thisitem,array('href' => $actionurl)); + } + return $thisitem.$this->render_children($stringidentifier, $link); } } /** @@ -162,8 +177,11 @@ class qtype_ddmarker_context_list extends qtype_ddmarker_list { } parent::make_list_item_instances_from_records ($contextids); } - public function render() { - $rootitem = html_writer::tag('li', $this->root_node()->render()); + public function render($stringidentifier, $link, $roottorender = null) { + if ($roottorender === null) { + $roottorender = $this->root_node(); + } + $rootitem = html_writer::tag('li', $roottorender->render($stringidentifier, $link)); return html_writer::tag('ul', $rootitem); } public function root_node () { @@ -187,6 +205,10 @@ class qtype_ddmarker_category_list extends qtype_ddmarker_list { parent::make_list_item_instances_from_records ($contextids); } } + +$categoryid = optional_param('categoryid', 0, PARAM_INT); +$qcontextid = optional_param('contextid', 0, PARAM_INT); +$confirm = optional_param('confirm', 0, PARAM_INT); // Check the user is logged in. require_login(); $context = get_context_instance(CONTEXT_SYSTEM); @@ -198,10 +220,29 @@ admin_externalpage_setup('qtypeddmarkerfromimagetarget'); echo $OUTPUT->header(); echo $OUTPUT->heading_with_help(get_string('imagetargetconverter', 'qtype_ddmarker'), '', 'qtype_ddmarker'); -$catswithquestions = $DB->get_records_sql('SELECT cat.id, cat.contextid, COUNT(1) AS qcount '. - 'FROM {question_categories} cat, {question} q '. - 'WHERE q.category = cat.id '. - 'GROUP BY cat.id, cat.contextid'); + +$params = array(); +$from = 'FROM {question_categories} cat, {question} q'; +$where = ' WHERE q.category = cat.id '; + +if ($qcontextid) { + $qcontext = get_context_instance_by_id($qcontextid, MUST_EXIST); + $from .= ', {context} context'; + $where .= 'AND cat.contextid = context.id AND (context.path LIKE :path OR context.id = :id) '; + $params['path'] = $qcontext->path.'/%'; + $params['id'] = $qcontext->id; +} else if ($categoryid) { + $from .= ', {context} context, {question_categories} cat2'; + $where .= 'AND cat.contextid = cat2.contextid AND cat2.id = :categoryid '; + $params['categoryid'] = $categoryid; +} +$sql = 'SELECT cat.id, cat.contextid, COUNT(1) AS qcount '. + $from. + $where. + 'GROUP BY cat.id, cat.contextid'; + + +$catswithquestions = $DB->get_records_sql($sql, $params); //print_object($catswithquestions); $contextids = array(); @@ -216,8 +257,25 @@ foreach ($catswithquestions as $catwithquestions) { $categories->leaf_node($catwithquestions->id, $catwithquestions->qcount); } //print_object($contexts->root_node()); - -echo $contexts->render(); +if ($categoryid || $qcontextid) { + if (!$confirm) { + $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid')+array('confirm'=>1)); + $cancelurl = new moodle_url($PAGE->url); + if ($categoryid) { + $torender = $categories->get_instance($categoryid); + } else if ($qcontextid) { + $torender = $contexts->get_instance($qcontextid); + } else { + $torender = $contexts->root_node(); + } + echo $contexts->render('listitem', false, $torender); + echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); + } else if (confirm_sesskey()) { + + } +} else { + echo $contexts->render('listitemaction', true, $contexts->root_node()); +} // Footer. diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index 581fd492cc0..b5e481d5546 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -27,8 +27,7 @@ $string['addmoreitems'] = 'Blanks for {no} more markers'; $string['alttext'] = 'Alt text'; $string['answer'] = 'Answer'; $string['bgimage'] = 'Background image'; -$string['categorylistitem'] = 'Category "{$a->name}" (contains {$a->qcount} questions)'; -$string['contextlistitem'] = 'Context "{$a->name}" (contains {$a->qcount} questions)'; +$string['confirmimagetargetconversion'] = 'You are about to convert the above image target questions to the drag and drop markers question type.'; $string['coords'] = 'Coords'; $string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddmarker'] = 'Drag and drop markers'; @@ -57,6 +56,10 @@ $string['formerror_unrecognisedwidthheightpart'] = 'We do not recognise the widt $string['formerror_unrecognisedxypart'] = 'We do not recognise the x,y coordinates you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.'; $string['imagetargetconverter'] = 'Convert image target questions to drag and drop marker'; $string['infinite'] = 'Infinite'; +$string['listitemactioncategory'] = 'Convert all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemactioncontext'] = 'Convert all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemcategory'] = 'Questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemcontext'] = 'Questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; $string['marker'] = 'Marker'; $string['marker_n'] = 'Marker {no}'; $string['markers'] = 'Markers'; From 2379439f63af89fa968c6e636fb45dd830ca349c Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 27 Mar 2012 14:41:58 +0700 Subject: [PATCH 03/28] MDL-47494 ddmarker: NOBUG change API calls that only work post 2.1 This need to be merged into master branch because we want to keep the 2.1 branch mergeable but then we will merge with 'ours' strategy, effectively discarding changes. --- .../type/ddmarker/imagetargetconverter.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 7eb3f997920..be2d62f1148 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -99,7 +99,7 @@ class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { $actionurl = new moodle_url($PAGE->url, array('categoryid'=> $this->record->id)); $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); } - + return $thisitem.$this->render_children($stringidentifier, $link); } } @@ -126,7 +126,7 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { global $PAGE; $a = new stdClass(); $a->qcount = $this->qcount; - $a->name = $this->record->get_context_name(); + $a->name = print_context_name($this->record); $thisitem = get_string($stringidentifier.'context', 'qtype_ddmarker', $a); if ($link) { $actionurl = new moodle_url($PAGE->url, array('contextid'=> $this->record->id)); @@ -170,10 +170,16 @@ class qtype_ddmarker_context_list extends qtype_ddmarker_list { global $DB; $this->records = array(); foreach ($contextids as $contextid) { - if (!isset($records[$contextid])) { - $this->records[$contextid] = context::instance_by_id($contextid); + if (!isset($this->records[$contextid])) { + $this->records[$contextid] = get_context_instance_by_id($contextid, MUST_EXIST); + } + $parents = get_parent_contexts($this->records[$contextid]); + foreach ($parents as $parentcontextid) { + if (!isset($this->records[$parentcontextid])) { + $this->records[$parentcontextid] = + get_context_instance_by_id($parentcontextid, MUST_EXIST); + } } - $this->records += $this->records[$contextid]->get_parent_contexts(); } parent::make_list_item_instances_from_records ($contextids); } @@ -271,7 +277,7 @@ if ($categoryid || $qcontextid) { echo $contexts->render('listitem', false, $torender); echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); } else if (confirm_sesskey()) { - + } } else { echo $contexts->render('listitemaction', true, $contexts->root_node()); From e1e835e7272658a36605d302eba37fa378f6ea68 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 27 Mar 2012 18:20:14 +0700 Subject: [PATCH 04/28] MDL-47494 ddmarker: NOBUG fixing coding style deviations found by code checker. --- question/type/ddmarker/imagetargetconverter.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index be2d62f1148..917aa48d341 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -75,7 +75,7 @@ abstract class qtype_ddmarker_list_item { } class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { - function __construct($record, $list, $parentlist) { + public function __construct($record, $list, $parentlist) { $this->record = $record; $this->list = $list; $this->parentlist = $parentlist; @@ -108,7 +108,7 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { protected $list; protected $parentlist = null; - function __construct($record, $list) { + public function __construct($record, $list) { $this->record = $record; $this->list = $list; } @@ -130,7 +130,7 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { $thisitem = get_string($stringidentifier.'context', 'qtype_ddmarker', $a); if ($link) { $actionurl = new moodle_url($PAGE->url, array('contextid'=> $this->record->id)); - $thisitem = html_writer::tag('a', $thisitem,array('href' => $actionurl)); + $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); } return $thisitem.$this->render_children($stringidentifier, $link); } @@ -249,7 +249,6 @@ $sql = 'SELECT cat.id, cat.contextid, COUNT(1) AS qcount '. $catswithquestions = $DB->get_records_sql($sql, $params); -//print_object($catswithquestions); $contextids = array(); foreach ($catswithquestions as $catwithquestions) { @@ -262,7 +261,6 @@ $categories = new qtype_ddmarker_category_list($contextids, $contexts); foreach ($catswithquestions as $catwithquestions) { $categories->leaf_node($catwithquestions->id, $catwithquestions->qcount); } -//print_object($contexts->root_node()); if ($categoryid || $qcontextid) { if (!$confirm) { $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid')+array('confirm'=>1)); From a83fc4678471516a93c91f78fd5d9d24d2cebadd Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 27 Mar 2012 18:22:49 +0700 Subject: [PATCH 05/28] MDL-47494 ddmarker: NOBUG fixing white space issue --- question/type/ddmarker/imagetargetconverter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index a98346f3e56..e2a36853671 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -99,7 +99,7 @@ class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { $actionurl = new moodle_url($PAGE->url, array('categoryid'=> $this->record->id)); $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); } - + return $thisitem.$this->render_children($stringidentifier, $link); } } @@ -269,7 +269,7 @@ if ($categoryid || $qcontextid) { echo $contexts->render('listitem', false, $torender); echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); } else if (confirm_sesskey()) { - + } } else { echo $contexts->render('listitemaction', true, $contexts->root_node()); From af9d63a8dc662b9b015ecdbcbed5aa3ce84f1f1c Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 29 Mar 2012 14:05:57 +0700 Subject: [PATCH 06/28] MDL-47494 ddmarker: NOBUG list questions in categories in category / context selection UI --- .../type/ddmarker/imagetargetconverter.php | 74 ++++++++++++++----- .../type/ddmarker/lang/en/qtype_ddmarker.php | 1 + 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 917aa48d341..6b8ea1a5d42 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -103,6 +103,26 @@ class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { return $thisitem.$this->render_children($stringidentifier, $link); } } +class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { + + public function __construct($record, $list, $parentlist) { + $this->record = $record; + $this->list = $list; + $this->parentlist = $parentlist; + } + + public function parent_node() { + return $this->parentlist->get_instance($this->record->cat_id); + } + + public function render ($stringidentifier, $link) { + global $PAGE; + $a = new stdClass(); + $a->name = $this->record->name; + $thisitem = get_string('listitemquestion', 'qtype_ddmarker', $a); + return $thisitem; + } +} class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { protected $list; @@ -139,8 +159,10 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { * Describes a nested list of listitems. This class and sub classes contain the functionality to build the nested list. **/ abstract class qtype_ddmarker_list { + protected $records = array(); + protected $instances = array(); abstract protected function new_list_item($record); - protected function make_list_item_instances_from_records ($contextids) { + protected function make_list_item_instances_from_records ($contextids = null) { if (!empty($this->records)) { foreach ($this->records as $id => $record) { $this->instances[$id] = $this->new_list_item($record); @@ -154,13 +176,12 @@ abstract class qtype_ddmarker_list { public function leaf_node ($id, $qcount) { $instance = $this->get_instance($id); $instance->leaf_to_root($qcount); + //print_object(array('list' => $this)+ compact('id', 'qcount')); } } class qtype_ddmarker_context_list extends qtype_ddmarker_list { - protected $records = array(); - protected $instances = array(); protected function new_list_item($record) { return new qtype_ddmarker_context_list_item($record, $this); @@ -195,9 +216,9 @@ class qtype_ddmarker_context_list extends qtype_ddmarker_list { } } + + class qtype_ddmarker_category_list extends qtype_ddmarker_list { - protected $records = array(); - protected $instances = array(); protected $contextlist; protected function new_list_item($record) { return new qtype_ddmarker_category_list_item($record, $this, $this->contextlist); @@ -212,6 +233,19 @@ class qtype_ddmarker_category_list extends qtype_ddmarker_list { } } +class qtype_ddmarker_question_list extends qtype_ddmarker_list { + protected $categorylist; + protected function new_list_item($record) { + return new qtype_ddmarker_question_list_item($record, $this, $this->categorylist); + } + public function __construct($questions, $categorylist) { + global $DB; + $this->categorylist = $categorylist; + $this->records = $questions; + parent::make_list_item_instances_from_records (); + } +} + $categoryid = optional_param('categoryid', 0, PARAM_INT); $qcontextid = optional_param('contextid', 0, PARAM_INT); $confirm = optional_param('confirm', 0, PARAM_INT); @@ -242,45 +276,45 @@ if ($qcontextid) { $where .= 'AND cat.contextid = cat2.contextid AND cat2.id = :categoryid '; $params['categoryid'] = $categoryid; } -$sql = 'SELECT cat.id, cat.contextid, COUNT(1) AS qcount '. +$sql = 'SELECT q.id, cat.id AS cat_id, cat.contextid, q.name '. $from. $where. - 'GROUP BY cat.id, cat.contextid'; + 'ORDER BY cat.id'; -$catswithquestions = $DB->get_records_sql($sql, $params); +$questions = $DB->get_records_sql($sql, $params); $contextids = array(); -foreach ($catswithquestions as $catwithquestions) { - $contextids[] = $catwithquestions->contextid; +foreach ($questions as $question) { + $contextids[] = $question->contextid; } -$contexts = new qtype_ddmarker_context_list($contextids); -$categories = new qtype_ddmarker_category_list($contextids, $contexts); +$contextlist = new qtype_ddmarker_context_list(array_unique($contextids)); +$categorylist = new qtype_ddmarker_category_list($contextids, $contextlist); +$questionlist = new qtype_ddmarker_question_list($questions, $categorylist); -foreach ($catswithquestions as $catwithquestions) { - $categories->leaf_node($catwithquestions->id, $catwithquestions->qcount); +foreach ($questions as $question) { + $questionlist->leaf_node($question->id, 1); } if ($categoryid || $qcontextid) { if (!$confirm) { $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid')+array('confirm'=>1)); $cancelurl = new moodle_url($PAGE->url); if ($categoryid) { - $torender = $categories->get_instance($categoryid); + $torender = $categorylist->get_instance($categoryid); } else if ($qcontextid) { - $torender = $contexts->get_instance($qcontextid); + $torender = $contextlist->get_instance($qcontextid); } else { - $torender = $contexts->root_node(); + $torender = $contextlist->root_node(); } - echo $contexts->render('listitem', false, $torender); + echo $contextlist->render('listitem', false, $torender); echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); } else if (confirm_sesskey()) { } } else { - echo $contexts->render('listitemaction', true, $contexts->root_node()); + echo $contextlist->render('listitemaction', true, $contextlist->root_node()); } - // Footer. echo $OUTPUT->footer(); diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index b5e481d5546..1503967ed10 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -60,6 +60,7 @@ $string['listitemactioncategory'] = 'Convert all imagetarget questions in catego $string['listitemactioncontext'] = 'Convert all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; $string['listitemcategory'] = 'Questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; $string['listitemcontext'] = 'Questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemquestion'] = 'Question "{$a->name}"'; $string['marker'] = 'Marker'; $string['marker_n'] = 'Marker {no}'; $string['markers'] = 'Markers'; From 2de9e082eeb3256b36e7d5811b31f188dcd98a81 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 29 Mar 2012 15:29:06 +0700 Subject: [PATCH 07/28] MDL-47494 ddmarker: NOBUG fixing error in sql to fetch relevant questions --- question/type/ddmarker/imagetargetconverter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 6b8ea1a5d42..3398da0777e 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -272,7 +272,7 @@ if ($qcontextid) { $params['path'] = $qcontext->path.'/%'; $params['id'] = $qcontext->id; } else if ($categoryid) { - $from .= ', {context} context, {question_categories} cat2'; + $from .= ', {question_categories} cat2'; $where .= 'AND cat.contextid = cat2.contextid AND cat2.id = :categoryid '; $params['categoryid'] = $categoryid; } From 9437265e8b761f41545bbef2050e37224158abcc Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Thu, 29 Mar 2012 15:30:55 +0700 Subject: [PATCH 08/28] MDL-47494 ddmarker: NOBUG restructuring if conditions to interpret page params --- .../type/ddmarker/imagetargetconverter.php | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 3398da0777e..9e15df3beab 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -176,7 +176,6 @@ abstract class qtype_ddmarker_list { public function leaf_node ($id, $qcount) { $instance = $this->get_instance($id); $instance->leaf_to_root($qcount); - //print_object(array('list' => $this)+ compact('id', 'qcount')); } } @@ -272,6 +271,7 @@ if ($qcontextid) { $params['path'] = $qcontext->path.'/%'; $params['id'] = $qcontext->id; } else if ($categoryid) { + //fetch all questions from this cats context $from .= ', {question_categories} cat2'; $where .= 'AND cat.contextid = cat2.contextid AND cat2.id = :categoryid '; $params['categoryid'] = $categoryid; @@ -279,8 +279,7 @@ if ($qcontextid) { $sql = 'SELECT q.id, cat.id AS cat_id, cat.contextid, q.name '. $from. $where. - 'ORDER BY cat.id'; - + 'ORDER BY cat.id, q.name'; $questions = $DB->get_records_sql($sql, $params); @@ -296,24 +295,25 @@ $questionlist = new qtype_ddmarker_question_list($questions, $categorylist); foreach ($questions as $question) { $questionlist->leaf_node($question->id, 1); } -if ($categoryid || $qcontextid) { - if (!$confirm) { +$questionsselected = (bool) ($categoryid || $qcontextid); +if ($categoryid) { + $top = $categorylist->get_instance($categoryid); +} else if ($qcontextid) { + $top = $contextlist->get_instance($qcontextid); +} else { + $top = $contextlist->root_node(); +} +if (!$confirm) { + if ($questionsselected) { + echo $contextlist->render('listitemaction', false, $top); $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid')+array('confirm'=>1)); $cancelurl = new moodle_url($PAGE->url); - if ($categoryid) { - $torender = $categorylist->get_instance($categoryid); - } else if ($qcontextid) { - $torender = $contextlist->get_instance($qcontextid); - } else { - $torender = $contextlist->root_node(); - } - echo $contextlist->render('listitem', false, $torender); echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); - } else if (confirm_sesskey()) { - + } else { + echo $contextlist->render('listitem', true, $top); } -} else { - echo $contextlist->render('listitemaction', true, $contextlist->root_node()); +} else if (confirm_sesskey()) { + } // Footer. From d0c22457577a4f8e11f34e2ade1b6c0bb6bca563 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 31 Mar 2012 09:46:23 +0700 Subject: [PATCH 09/28] MDL-47494 ddmarker: NOBUG adding method to process questions. --- question/type/ddmarker/imagetargetconverter.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 9e15df3beab..5e5c7a44df2 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -60,6 +60,21 @@ abstract class qtype_ddmarker_list_item { } } + public function process($progresstrace = null, $depth = 0) { + if (null === $progresstrace) { + $progresstrace = new html_list_progress_trace(); + } + $progresstrace->output((string)$this, $depth); + $this->process_children($progresstrace, $depth); + } + + protected function process_children($progresstrace, $depth) { + $children = array(); + foreach ($this->children as $child) { + $child->process($progresstrace, $depth + 1); + } + } + protected function render_children($stringidentifier, $link) { $children = array(); foreach ($this->children as $child) { @@ -313,7 +328,7 @@ if (!$confirm) { echo $contextlist->render('listitem', true, $top); } } else if (confirm_sesskey()) { - + $top->process(); } // Footer. From d4e4c3131dbcc4ead925e934c197b815acd51e10 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 31 Mar 2012 10:04:15 +0700 Subject: [PATCH 10/28] MDL-47494 ddmarker: NOBUG moved list classes to new file --- .../type/ddmarker/imagetargetconverter.php | 234 +--------------- question/type/ddmarker/questionlists.php | 257 ++++++++++++++++++ 2 files changed, 258 insertions(+), 233 deletions(-) create mode 100644 question/type/ddmarker/questionlists.php diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 5e5c7a44df2..cbbe57f0b94 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -26,239 +26,7 @@ require_once(dirname(__FILE__) . '/../../../config.php'); require_once($CFG->libdir . '/adminlib.php'); - -abstract class qtype_ddmarker_list_item { - /** - * @var count of questions contained in this item and sub items. - */ - protected $qcount = 0; - /** - * @var children array of pointers to list_items either category_list_items or context_list_items - */ - protected $children = array(); - - protected $record; - - - public function add_child($child) { - $this->children[] = $child; - //array_unique relies on __toString() returning a unique string to determine if objects in array - //are the same or not - $this->children = array_unique($this->children); - } - - abstract protected function parent_node (); - - abstract public function render($stringidentifier, $link); - - public function leaf_to_root($qcount) { - $this->qcount += $qcount; - $parent = $this->parent_node(); - if ($parent !== null) { - $parent->add_child($this); - $parent->leaf_to_root($qcount); - } - } - - public function process($progresstrace = null, $depth = 0) { - if (null === $progresstrace) { - $progresstrace = new html_list_progress_trace(); - } - $progresstrace->output((string)$this, $depth); - $this->process_children($progresstrace, $depth); - } - - protected function process_children($progresstrace, $depth) { - $children = array(); - foreach ($this->children as $child) { - $child->process($progresstrace, $depth + 1); - } - } - - protected function render_children($stringidentifier, $link) { - $children = array(); - foreach ($this->children as $child) { - $children[] = $child->render($stringidentifier, $link); - } - return html_writer::alist($children); - } - - public function __toString() { - return get_class($this).' '.$this->record->id; - } - -} -class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { - - public function __construct($record, $list, $parentlist) { - $this->record = $record; - $this->list = $list; - $this->parentlist = $parentlist; - } - - public function parent_node() { - if ($this->record->parent == 0) { - return $this->parentlist->get_instance($this->record->contextid); - } else { - return $this->list->get_instance($this->record->parent); - } - } - - public function render ($stringidentifier, $link) { - global $PAGE; - $a = new stdClass(); - $a->qcount = $this->qcount; - $a->name = $this->record->name; - $thisitem = get_string($stringidentifier.'category', 'qtype_ddmarker', $a); - if ($link) { - $actionurl = new moodle_url($PAGE->url, array('categoryid'=> $this->record->id)); - $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); - } - - return $thisitem.$this->render_children($stringidentifier, $link); - } -} -class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { - - public function __construct($record, $list, $parentlist) { - $this->record = $record; - $this->list = $list; - $this->parentlist = $parentlist; - } - - public function parent_node() { - return $this->parentlist->get_instance($this->record->cat_id); - } - - public function render ($stringidentifier, $link) { - global $PAGE; - $a = new stdClass(); - $a->name = $this->record->name; - $thisitem = get_string('listitemquestion', 'qtype_ddmarker', $a); - return $thisitem; - } -} -class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { - - protected $list; - protected $parentlist = null; - - public function __construct($record, $list) { - $this->record = $record; - $this->list = $list; - } - - public function parent_node() { - $pathids = explode('/', $this->record->path); - if (count($pathids) >= 3) { - return $this->list->get_instance($pathids[count($pathids)-2]); - } else { - return null; - } - } - - public function render ($stringidentifier, $link) { - global $PAGE; - $a = new stdClass(); - $a->qcount = $this->qcount; - $a->name = print_context_name($this->record); - $thisitem = get_string($stringidentifier.'context', 'qtype_ddmarker', $a); - if ($link) { - $actionurl = new moodle_url($PAGE->url, array('contextid'=> $this->record->id)); - $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); - } - return $thisitem.$this->render_children($stringidentifier, $link); - } -} -/** - * Describes a nested list of listitems. This class and sub classes contain the functionality to build the nested list. - **/ -abstract class qtype_ddmarker_list { - protected $records = array(); - protected $instances = array(); - abstract protected function new_list_item($record); - protected function make_list_item_instances_from_records ($contextids = null) { - if (!empty($this->records)) { - foreach ($this->records as $id => $record) { - $this->instances[$id] = $this->new_list_item($record); - } - } - } - public function get_instance($id) { - return $this->instances[$id]; - } - - public function leaf_node ($id, $qcount) { - $instance = $this->get_instance($id); - $instance->leaf_to_root($qcount); - } - -} - -class qtype_ddmarker_context_list extends qtype_ddmarker_list { - - protected function new_list_item($record) { - return new qtype_ddmarker_context_list_item($record, $this); - } - - public function __construct($contextids) { - global $DB; - $this->records = array(); - foreach ($contextids as $contextid) { - if (!isset($this->records[$contextid])) { - $this->records[$contextid] = get_context_instance_by_id($contextid, MUST_EXIST); - } - $parents = get_parent_contexts($this->records[$contextid]); - foreach ($parents as $parentcontextid) { - if (!isset($this->records[$parentcontextid])) { - $this->records[$parentcontextid] = - get_context_instance_by_id($parentcontextid, MUST_EXIST); - } - } - } - parent::make_list_item_instances_from_records ($contextids); - } - public function render($stringidentifier, $link, $roottorender = null) { - if ($roottorender === null) { - $roottorender = $this->root_node(); - } - $rootitem = html_writer::tag('li', $roottorender->render($stringidentifier, $link)); - return html_writer::tag('ul', $rootitem); - } - public function root_node () { - return $this->get_instance(get_context_instance(CONTEXT_SYSTEM)->id); - } -} - - - -class qtype_ddmarker_category_list extends qtype_ddmarker_list { - protected $contextlist; - protected function new_list_item($record) { - return new qtype_ddmarker_category_list_item($record, $this, $this->contextlist); - } - public function __construct($contextids, $contextlist) { - global $DB; - $this->contextlist = $contextlist; - //probably most efficient way to reconstruct question category tree is to load all q cats in relevant contexts - list($sql, $params) = $DB->get_in_or_equal($contextids); - $this->records = $DB->get_records_select('question_categories', "contextid ".$sql, $params); - parent::make_list_item_instances_from_records ($contextids); - } -} - -class qtype_ddmarker_question_list extends qtype_ddmarker_list { - protected $categorylist; - protected function new_list_item($record) { - return new qtype_ddmarker_question_list_item($record, $this, $this->categorylist); - } - public function __construct($questions, $categorylist) { - global $DB; - $this->categorylist = $categorylist; - $this->records = $questions; - parent::make_list_item_instances_from_records (); - } -} +require_once($CFG->dirroot.'/question/type/ddmarker/questionlists.php'); $categoryid = optional_param('categoryid', 0, PARAM_INT); $qcontextid = optional_param('contextid', 0, PARAM_INT); diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php new file mode 100644 index 00000000000..b7edebee3e8 --- /dev/null +++ b/question/type/ddmarker/questionlists.php @@ -0,0 +1,257 @@ +. + +/** + * These classes handle transforming arrays of records into a linked tree of contexts, categories and questions. + * + * @package qtype + * @subpackage pmatch + * @copyright 2012 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +abstract class qtype_ddmarker_list_item { + /** + * @var count of questions contained in this item and sub items. + */ + protected $qcount = 0; + /** + * @var children array of pointers to list_items either category_list_items or context_list_items + */ + protected $children = array(); + + protected $record; + + + public function add_child($child) { + $this->children[] = $child; + //array_unique relies on __toString() returning a unique string to determine if objects in array + //are the same or not + $this->children = array_unique($this->children); + } + + abstract protected function parent_node (); + + abstract public function render($stringidentifier, $link); + + public function leaf_to_root($qcount) { + $this->qcount += $qcount; + $parent = $this->parent_node(); + if ($parent !== null) { + $parent->add_child($this); + $parent->leaf_to_root($qcount); + } + } + + public function process($progresstrace = null, $depth = 0) { + if (null === $progresstrace) { + $progresstrace = new html_list_progress_trace(); + } + $progresstrace->output((string)$this, $depth); + $this->process_children($progresstrace, $depth); + } + + protected function process_children($progresstrace, $depth) { + $children = array(); + foreach ($this->children as $child) { + $child->process($progresstrace, $depth + 1); + } + } + + protected function render_children($stringidentifier, $link) { + $children = array(); + foreach ($this->children as $child) { + $children[] = $child->render($stringidentifier, $link); + } + return html_writer::alist($children); + } + + public function __toString() { + return get_class($this).' '.$this->record->id; + } + +} +class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { + + public function __construct($record, $list, $parentlist) { + $this->record = $record; + $this->list = $list; + $this->parentlist = $parentlist; + } + + public function parent_node() { + if ($this->record->parent == 0) { + return $this->parentlist->get_instance($this->record->contextid); + } else { + return $this->list->get_instance($this->record->parent); + } + } + + public function render ($stringidentifier, $link) { + global $PAGE; + $a = new stdClass(); + $a->qcount = $this->qcount; + $a->name = $this->record->name; + $thisitem = get_string($stringidentifier.'category', 'qtype_ddmarker', $a); + if ($link) { + $actionurl = new moodle_url($PAGE->url, array('categoryid'=> $this->record->id)); + $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); + } + + return $thisitem.$this->render_children($stringidentifier, $link); + } +} +class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { + + public function __construct($record, $list, $parentlist) { + $this->record = $record; + $this->list = $list; + $this->parentlist = $parentlist; + } + + public function parent_node() { + return $this->parentlist->get_instance($this->record->cat_id); + } + + public function render ($stringidentifier, $link) { + global $PAGE; + $a = new stdClass(); + $a->name = $this->record->name; + $thisitem = get_string('listitemquestion', 'qtype_ddmarker', $a); + return $thisitem; + } +} +class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { + + protected $list; + protected $parentlist = null; + + public function __construct($record, $list) { + $this->record = $record; + $this->list = $list; + } + + public function parent_node() { + $pathids = explode('/', $this->record->path); + if (count($pathids) >= 3) { + return $this->list->get_instance($pathids[count($pathids)-2]); + } else { + return null; + } + } + + public function render ($stringidentifier, $link) { + global $PAGE; + $a = new stdClass(); + $a->qcount = $this->qcount; + $a->name = print_context_name($this->record); + $thisitem = get_string($stringidentifier.'context', 'qtype_ddmarker', $a); + if ($link) { + $actionurl = new moodle_url($PAGE->url, array('contextid'=> $this->record->id)); + $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); + } + return $thisitem.$this->render_children($stringidentifier, $link); + } +} +/** + * Describes a nested list of listitems. This class and sub classes contain the functionality to build the nested list. + **/ +abstract class qtype_ddmarker_list { + protected $records = array(); + protected $instances = array(); + abstract protected function new_list_item($record); + protected function make_list_item_instances_from_records ($contextids = null) { + if (!empty($this->records)) { + foreach ($this->records as $id => $record) { + $this->instances[$id] = $this->new_list_item($record); + } + } + } + public function get_instance($id) { + return $this->instances[$id]; + } + + public function leaf_node ($id, $qcount) { + $instance = $this->get_instance($id); + $instance->leaf_to_root($qcount); + } + +} + +class qtype_ddmarker_context_list extends qtype_ddmarker_list { + + protected function new_list_item($record) { + return new qtype_ddmarker_context_list_item($record, $this); + } + + public function __construct($contextids) { + global $DB; + $this->records = array(); + foreach ($contextids as $contextid) { + if (!isset($this->records[$contextid])) { + $this->records[$contextid] = get_context_instance_by_id($contextid, MUST_EXIST); + } + $parents = get_parent_contexts($this->records[$contextid]); + foreach ($parents as $parentcontextid) { + if (!isset($this->records[$parentcontextid])) { + $this->records[$parentcontextid] = + get_context_instance_by_id($parentcontextid, MUST_EXIST); + } + } + } + parent::make_list_item_instances_from_records ($contextids); + } + public function render($stringidentifier, $link, $roottorender = null) { + if ($roottorender === null) { + $roottorender = $this->root_node(); + } + $rootitem = html_writer::tag('li', $roottorender->render($stringidentifier, $link)); + return html_writer::tag('ul', $rootitem); + } + public function root_node () { + return $this->get_instance(get_context_instance(CONTEXT_SYSTEM)->id); + } +} + + + +class qtype_ddmarker_category_list extends qtype_ddmarker_list { + protected $contextlist; + protected function new_list_item($record) { + return new qtype_ddmarker_category_list_item($record, $this, $this->contextlist); + } + public function __construct($contextids, $contextlist) { + global $DB; + $this->contextlist = $contextlist; + //probably most efficient way to reconstruct question category tree is to load all q cats in relevant contexts + list($sql, $params) = $DB->get_in_or_equal($contextids); + $this->records = $DB->get_records_select('question_categories', "contextid ".$sql, $params); + parent::make_list_item_instances_from_records ($contextids); + } +} + +class qtype_ddmarker_question_list extends qtype_ddmarker_list { + protected $categorylist; + protected function new_list_item($record) { + return new qtype_ddmarker_question_list_item($record, $this, $this->categorylist); + } + public function __construct($questions, $categorylist) { + global $DB; + $this->categorylist = $categorylist; + $this->records = $questions; + parent::make_list_item_instances_from_records (); + } +} \ No newline at end of file From 44f16ef16d2b227dfc4dff36016fbec8e13c7b60 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 31 Mar 2012 10:25:13 +0700 Subject: [PATCH 11/28] MDL-47494 ddmarker: NOBUG some fixes to php doc comments --- question/type/ddmarker/imagetargetconverter.php | 6 +++--- question/type/ddmarker/questionlists.php | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index cbbe57f0b94..55496749fb6 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -15,11 +15,11 @@ // along with Moodle. If not, see . /** - * This page lets admins check the environment requirements for this question type. + * This page lets admin convert imagetarget questions to the ddmarker question type. * * @package qtype - * @subpackage pmatch - * @copyright 2012 The Open University + * @subpackage ddmarker + * @copyright 2012 Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index b7edebee3e8..a92a1bb7ff8 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -1,5 +1,4 @@ Date: Sat, 31 Mar 2012 10:52:28 +0700 Subject: [PATCH 12/28] MDL-47494 ddmarker: NOBUG subclass list and list item classes to add specific processing --- .../type/ddmarker/imagetargetconverter.php | 19 ++++++++++++++++++- question/type/ddmarker/questionlists.php | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 55496749fb6..2a40c465419 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -28,6 +28,23 @@ require_once(dirname(__FILE__) . '/../../../config.php'); require_once($CFG->libdir . '/adminlib.php'); require_once($CFG->dirroot.'/question/type/ddmarker/questionlists.php'); +class qtype_ddmarker_question_converter_list extends qtype_ddmarker_question_list { + protected function new_list_item($record) { + return new qtype_ddmarker_question_converter_list_item($record, $this, $this->categorylist); + } +} +class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_question_list_item { + public function process($progresstrace = null, $depth = 0) { + $this->convert_question(); + parent::process($progresstrace, $depth);//outputs progress message + } + + protected function convert_question() { + $questionrec = $this->record; + + } +} + $categoryid = optional_param('categoryid', 0, PARAM_INT); $qcontextid = optional_param('contextid', 0, PARAM_INT); $confirm = optional_param('confirm', 0, PARAM_INT); @@ -73,7 +90,7 @@ foreach ($questions as $question) { $contextlist = new qtype_ddmarker_context_list(array_unique($contextids)); $categorylist = new qtype_ddmarker_category_list($contextids, $contextlist); -$questionlist = new qtype_ddmarker_question_list($questions, $categorylist); +$questionlist = new qtype_ddmarker_question_converter_list($questions, $categorylist); foreach ($questions as $question) { $questionlist->leaf_node($question->id, 1); diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index a92a1bb7ff8..6c40685693d 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -14,6 +14,8 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . +defined('MOODLE_INTERNAL') || die(); + /** * These classes handle transforming arrays of records into a linked tree of contexts, categories and questions. * From e1bd1cf6e309a1283a9c8f03d395c1ef65e6af6b Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 31 Mar 2012 14:09:31 +0700 Subject: [PATCH 13/28] MDL-47494 ddmarker: NOBUG loading imagetarget and answers records all before processing --- .../type/ddmarker/imagetargetconverter.php | 24 ++++++++++++++----- question/type/ddmarker/questionlists.php | 19 ++++++++++++++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 2a40c465419..a0a9bb79c43 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -32,16 +32,30 @@ class qtype_ddmarker_question_converter_list extends qtype_ddmarker_question_lis protected function new_list_item($record) { return new qtype_ddmarker_question_converter_list_item($record, $this, $this->categorylist); } + public function prepare_for_processing($top) { + global $DB; + $questionids = $top->question_ids(); + list($inorequalsql, $inorequalparams) = $DB->get_in_or_equal($questionids); + $imagetargetrecords = $DB->get_records_select('question_imagetarget', 'question '.$inorequalsql, $inorequalparams); + $answers = array(); + foreach ($imagetargetrecords as $imagetargetrecord) { + $this->get_instance($imagetargetrecord->question)->imagetargetrecord = $imagetargetrecord; + } + $answerrecords = $DB->get_records_select('question_answers', 'question '.$inorequalsql, $inorequalparams); + foreach ($answerrecords as $answerrecord) { + $this->get_instance($answerrecord->question)->answers[] = $answerrecord; + } + } } class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_question_list_item { + public $imagetargetrecord = null; + public $answers = array(); public function process($progresstrace = null, $depth = 0) { $this->convert_question(); parent::process($progresstrace, $depth);//outputs progress message } - protected function convert_question() { $questionrec = $this->record; - } } @@ -76,10 +90,7 @@ if ($qcontextid) { $where .= 'AND cat.contextid = cat2.contextid AND cat2.id = :categoryid '; $params['categoryid'] = $categoryid; } -$sql = 'SELECT q.id, cat.id AS cat_id, cat.contextid, q.name '. - $from. - $where. - 'ORDER BY cat.id, q.name'; +$sql = 'SELECT q.*, cat.contextid '.$from.$where.'ORDER BY cat.id, q.name'; $questions = $DB->get_records_sql($sql, $params); @@ -113,6 +124,7 @@ if (!$confirm) { echo $contextlist->render('listitem', true, $top); } } else if (confirm_sesskey()) { + $questionlist->prepare_for_processing($top); $top->process(); } diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index 6c40685693d..23cd17ab540 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -72,6 +72,18 @@ abstract class qtype_ddmarker_list_item { } } + public function question_ids() { + return $this->child_question_ids(); + } + + protected function child_question_ids() { + $ids = array(); + foreach ($this->children as $child) { + $ids = array_merge($ids, $child->question_ids()); + } + return $ids; + } + protected function render_children($stringidentifier, $link) { $children = array(); foreach ($this->children as $child) { @@ -124,7 +136,7 @@ class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { } public function parent_node() { - return $this->parentlist->get_instance($this->record->cat_id); + return $this->parentlist->get_instance($this->record->category); } public function render ($stringidentifier, $link) { @@ -134,6 +146,9 @@ class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { $thisitem = get_string('listitemquestion', 'qtype_ddmarker', $a); return $thisitem; } + public function question_ids() { + return array($this->record->id); + } } class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { @@ -255,4 +270,6 @@ class qtype_ddmarker_question_list extends qtype_ddmarker_list { $this->records = $questions; parent::make_list_item_instances_from_records (); } + public function prepare_for_processing($top) { + } } \ No newline at end of file From 864e78601941ec3aaeb98b5937fa35bb950e0549 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 31 Mar 2012 14:23:25 +0700 Subject: [PATCH 14/28] MDL-47494 ddmarker: NOBUG make it possible to select just one question for processing --- question/type/ddmarker/imagetargetconverter.php | 13 ++++++++++--- question/type/ddmarker/questionlists.php | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index a0a9bb79c43..93423dd73e5 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -61,6 +61,7 @@ class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_questio $categoryid = optional_param('categoryid', 0, PARAM_INT); $qcontextid = optional_param('contextid', 0, PARAM_INT); +$questionid = optional_param('questionid', 0, PARAM_INT); $confirm = optional_param('confirm', 0, PARAM_INT); // Check the user is logged in. require_login(); @@ -89,6 +90,10 @@ if ($qcontextid) { $from .= ', {question_categories} cat2'; $where .= 'AND cat.contextid = cat2.contextid AND cat2.id = :categoryid '; $params['categoryid'] = $categoryid; +} else if ($questionid) { + //fetch all questions from this cats context + $where .= 'AND q.id = :questionid '; + $params['questionid'] = $questionid; } $sql = 'SELECT q.*, cat.contextid '.$from.$where.'ORDER BY cat.id, q.name'; @@ -106,8 +111,10 @@ $questionlist = new qtype_ddmarker_question_converter_list($questions, $category foreach ($questions as $question) { $questionlist->leaf_node($question->id, 1); } -$questionsselected = (bool) ($categoryid || $qcontextid); -if ($categoryid) { +$questionsselected = (bool) ($categoryid || $qcontextid || $questionid); +if ($questionid) { + $top = $questionlist->get_instance($questionid); +} else if ($categoryid) { $top = $categorylist->get_instance($categoryid); } else if ($qcontextid) { $top = $contextlist->get_instance($qcontextid); @@ -117,7 +124,7 @@ if ($categoryid) { if (!$confirm) { if ($questionsselected) { echo $contextlist->render('listitemaction', false, $top); - $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid')+array('confirm'=>1)); + $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid', 'questionid') + array('confirm'=>1)); $cancelurl = new moodle_url($PAGE->url); echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); } else { diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index 23cd17ab540..ecb5f4f93f2 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -144,6 +144,10 @@ class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { $a = new stdClass(); $a->name = $this->record->name; $thisitem = get_string('listitemquestion', 'qtype_ddmarker', $a); + if ($link) { + $actionurl = new moodle_url($PAGE->url, array('questionid'=> $this->record->id)); + $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); + } return $thisitem; } public function question_ids() { From c3efffdb72aa7221f84c7a6cd79fed642aa78550 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 31 Mar 2012 14:42:37 +0700 Subject: [PATCH 15/28] MDL-47494 ddmarker: NOBUG improvement in wording of messages for the user --- question/type/ddmarker/imagetargetconverter.php | 2 +- question/type/ddmarker/lang/en/qtype_ddmarker.php | 14 +++++++++----- question/type/ddmarker/questionlists.php | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 93423dd73e5..08c8090a16a 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -128,7 +128,7 @@ if (!$confirm) { $cancelurl = new moodle_url($PAGE->url); echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); } else { - echo $contextlist->render('listitem', true, $top); + echo $contextlist->render('listitemlist', true, $top); } } else if (confirm_sesskey()) { $questionlist->prepare_for_processing($top); diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index 1503967ed10..41211b816c1 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -56,11 +56,15 @@ $string['formerror_unrecognisedwidthheightpart'] = 'We do not recognise the widt $string['formerror_unrecognisedxypart'] = 'We do not recognise the x,y coordinates you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.'; $string['imagetargetconverter'] = 'Convert image target questions to drag and drop marker'; $string['infinite'] = 'Infinite'; -$string['listitemactioncategory'] = 'Convert all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemactioncontext'] = 'Convert all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemcategory'] = 'Questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemcontext'] = 'Questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemquestion'] = 'Question "{$a->name}"'; +$string['listitemactioncategory'] = 'About to convert all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemactioncontext'] = 'About to convert all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemactionquestion'] = 'About to convert question "{$a->name}"'; +$string['listitemlistcategory'] = 'Select all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemlistcontext'] = 'Select all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemlistquestion'] = 'Select question "{$a->name}"'; +$string['listitemprocessingcategory'] = 'Converting all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemprocessingcontext'] = 'Converting all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemprocessingquestion'] = 'Converted question "{$a->name}"'; $string['marker'] = 'Marker'; $string['marker_n'] = 'Marker {no}'; $string['markers'] = 'Markers'; diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index ecb5f4f93f2..5bbdbcb42e1 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -61,7 +61,7 @@ abstract class qtype_ddmarker_list_item { if (null === $progresstrace) { $progresstrace = new html_list_progress_trace(); } - $progresstrace->output((string)$this, $depth); + $progresstrace->output($this->render('listitemprocessing', false), $depth); $this->process_children($progresstrace, $depth); } @@ -143,7 +143,7 @@ class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { global $PAGE; $a = new stdClass(); $a->name = $this->record->name; - $thisitem = get_string('listitemquestion', 'qtype_ddmarker', $a); + $thisitem = get_string($stringidentifier.'question', 'qtype_ddmarker', $a); if ($link) { $actionurl = new moodle_url($PAGE->url, array('questionid'=> $this->record->id)); $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); From 45766c517adebce30ae4d05712fbe5c8250de879 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 31 Mar 2012 18:13:39 +0700 Subject: [PATCH 16/28] MDL-47494 ddmarker: NOBUG implemented conversion of question itself --- .../type/ddmarker/imagetargetconverter.php | 67 ++++++++++++++++++- question/type/ddmarker/questionlists.php | 15 +++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 08c8090a16a..19667a43c34 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -55,7 +55,70 @@ class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_questio parent::process($progresstrace, $depth);//outputs progress message } protected function convert_question() { - $questionrec = $this->record; + global $DB; + foreach ($this->answers as $answer) { + $no = 1; + if ('*' !== $answer->answer) { + $drop = new stdClass(); + $drop->questionid = $this->record->id; + $drop->shape = 'rectangle'; + $drop->no = $no; + list($x1, $y1, $x2, $y2) = explode(',', $answer->answer); + $width = $x2 - $x1; + $height = $y2 - $y1; + $drop->coords = "{$x1},{$y1};{$width},{$height}"; + $drop->choice = 1; + $DB->insert_record('qtype_ddmarker_drops', $drop); + $no++; + $correctfeedback = $answer->feedback; + $correctfeedbackformat = $answer->feedbackformat; + } else { + $incorrectfeedback = $answer->feedback; + $incorrectfeedbackformat = $answer->feedbackformat; + } + } + $drag = new stdClass(); + $drag->questionid = $this->record->id; + $drag->no = 1; + $drag->label = "X"; + $drag->infinite = 0; + $DB->insert_record('qtype_ddmarker_drags', $drag); + + $ddmarker = new stdClass(); + $ddmarker->questionid = $this->record->id; + $ddmarker->shuffleanswers = 0; + $ddmarker->correctfeedback = $correctfeedback; + $ddmarker->correctfeedbackformat = $correctfeedbackformat; + $ddmarker->partiallycorrectfeedback = ''; + $ddmarker->partiallycorrectfeedbackformat = 1; + $ddmarker->incorrectfeedback = $incorrectfeedback; + $ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat; + $ddmarker->shownumcorrect = 0; + $ddmarker->showmisplaced = 0; + $DB->insert_record('qtype_ddmarker', $ddmarker); + + $newrec = clone($this->record); + unset($newrec->contextid); + $newrec->qtype = 'ddmarker'; + $newrec->timemodified = time(); + $DB->update_record('question', $newrec); + + $fs = get_file_storage(); + $bgimagefile = $fs->get_file($this->course_context_id(), + 'course', + 'legacy', + '0', + '/'.dirname($this->imagetargetrecord->qimage).'/', + basename($this->imagetargetrecord->qimage)); + $newbgimagefile = new stdClass(); + $newbgimagefile->component = 'qtype_ddmarker'; + $newbgimagefile->filearea = 'bgimage'; + $newbgimagefile->filepath = '/'; + $newbgimagefile->itemid = $this->record->id; + $fs->create_file_from_storedfile($newbgimagefile, $bgimagefile); + + $DB->delete_records('question_imagetarget', array('question' => $this->record->id)); + $DB->delete_records('question_answers', array('question' => $this->record->id)); } } @@ -77,7 +140,7 @@ echo $OUTPUT->heading_with_help(get_string('imagetargetconverter', 'qtype_ddmark $params = array(); $from = 'FROM {question_categories} cat, {question} q'; -$where = ' WHERE q.category = cat.id '; +$where = ' WHERE q.qtype = \'imagetarget\' AND q.category = cat.id '; if ($qcontextid) { $qcontext = get_context_instance_by_id($qcontextid, MUST_EXIST); diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index 5bbdbcb42e1..af4668d8a3b 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -96,6 +96,13 @@ abstract class qtype_ddmarker_list_item { return get_class($this).' '.$this->record->id; } + /** + * @return the course id in which this item is contained or the id of the front page course + */ + public function course_context_id() { + return $this->parent_node()->course_context_id(); + } + } class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { @@ -185,6 +192,14 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { } return $thisitem.$this->render_children($stringidentifier, $link); } + + public function course_context_id() { + if ((int)$this->record->contextlevel === CONTEXT_COURSE) { + return $this->record->id; + } else { + return parent::course_context_id(); + } + } } /** * Describes a nested list of listitems. This class and sub classes contain the functionality to build the nested list. From a79d43fe9c21d7a3f1a4589627c91c27a53a3118 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 1 Apr 2012 17:30:42 +0700 Subject: [PATCH 17/28] MDL-47494 ddmarker: NOBUG adding a condition to catch if there are no questions to convert --- .../type/ddmarker/imagetargetconverter.php | 69 ++++++++++--------- .../type/ddmarker/lang/en/qtype_ddmarker.php | 1 + 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 19667a43c34..364d6451381 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -162,41 +162,44 @@ $sql = 'SELECT q.*, cat.contextid '.$from.$where.'ORDER BY cat.id, q.name'; $questions = $DB->get_records_sql($sql, $params); -$contextids = array(); -foreach ($questions as $question) { - $contextids[] = $question->contextid; -} - -$contextlist = new qtype_ddmarker_context_list(array_unique($contextids)); -$categorylist = new qtype_ddmarker_category_list($contextids, $contextlist); -$questionlist = new qtype_ddmarker_question_converter_list($questions, $categorylist); - -foreach ($questions as $question) { - $questionlist->leaf_node($question->id, 1); -} -$questionsselected = (bool) ($categoryid || $qcontextid || $questionid); -if ($questionid) { - $top = $questionlist->get_instance($questionid); -} else if ($categoryid) { - $top = $categorylist->get_instance($categoryid); -} else if ($qcontextid) { - $top = $contextlist->get_instance($qcontextid); +if (!count($questions)) { + echo html_writer::tag('div', get_string('noquestionsfound', 'qtype_ddmarker')); } else { - $top = $contextlist->root_node(); -} -if (!$confirm) { - if ($questionsselected) { - echo $contextlist->render('listitemaction', false, $top); - $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid', 'questionid') + array('confirm'=>1)); - $cancelurl = new moodle_url($PAGE->url); - echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); - } else { - echo $contextlist->render('listitemlist', true, $top); + $contextids = array(); + foreach ($questions as $question) { + $contextids[] = $question->contextid; } -} else if (confirm_sesskey()) { - $questionlist->prepare_for_processing($top); - $top->process(); -} + $contextlist = new qtype_ddmarker_context_list(array_unique($contextids)); + $categorylist = new qtype_ddmarker_category_list($contextids, $contextlist); + $questionlist = new qtype_ddmarker_question_converter_list($questions, $categorylist); + + foreach ($questions as $question) { + $questionlist->leaf_node($question->id, 1); + } + $questionsselected = (bool) ($categoryid || $qcontextid || $questionid); + if ($questionid) { + $top = $questionlist->get_instance($questionid); + } else if ($categoryid) { + $top = $categorylist->get_instance($categoryid); + } else if ($qcontextid) { + $top = $contextlist->get_instance($qcontextid); + } else { + $top = $contextlist->root_node(); + } + if (!$confirm) { + if ($questionsselected) { + echo $contextlist->render('listitemaction', false, $top); + $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid', 'questionid') + array('confirm'=>1)); + $cancelurl = new moodle_url($PAGE->url); + echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); + } else { + echo $contextlist->render('listitemlist', true, $top); + } + } else if (confirm_sesskey()) { + $questionlist->prepare_for_processing($top); + $top->process(); + } +} // Footer. echo $OUTPUT->footer(); diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index 41211b816c1..aa4cc9263b9 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -69,6 +69,7 @@ $string['marker'] = 'Marker'; $string['marker_n'] = 'Marker {no}'; $string['markers'] = 'Markers'; $string['nolabel'] = 'No label text'; +$string['noquestionsfound'] = 'No questions found to convert here.'; $string['pleasedragatleastonemarker'] = 'Your answer is not complete, you must place at least one marker on the image.'; $string['pluginname'] = 'Drag and drop markers'; $string['previewarea'] = 'Preview area -'; From 35c7dea6d201de9fd72ba5920119ffe09257e3af Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 2 Apr 2012 16:33:09 +0700 Subject: [PATCH 18/28] MDL-47494 ddmarker: NOBUG added script needed for upgrading attempt data from imagetarget qs --- question/type/ddmarker/db/upgradelib.php | 85 ++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 question/type/ddmarker/db/upgradelib.php diff --git a/question/type/ddmarker/db/upgradelib.php b/question/type/ddmarker/db/upgradelib.php new file mode 100644 index 00000000000..2ab9118ddb7 --- /dev/null +++ b/question/type/ddmarker/db/upgradelib.php @@ -0,0 +1,85 @@ +. + +/** + * Upgrade library code for the ddmarker question type. This will only get triggered by the code + * to convert imagetarget questions to ddmarker. + * + * @package qtype + * @subpackage ddmarker + * @copyright 2012 Jamie Pratt + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +/** + * Class for converting attempt data from imagetarget questions when converting + * attempts to the new question engine. + * + * This class is used by the code in question/engine/upgrade/upgradelib.php. + * + * @copyright 2010 The Open University + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class qtype_ddmarker_qe2_attempt_updater extends question_qtype_attempt_updater { + public function right_answer() { + $drag = reset($this->question->options->drags); + return '{'.get_string('dropzone', 'qtype_ddmarker', '1')." -> ".$drag->label.'}'; + } + + public function was_answered($state) { + return !empty($state->answer); + } + + public function response_summary($state) { + if (!empty($state->answer)) { + $drag = reset($this->question->options->drags); + foreach ($this->question->options->drops as $drop) { + list($xy, $wh) = explode(';', $drop->coords); + list($x, $y) = explode(',', $xy); + list($w, $h) = explode(',', $wh); + list($answerx, $answery) = explode(',', $state->answer); + if (($answerx >= $x && $answerx <= ($x + $w)) && ($answery >= $y && $answery <= ($y + $h))) { + return '{'.get_string('dropzone', 'qtype_ddmarker', $drop->no)." -> ".$drag->label.'}'; + } + } + return ''; + } else { + return null; + } + } + + public function question_summary() { + $drag = reset($this->question->options->drags); + return parent::question_summary().'[['.get_string('dropzone', 'qtype_ddmarker', '1')."]] -> {".$drag->label.'}'; + } + + public function set_first_step_data_elements($state, &$data) { + $data['_choiceorder1'] = '1'; + } + + public function supply_missing_first_step_data(&$data) { + } + + public function set_data_elements_for_step($state, &$data) { + if (!empty($state->answer)) { + $data['c1'] = $state->answer; + } + } +} From 5153be2b26f32dfd245e71ecbda2360e39dc80f3 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Mon, 2 Apr 2012 17:20:12 +0700 Subject: [PATCH 19/28] MDL-47494 ddmarker: NOBUG not using list progress trace any more as it is has a bug --- .../type/ddmarker/imagetargetconverter.php | 2 ++ question/type/ddmarker/questionlists.php | 35 +++++++++++-------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 364d6451381..6533917d38b 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -198,7 +198,9 @@ if (!count($questions)) { } } else if (confirm_sesskey()) { $questionlist->prepare_for_processing($top); + echo '
    '; $top->process(); + echo '
'; } } // Footer. diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index af4668d8a3b..9f8a0ba9f4d 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -46,7 +46,11 @@ abstract class qtype_ddmarker_list_item { abstract protected function parent_node (); - abstract public function render($stringidentifier, $link); + public function render($stringidentifier, $link) { + return $this->render_item($stringidentifier, $link).$this->render_children($stringidentifier, $link); + } + + abstract protected function render_item($stringidentifier, $link); public function leaf_to_root($qcount) { $this->qcount += $qcount; @@ -57,19 +61,20 @@ abstract class qtype_ddmarker_list_item { } } - public function process($progresstrace = null, $depth = 0) { - if (null === $progresstrace) { - $progresstrace = new html_list_progress_trace(); - } - $progresstrace->output($this->render('listitemprocessing', false), $depth); - $this->process_children($progresstrace, $depth); + public function process() { + echo '
  • '; + echo $this->render_item('listitemprocessing', false); + $this->process_children(); + echo '
  • '; + flush(); } - protected function process_children($progresstrace, $depth) { - $children = array(); + protected function process_children() { + echo '
      '; foreach ($this->children as $child) { - $child->process($progresstrace, $depth + 1); + $child->process(); } + echo '
    '; } public function question_ids() { @@ -120,7 +125,7 @@ class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { } } - public function render ($stringidentifier, $link) { + protected function render_item ($stringidentifier, $link) { global $PAGE; $a = new stdClass(); $a->qcount = $this->qcount; @@ -131,7 +136,7 @@ class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); } - return $thisitem.$this->render_children($stringidentifier, $link); + return $thisitem; } } class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { @@ -146,7 +151,7 @@ class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { return $this->parentlist->get_instance($this->record->category); } - public function render ($stringidentifier, $link) { + protected function render_item ($stringidentifier, $link) { global $PAGE; $a = new stdClass(); $a->name = $this->record->name; @@ -180,7 +185,7 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { } } - public function render ($stringidentifier, $link) { + protected function render_item ($stringidentifier, $link) { global $PAGE; $a = new stdClass(); $a->qcount = $this->qcount; @@ -190,7 +195,7 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { $actionurl = new moodle_url($PAGE->url, array('contextid'=> $this->record->id)); $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); } - return $thisitem.$this->render_children($stringidentifier, $link); + return $thisitem; } public function course_context_id() { From d544fb24ce8e95e69b0f4957e989d8d42fe57eb0 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 4 Apr 2012 12:58:02 +0700 Subject: [PATCH 20/28] MDL-47494 ddmarker: NOBUG added script to do upgrade automatically during 2.1 site upgrade --- question/type/ddmarker/db/install.php | 166 ++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 question/type/ddmarker/db/install.php diff --git a/question/type/ddmarker/db/install.php b/question/type/ddmarker/db/install.php new file mode 100644 index 00000000000..59a39eb8cb2 --- /dev/null +++ b/question/type/ddmarker/db/install.php @@ -0,0 +1,166 @@ +. + +/** + * Matching question type upgrade code. + * + * @package qtype + * @subpackage match + * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + + +defined('MOODLE_INTERNAL') || die(); + + +function index_array_of_records_by_key($key, $recs) { + $out = array(); + foreach ($recs as $id => $rec) { + if (!isset($out[$rec->{$key}])) { + $out[$rec->{$key}] = array(); + } + $out[$rec->{$key}][$id] = $rec; + } + return $out; +} + +function course_context_id($catcontextid) { + $context = get_context_instance_by_id($catcontextid); + while ($context->contextlevel != CONTEXT_COURSE) { + $context = get_context_instance_by_id(get_parent_contextid($context)); + } + return $context->id; +} +/** + * Upgrade code for the matching question type. + * @param int $oldversion the version we are upgrading from. + */ +function xmldb_qtype_ddmarker_install() { + global $DB, $OUTPUT; + + $from = 'FROM {question_categories} cat, {question} q'; + $where = ' WHERE q.qtype = \'imagetarget\' AND q.category = cat.id '; + + $sql = 'SELECT q.*, cat.contextid '.$from.$where.'ORDER BY cat.id, q.name'; + + $questions = $DB->get_records_sql($sql); + + if (!empty($questions)) { + foreach ($questions as $question) { + $dragssql = 'SELECT drag.* '.$from.', {qtype_ddmarker_drags} drag'.$where.' AND drag.questionid = q.id'; + $drags = index_array_of_records_by_key('questionid', $DB->get_records_sql($dragssql)); + + $dropssql = 'SELECT drop.* '.$from.', {qtype_ddmarker_drops} drop'.$where.' AND drop.questionid = q.id'; + $drops = index_array_of_records_by_key('questionid', $DB->get_records_sql($dropssql)); + + $answerssql = 'SELECT answer.* '.$from.', {question_answers} answer'.$where.' AND answer.question = q.id'; + $answers = index_array_of_records_by_key('question', $DB->get_records_sql($answerssql)); + + $imgfiles = $DB->get_records_sql_menu('SELECT question, qimage FROM {question_imagetarget}'); + + $correctfeedback = ''; + $correctfeedbackformat = 1; + $incorrectfeedback = ''; + $incorrectfeedbackformat = 1; + $foundincorrectanswer = false; + foreach ($answers[$question->id] as $answer) { + $no = 1; + if ('*' !== $answer->answer) { + $drop = new stdClass(); + $drop->questionid = $question->id; + $drop->shape = 'rectangle'; + $drop->no = $no; + list($x1, $y1, $x2, $y2) = explode(',', $answer->answer); + $width = $x2 - $x1; + $height = $y2 - $y1; + $drop->coords = "{$x1},{$y1};{$width},{$height}"; + $drop->choice = 1; + $DB->insert_record('qtype_ddmarker_drops', $drop); + $no++; + $correctfeedback = $answer->feedback; + $correctfeedbackformat = $answer->feedbackformat; + } else { + $foundincorrectanswer = false; + $incorrectfeedback = $answer->feedback; + $incorrectfeedbackformat = $answer->feedbackformat; + } + } + if (count($answers[$question->id]) < 2) { + echo $OUTPUT->notification('There are less than 2 answers. '. + '(Normally we expect at least a correct and incorrect answer). '. + 'For question id '.$question->id.' "'.$question->name.'".', + 'notifyproblem'); + } + if (!$foundincorrectanswer) { + echo $OUTPUT->notification('No incorrect answer found for question id '.$question->id.' "'.$question->name.'".', + 'notifyproblem'); + } + $drag = new stdClass(); + $drag->questionid = $question->id; + $drag->no = 1; + $drag->label = "X"; + $drag->infinite = 0; + $DB->insert_record('qtype_ddmarker_drags', $drag); + + $ddmarker = new stdClass(); + $ddmarker->questionid = $question->id; + $ddmarker->shuffleanswers = 0; + $ddmarker->correctfeedback = $correctfeedback; + $ddmarker->correctfeedbackformat = $correctfeedbackformat; + $ddmarker->partiallycorrectfeedback = ''; + $ddmarker->partiallycorrectfeedbackformat = 1; + $ddmarker->incorrectfeedback = $incorrectfeedback; + $ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat; + $ddmarker->shownumcorrect = 0; + $ddmarker->showmisplaced = 0; + $DB->insert_record('qtype_ddmarker', $ddmarker); + + $newrec = clone($question); + unset($newrec->contextid); + $newrec->qtype = 'ddmarker'; + $newrec->timemodified = time(); + $DB->update_record('question', $newrec); + + $fs = get_file_storage(); + //we need to look in the course legacy files area for file + $bgimagefile = $fs->get_file(course_context_id($question->contextid), + 'course', + 'legacy', + '0', + '/'.dirname($imgfiles[$question->id]).'/', + basename($imgfiles[$question->id])); + if ($bgimagefile === false) { + echo $OUTPUT->notification('File "'.$imgfiles[$question->id].'" not found in legacy course files area. '. + 'For question id '.$question->id.' "'.$question->name.'".', + 'notifyproblem'); + } else { + $newbgimagefile = new stdClass(); + $newbgimagefile->component = 'qtype_ddmarker'; + $newbgimagefile->filearea = 'bgimage'; + $newbgimagefile->filepath = '/'; + $newbgimagefile->itemid = $question->id; + $newbgimagefile->contextid = $question->contextid; + $fs->create_file_from_storedfile($newbgimagefile, $bgimagefile); + } + } + + list($qsql, $qparams) = $DB->get_in_or_equal(array_keys($questions)); + $DB->delete_records_select('question_answers', 'question '.$qsql, $qparams); + $dbman = $DB->get_manager(); + $dbman->drop_table(new xmldb_table('question_imagetarget')); + } +} From 86529cb3abd489f79bb88070ee0cd6738a87c155 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Wed, 4 Apr 2012 14:42:40 +0700 Subject: [PATCH 21/28] MDL-47494 ddmarker: NOBUG refactoring so that automatic and manual conversion code is shared --- question/type/ddmarker/db/install.php | 141 +++--------------- question/type/ddmarker/db/upgradelib.php | 1 - .../type/ddmarker/imagetargetconverter.php | 69 +-------- question/type/ddmarker/lib.php | 98 ++++++++++++ 4 files changed, 124 insertions(+), 185 deletions(-) diff --git a/question/type/ddmarker/db/install.php b/question/type/ddmarker/db/install.php index 59a39eb8cb2..dfa98f087af 100644 --- a/question/type/ddmarker/db/install.php +++ b/question/type/ddmarker/db/install.php @@ -15,7 +15,7 @@ // along with Moodle. If not, see . /** - * Matching question type upgrade code. + * ddmarker question type installation code. * * @package qtype * @subpackage match @@ -27,27 +27,8 @@ defined('MOODLE_INTERNAL') || die(); -function index_array_of_records_by_key($key, $recs) { - $out = array(); - foreach ($recs as $id => $rec) { - if (!isset($out[$rec->{$key}])) { - $out[$rec->{$key}] = array(); - } - $out[$rec->{$key}][$id] = $rec; - } - return $out; -} - -function course_context_id($catcontextid) { - $context = get_context_instance_by_id($catcontextid); - while ($context->contextlevel != CONTEXT_COURSE) { - $context = get_context_instance_by_id(get_parent_contextid($context)); - } - return $context->id; -} /** - * Upgrade code for the matching question type. - * @param int $oldversion the version we are upgrading from. + * Installation code for the ddmarker question type. It converts all existing imagetarget questions to ddmarker */ function xmldb_qtype_ddmarker_install() { global $DB, $OUTPUT; @@ -60,107 +41,33 @@ function xmldb_qtype_ddmarker_install() { $questions = $DB->get_records_sql($sql); if (!empty($questions)) { + require_once(dirname(__FILE__).'/../lib.php'); + $dragssql = 'SELECT drag.* '.$from.', {qtype_ddmarker_drags} drag'.$where.' AND drag.questionid = q.id'; + $drags = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dragssql)); + + $dropssql = 'SELECT drop.* '.$from.', {qtype_ddmarker_drops} drop'.$where.' AND drop.questionid = q.id'; + $drops = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dropssql)); + + $answerssql = 'SELECT answer.* '.$from.', {question_answers} answer'.$where.' AND answer.question = q.id'; + $answers = xmldb_qtype_ddmarker_index_array_of_records_by_key('question', $DB->get_records_sql($answerssql)); + + $imgfiles = $DB->get_records_sql_menu('SELECT question, qimage FROM {question_imagetarget}'); foreach ($questions as $question) { - $dragssql = 'SELECT drag.* '.$from.', {qtype_ddmarker_drags} drag'.$where.' AND drag.questionid = q.id'; - $drags = index_array_of_records_by_key('questionid', $DB->get_records_sql($dragssql)); - - $dropssql = 'SELECT drop.* '.$from.', {qtype_ddmarker_drops} drop'.$where.' AND drop.questionid = q.id'; - $drops = index_array_of_records_by_key('questionid', $DB->get_records_sql($dropssql)); - - $answerssql = 'SELECT answer.* '.$from.', {question_answers} answer'.$where.' AND answer.question = q.id'; - $answers = index_array_of_records_by_key('question', $DB->get_records_sql($answerssql)); - - $imgfiles = $DB->get_records_sql_menu('SELECT question, qimage FROM {question_imagetarget}'); - - $correctfeedback = ''; - $correctfeedbackformat = 1; - $incorrectfeedback = ''; - $incorrectfeedbackformat = 1; - $foundincorrectanswer = false; - foreach ($answers[$question->id] as $answer) { - $no = 1; - if ('*' !== $answer->answer) { - $drop = new stdClass(); - $drop->questionid = $question->id; - $drop->shape = 'rectangle'; - $drop->no = $no; - list($x1, $y1, $x2, $y2) = explode(',', $answer->answer); - $width = $x2 - $x1; - $height = $y2 - $y1; - $drop->coords = "{$x1},{$y1};{$width},{$height}"; - $drop->choice = 1; - $DB->insert_record('qtype_ddmarker_drops', $drop); - $no++; - $correctfeedback = $answer->feedback; - $correctfeedbackformat = $answer->feedbackformat; - } else { - $foundincorrectanswer = false; - $incorrectfeedback = $answer->feedback; - $incorrectfeedbackformat = $answer->feedbackformat; - } - } - if (count($answers[$question->id]) < 2) { - echo $OUTPUT->notification('There are less than 2 answers. '. - '(Normally we expect at least a correct and incorrect answer). '. - 'For question id '.$question->id.' "'.$question->name.'".', - 'notifyproblem'); - } - if (!$foundincorrectanswer) { - echo $OUTPUT->notification('No incorrect answer found for question id '.$question->id.' "'.$question->name.'".', - 'notifyproblem'); - } - $drag = new stdClass(); - $drag->questionid = $question->id; - $drag->no = 1; - $drag->label = "X"; - $drag->infinite = 0; - $DB->insert_record('qtype_ddmarker_drags', $drag); - - $ddmarker = new stdClass(); - $ddmarker->questionid = $question->id; - $ddmarker->shuffleanswers = 0; - $ddmarker->correctfeedback = $correctfeedback; - $ddmarker->correctfeedbackformat = $correctfeedbackformat; - $ddmarker->partiallycorrectfeedback = ''; - $ddmarker->partiallycorrectfeedbackformat = 1; - $ddmarker->incorrectfeedback = $incorrectfeedback; - $ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat; - $ddmarker->shownumcorrect = 0; - $ddmarker->showmisplaced = 0; - $DB->insert_record('qtype_ddmarker', $ddmarker); - - $newrec = clone($question); - unset($newrec->contextid); - $newrec->qtype = 'ddmarker'; - $newrec->timemodified = time(); - $DB->update_record('question', $newrec); - - $fs = get_file_storage(); - //we need to look in the course legacy files area for file - $bgimagefile = $fs->get_file(course_context_id($question->contextid), - 'course', - 'legacy', - '0', - '/'.dirname($imgfiles[$question->id]).'/', - basename($imgfiles[$question->id])); - if ($bgimagefile === false) { - echo $OUTPUT->notification('File "'.$imgfiles[$question->id].'" not found in legacy course files area. '. - 'For question id '.$question->id.' "'.$question->name.'".', - 'notifyproblem'); - } else { - $newbgimagefile = new stdClass(); - $newbgimagefile->component = 'qtype_ddmarker'; - $newbgimagefile->filearea = 'bgimage'; - $newbgimagefile->filepath = '/'; - $newbgimagefile->itemid = $question->id; - $newbgimagefile->contextid = $question->contextid; - $fs->create_file_from_storedfile($newbgimagefile, $bgimagefile); - } + qtype_ddmarker_convert_image_target_question($question, $imgfiles[$question->id], $answers[$question->id]); } - list($qsql, $qparams) = $DB->get_in_or_equal(array_keys($questions)); $DB->delete_records_select('question_answers', 'question '.$qsql, $qparams); $dbman = $DB->get_manager(); $dbman->drop_table(new xmldb_table('question_imagetarget')); } } +function xmldb_qtype_ddmarker_index_array_of_records_by_key($key, $recs) { + $out = array(); + foreach ($recs as $id => $rec) { + if (!isset($out[$rec->{$key}])) { + $out[$rec->{$key}] = array(); + } + $out[$rec->{$key}][$id] = $rec; + } + return $out; +} diff --git a/question/type/ddmarker/db/upgradelib.php b/question/type/ddmarker/db/upgradelib.php index 2ab9118ddb7..7c854a4c5c9 100644 --- a/question/type/ddmarker/db/upgradelib.php +++ b/question/type/ddmarker/db/upgradelib.php @@ -27,7 +27,6 @@ defined('MOODLE_INTERNAL') || die(); - /** * Class for converting attempt data from imagetarget questions when converting * attempts to the new question engine. diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index 6533917d38b..ebb8dece159 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -51,75 +51,9 @@ class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_questio public $imagetargetrecord = null; public $answers = array(); public function process($progresstrace = null, $depth = 0) { - $this->convert_question(); + qtype_ddmarker_convert_image_target_question($this->record, $this->imagetargetrecord->qimage, $this->answers); parent::process($progresstrace, $depth);//outputs progress message } - protected function convert_question() { - global $DB; - foreach ($this->answers as $answer) { - $no = 1; - if ('*' !== $answer->answer) { - $drop = new stdClass(); - $drop->questionid = $this->record->id; - $drop->shape = 'rectangle'; - $drop->no = $no; - list($x1, $y1, $x2, $y2) = explode(',', $answer->answer); - $width = $x2 - $x1; - $height = $y2 - $y1; - $drop->coords = "{$x1},{$y1};{$width},{$height}"; - $drop->choice = 1; - $DB->insert_record('qtype_ddmarker_drops', $drop); - $no++; - $correctfeedback = $answer->feedback; - $correctfeedbackformat = $answer->feedbackformat; - } else { - $incorrectfeedback = $answer->feedback; - $incorrectfeedbackformat = $answer->feedbackformat; - } - } - $drag = new stdClass(); - $drag->questionid = $this->record->id; - $drag->no = 1; - $drag->label = "X"; - $drag->infinite = 0; - $DB->insert_record('qtype_ddmarker_drags', $drag); - - $ddmarker = new stdClass(); - $ddmarker->questionid = $this->record->id; - $ddmarker->shuffleanswers = 0; - $ddmarker->correctfeedback = $correctfeedback; - $ddmarker->correctfeedbackformat = $correctfeedbackformat; - $ddmarker->partiallycorrectfeedback = ''; - $ddmarker->partiallycorrectfeedbackformat = 1; - $ddmarker->incorrectfeedback = $incorrectfeedback; - $ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat; - $ddmarker->shownumcorrect = 0; - $ddmarker->showmisplaced = 0; - $DB->insert_record('qtype_ddmarker', $ddmarker); - - $newrec = clone($this->record); - unset($newrec->contextid); - $newrec->qtype = 'ddmarker'; - $newrec->timemodified = time(); - $DB->update_record('question', $newrec); - - $fs = get_file_storage(); - $bgimagefile = $fs->get_file($this->course_context_id(), - 'course', - 'legacy', - '0', - '/'.dirname($this->imagetargetrecord->qimage).'/', - basename($this->imagetargetrecord->qimage)); - $newbgimagefile = new stdClass(); - $newbgimagefile->component = 'qtype_ddmarker'; - $newbgimagefile->filearea = 'bgimage'; - $newbgimagefile->filepath = '/'; - $newbgimagefile->itemid = $this->record->id; - $fs->create_file_from_storedfile($newbgimagefile, $bgimagefile); - - $DB->delete_records('question_imagetarget', array('question' => $this->record->id)); - $DB->delete_records('question_answers', array('question' => $this->record->id)); - } } $categoryid = optional_param('categoryid', 0, PARAM_INT); @@ -197,6 +131,7 @@ if (!count($questions)) { echo $contextlist->render('listitemlist', true, $top); } } else if (confirm_sesskey()) { + require_once(dirname(__FILE__).'/lib.php'); $questionlist->prepare_for_processing($top); echo '
      '; $top->process(); diff --git a/question/type/ddmarker/lib.php b/question/type/ddmarker/lib.php index 7d2cb6d9bc0..2c7cdae3da3 100644 --- a/question/type/ddmarker/lib.php +++ b/question/type/ddmarker/lib.php @@ -36,3 +36,101 @@ function qtype_ddmarker_pluginfile($course, $cm, $context, $filearea, $args, $fo require_once($CFG->libdir . '/questionlib.php'); question_pluginfile($course, $context, 'qtype_ddmarker', $filearea, $args, $forcedownload); } + + + +function qtype_ddmarker_course_context_id($catcontextid) { + $context = get_context_instance_by_id($catcontextid); + while ($context->contextlevel != CONTEXT_COURSE) { + $context = get_context_instance_by_id(get_parent_contextid($context)); + } + return $context->id; +} + +function qtype_ddmarker_convert_image_target_question($question, $imgfilename, $answers) { + global $DB, $OUTPUT; + $correctfeedback = ''; + $correctfeedbackformat = 1; + $incorrectfeedback = ''; + $incorrectfeedbackformat = 1; + $foundincorrectanswer = false; + foreach ($answers as $answer) { + $no = 1; + if ('*' !== $answer->answer) { + $drop = new stdClass(); + $drop->questionid = $question->id; + $drop->shape = 'rectangle'; + $drop->no = $no; + list($x1, $y1, $x2, $y2) = explode(',', $answer->answer); + $width = $x2 - $x1; + $height = $y2 - $y1; + $drop->coords = "{$x1},{$y1};{$width},{$height}"; + $drop->choice = 1; + $DB->insert_record('qtype_ddmarker_drops', $drop); + $no++; + $correctfeedback = $answer->feedback; + $correctfeedbackformat = $answer->feedbackformat; + } else { + $foundincorrectanswer = true; + $incorrectfeedback = $answer->feedback; + $incorrectfeedbackformat = $answer->feedbackformat; + } + } + if (count($answers) < 2) { + echo $OUTPUT->notification('There are less than 2 answers. '. + '(Normally we expect at least a correct and incorrect answer). '. + 'For question id '.$question->id.' "'.$question->name.'".', + 'notifyproblem'); + } + if (!$foundincorrectanswer) { + echo $OUTPUT->notification('No incorrect answer found for question id '.$question->id.' "'.$question->name.'".', + 'notifyproblem'); + } + $drag = new stdClass(); + $drag->questionid = $question->id; + $drag->no = 1; + $drag->label = "X"; + $drag->infinite = 0; + $DB->insert_record('qtype_ddmarker_drags', $drag); + + $ddmarker = new stdClass(); + $ddmarker->questionid = $question->id; + $ddmarker->shuffleanswers = 0; + $ddmarker->correctfeedback = $correctfeedback; + $ddmarker->correctfeedbackformat = $correctfeedbackformat; + $ddmarker->partiallycorrectfeedback = ''; + $ddmarker->partiallycorrectfeedbackformat = 1; + $ddmarker->incorrectfeedback = $incorrectfeedback; + $ddmarker->incorrectfeedbackformat = $incorrectfeedbackformat; + $ddmarker->shownumcorrect = 0; + $ddmarker->showmisplaced = 0; + $DB->insert_record('qtype_ddmarker', $ddmarker); + + $newrec = clone($question); + unset($newrec->contextid); + $newrec->qtype = 'ddmarker'; + $newrec->timemodified = time(); + $DB->update_record('question', $newrec); + + $fs = get_file_storage(); + //we need to look in the course legacy files area for file + $bgimagefile = $fs->get_file(qtype_ddmarker_course_context_id($question->contextid), + 'course', + 'legacy', + '0', + '/'.dirname($imgfilename).'/', + basename($imgfilename)); + if ($bgimagefile === false) { + echo $OUTPUT->notification('File "'.$imgfilename.'" not found in legacy course files area. '. + 'For question id '.$question->id.' "'.$question->name.'".', + 'notifyproblem'); + } else { + $newbgimagefile = new stdClass(); + $newbgimagefile->component = 'qtype_ddmarker'; + $newbgimagefile->filearea = 'bgimage'; + $newbgimagefile->filepath = '/'; + $newbgimagefile->itemid = $question->id; + $newbgimagefile->contextid = $question->contextid; + $fs->create_file_from_storedfile($newbgimagefile, $bgimagefile); + } +} \ No newline at end of file From 34ec5ad14dd141ac5456148945ce5d8a41c24931 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 7 Apr 2012 14:23:18 +0700 Subject: [PATCH 22/28] MDL-47494 ddmarker: NOBUG made string for label into a constant so it is easy to change --- question/type/ddmarker/lib.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/question/type/ddmarker/lib.php b/question/type/ddmarker/lib.php index 2c7cdae3da3..fc09c0cfb8b 100644 --- a/question/type/ddmarker/lib.php +++ b/question/type/ddmarker/lib.php @@ -27,6 +27,11 @@ defined('MOODLE_INTERNAL') || die(); +/** + * + * @var string label to use for drag items when converting image target questions to ddmarker question type + */ +define('QTYPE_DDMARKER_LABEL_FOR_MARKER_FOR_IMAGE_TARGET_QS', 'X'); /** * Checks file access for essay questions. @@ -89,7 +94,7 @@ function qtype_ddmarker_convert_image_target_question($question, $imgfilename, $ $drag = new stdClass(); $drag->questionid = $question->id; $drag->no = 1; - $drag->label = "X"; + $drag->label = QTYPE_DDMARKER_LABEL_FOR_MARKER_FOR_IMAGE_TARGET_QS; $drag->infinite = 0; $DB->insert_record('qtype_ddmarker_drags', $drag); From 6a3b5993665040f974f8c1ed4ac4afe4b155785e Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 7 Apr 2012 14:24:25 +0700 Subject: [PATCH 23/28] MDL-47494 ddmarker: NOBUG added progress bar for question conversion during upgrade --- question/type/ddmarker/db/install.php | 5 +++++ question/type/ddmarker/lang/en/qtype_ddmarker.php | 1 + 2 files changed, 6 insertions(+) diff --git a/question/type/ddmarker/db/install.php b/question/type/ddmarker/db/install.php index dfa98f087af..98b000eebef 100644 --- a/question/type/ddmarker/db/install.php +++ b/question/type/ddmarker/db/install.php @@ -52,8 +52,13 @@ function xmldb_qtype_ddmarker_install() { $answers = xmldb_qtype_ddmarker_index_array_of_records_by_key('question', $DB->get_records_sql($answerssql)); $imgfiles = $DB->get_records_sql_menu('SELECT question, qimage FROM {question_imagetarget}'); + $progressbar = new progress_bar('qtype_ddmarker_convert_from_imagetarget'); + $progressbar->create(); + $done = 0; foreach ($questions as $question) { qtype_ddmarker_convert_image_target_question($question, $imgfiles[$question->id], $answers[$question->id]); + $done++; + $progressbar->update($done, count($questions), get_string('convertingimagetargetquestion', 'qtype_ddmarker', $question)); } list($qsql, $qparams) = $DB->get_in_or_equal(array_keys($questions)); $DB->delete_records_select('question_answers', 'question '.$qsql, $qparams); diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index aa4cc9263b9..071be068250 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -29,6 +29,7 @@ $string['answer'] = 'Answer'; $string['bgimage'] = 'Background image'; $string['confirmimagetargetconversion'] = 'You are about to convert the above image target questions to the drag and drop markers question type.'; $string['coords'] = 'Coords'; +$string['convertingimagetargetquestion'] = 'Converted question "{$a->name}"'; $string['correctansweris'] = 'The correct answer is: {$a}'; $string['ddmarker'] = 'Drag and drop markers'; $string['ddmarker_help'] = 'select a background image file, enter text labels for markers and define the drop zones on the background image to which they must be dragged.'; From b409f1990e0037643fb63598d0ccd7d4d837556b Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sat, 7 Apr 2012 14:34:58 +0700 Subject: [PATCH 24/28] MDL-47494 ddmarker: NOBUG fixing and updating tags in phpdoc comments --- .../backup/moodle2/backup_qtype_ddmarker_plugin.class.php | 7 ++++--- .../backup/moodle2/restore_qtype_ddmarker_plugin.class.php | 7 ++++--- question/type/ddmarker/db/install.php | 5 +++-- question/type/ddmarker/db/upgradelib.php | 3 ++- question/type/ddmarker/edit_ddmarker_form.php | 3 ++- question/type/ddmarker/imagetargetconverter.php | 3 ++- question/type/ddmarker/lang/en/qtype_ddmarker.php | 3 ++- question/type/ddmarker/lib.php | 6 +++--- question/type/ddmarker/question.php | 6 ++++-- question/type/ddmarker/questiontype.php | 3 ++- question/type/ddmarker/renderer.php | 6 ++++-- question/type/ddmarker/settings.php | 5 +++-- question/type/ddmarker/shapes.php | 6 ++++-- question/type/ddmarker/simpletest/helper.php | 6 ++++-- question/type/ddmarker/simpletest/testquestion.php | 6 ++++-- question/type/ddmarker/simpletest/testquestiontype.php | 6 ++++-- question/type/ddmarker/simpletest/testshapes.php | 3 ++- question/type/ddmarker/simpletest/testwalkthrough.php | 6 ++++-- question/type/ddmarker/version.php | 6 ++++-- 19 files changed, 61 insertions(+), 35 deletions(-) diff --git a/question/type/ddmarker/backup/moodle2/backup_qtype_ddmarker_plugin.class.php b/question/type/ddmarker/backup/moodle2/backup_qtype_ddmarker_plugin.class.php index d304edb9886..fc40930bc67 100644 --- a/question/type/ddmarker/backup/moodle2/backup_qtype_ddmarker_plugin.class.php +++ b/question/type/ddmarker/backup/moodle2/backup_qtype_ddmarker_plugin.class.php @@ -15,9 +15,10 @@ // along with Moodle. If not, see . /** - * @package moodlecore - * @subpackage backup-moodle2 - * @copyright 2011 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); diff --git a/question/type/ddmarker/backup/moodle2/restore_qtype_ddmarker_plugin.class.php b/question/type/ddmarker/backup/moodle2/restore_qtype_ddmarker_plugin.class.php index ea190807504..25e7233c479 100644 --- a/question/type/ddmarker/backup/moodle2/restore_qtype_ddmarker_plugin.class.php +++ b/question/type/ddmarker/backup/moodle2/restore_qtype_ddmarker_plugin.class.php @@ -15,9 +15,10 @@ // along with Moodle. If not, see . /** - * @package moodlecore - * @subpackage backup-moodle2 - * @copyright 2011 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/db/install.php b/question/type/ddmarker/db/install.php index 98b000eebef..45d415c6502 100644 --- a/question/type/ddmarker/db/install.php +++ b/question/type/ddmarker/db/install.php @@ -18,8 +18,9 @@ * ddmarker question type installation code. * * @package qtype - * @subpackage match - * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/db/upgradelib.php b/question/type/ddmarker/db/upgradelib.php index 7c854a4c5c9..fd2e3810edd 100644 --- a/question/type/ddmarker/db/upgradelib.php +++ b/question/type/ddmarker/db/upgradelib.php @@ -20,7 +20,8 @@ * * @package qtype * @subpackage ddmarker - * @copyright 2012 Jamie Pratt + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/edit_ddmarker_form.php b/question/type/ddmarker/edit_ddmarker_form.php index 9fc2d8efe76..5969a3367d8 100644 --- a/question/type/ddmarker/edit_ddmarker_form.php +++ b/question/type/ddmarker/edit_ddmarker_form.php @@ -24,7 +24,8 @@ define('QTYPE_DDMARKER_ALLOWED_TAGS_IN_MARKER', '
      * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index ebb8dece159..f5a99a66fea 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -19,7 +19,8 @@ * * @package qtype * @subpackage ddmarker - * @copyright 2012 Jamie Pratt + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index 071be068250..30fb9b249e9 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -18,7 +18,8 @@ * * @package qtype * @subpackage ddmarker - * @copyright 2011 The Open University + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/lib.php b/question/type/ddmarker/lib.php index fc09c0cfb8b..2eb5d3bbbf6 100644 --- a/question/type/ddmarker/lib.php +++ b/question/type/ddmarker/lib.php @@ -17,10 +17,10 @@ /** * Serve question type files * - * @since 2.0 * @package qtype - * @subpackage essay - * @copyright Dongsheng Cai + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/question.php b/question/type/ddmarker/question.php index 22cb99e408d..568313d4b50 100644 --- a/question/type/ddmarker/question.php +++ b/question/type/ddmarker/question.php @@ -17,8 +17,10 @@ /** * Drag-and-drop markers question definition class. * - * @package qtype_ddmarker - * @copyright 2009 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/questiontype.php b/question/type/ddmarker/questiontype.php index 66ffaf7cf61..e65d7945459 100644 --- a/question/type/ddmarker/questiontype.php +++ b/question/type/ddmarker/questiontype.php @@ -19,7 +19,8 @@ * * @package qtype * @subpackage ddmarker - * @copyright 2009 The Open University + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/renderer.php b/question/type/ddmarker/renderer.php index 0c047631d22..ef1285dd1f9 100644 --- a/question/type/ddmarker/renderer.php +++ b/question/type/ddmarker/renderer.php @@ -17,8 +17,10 @@ /** * Drag-and-drop markers question renderer class. * - * @package qtype_ddmarker - * @copyright 2010 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/settings.php b/question/type/ddmarker/settings.php index a523f7128df..e79d78ef513 100644 --- a/question/type/ddmarker/settings.php +++ b/question/type/ddmarker/settings.php @@ -18,8 +18,9 @@ * Admin settings for the Opaque question type. * * @package qtype - * @subpackage opaque - * @copyright 2011 The Open University + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/shapes.php b/question/type/ddmarker/shapes.php index eae350ced22..e645fc76b55 100644 --- a/question/type/ddmarker/shapes.php +++ b/question/type/ddmarker/shapes.php @@ -17,8 +17,10 @@ /** * Drag-and-drop markers classes for dealing with shapes on the server side. * - * @package qtype_ddmarker - * @copyright 2009 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class qtype_ddmarker_shape { diff --git a/question/type/ddmarker/simpletest/helper.php b/question/type/ddmarker/simpletest/helper.php index 1c773da62d3..a78d3e08bcf 100644 --- a/question/type/ddmarker/simpletest/helper.php +++ b/question/type/ddmarker/simpletest/helper.php @@ -17,8 +17,10 @@ /** * Test helpers for the drag-and-drop markers question type. * - * @package qtype_ddmarker - * @copyright 2010 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/simpletest/testquestion.php b/question/type/ddmarker/simpletest/testquestion.php index 705f95a49d0..7d1cafd86e1 100644 --- a/question/type/ddmarker/simpletest/testquestion.php +++ b/question/type/ddmarker/simpletest/testquestion.php @@ -17,8 +17,10 @@ /** * Unit tests for the drag-and-drop markers question definition class. * - * @package qtype_ddmarker - * @copyright 2010 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/simpletest/testquestiontype.php b/question/type/ddmarker/simpletest/testquestiontype.php index 63d0cdd1e7d..4c0b632a46f 100644 --- a/question/type/ddmarker/simpletest/testquestiontype.php +++ b/question/type/ddmarker/simpletest/testquestiontype.php @@ -17,8 +17,10 @@ /** * Unit tests for the drag-and-drop markers question definition class. * - * @package qtype_ddmarker - * @copyright 2010 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/simpletest/testshapes.php b/question/type/ddmarker/simpletest/testshapes.php index 42f8a5bfa0b..17279fc1036 100644 --- a/question/type/ddmarker/simpletest/testshapes.php +++ b/question/type/ddmarker/simpletest/testshapes.php @@ -19,7 +19,8 @@ * * @package qtype * @subpackage ddmarker - * @copyright 2010 The Open University + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/simpletest/testwalkthrough.php b/question/type/ddmarker/simpletest/testwalkthrough.php index 62411531aa9..3fc1a9187a5 100644 --- a/question/type/ddmarker/simpletest/testwalkthrough.php +++ b/question/type/ddmarker/simpletest/testwalkthrough.php @@ -17,8 +17,10 @@ /** * Unit tests for the drag-and-drop markers question type. * - * @package qtype_ddmarker - * @copyright 2010 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/question/type/ddmarker/version.php b/question/type/ddmarker/version.php index d62ee1c6466..8a7e2b24259 100644 --- a/question/type/ddmarker/version.php +++ b/question/type/ddmarker/version.php @@ -17,8 +17,10 @@ /** * Version information for the drag-and-drop markers question type. * - * @package qtype_ddmarker - * @copyright 2011 The Open University + * @package qtype + * @subpackage ddmarker + * @copyright 2012 The Open University + * @author Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ From 73f356a4ee1a0f67653794b1a6ad4de16430c776 Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 8 Apr 2012 18:16:38 +0700 Subject: [PATCH 25/28] MDL-47494 ddmarker: NOBUG converted question conversion code to use a renderer --- .../type/ddmarker/imagetargetconverter.php | 65 +++++--- .../type/ddmarker/lang/en/qtype_ddmarker.php | 12 +- question/type/ddmarker/questionlists.php | 156 ++++++++---------- question/type/ddmarker/renderer.php | 33 ++++ 4 files changed, 144 insertions(+), 122 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index f5a99a66fea..e1d89dce46a 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -27,11 +27,12 @@ require_once(dirname(__FILE__) . '/../../../config.php'); require_once($CFG->libdir . '/adminlib.php'); -require_once($CFG->dirroot.'/question/type/ddmarker/questionlists.php'); +require_once(dirname(__FILE__).'/questionlists.php'); +require_once(dirname(__FILE__).'/lib.php'); class qtype_ddmarker_question_converter_list extends qtype_ddmarker_question_list { - protected function new_list_item($record) { - return new qtype_ddmarker_question_converter_list_item($record, $this, $this->categorylist); + protected function new_list_item($stringidentifier, $link, $record) { + return new qtype_ddmarker_question_converter_list_item($stringidentifier, $link, $record, $this, $this->categorylist); } public function prepare_for_processing($top) { global $DB; @@ -51,9 +52,9 @@ class qtype_ddmarker_question_converter_list extends qtype_ddmarker_question_lis class qtype_ddmarker_question_converter_list_item extends qtype_ddmarker_question_list_item { public $imagetargetrecord = null; public $answers = array(); - public function process($progresstrace = null, $depth = 0) { + public function process($renderer) { qtype_ddmarker_convert_image_target_question($this->record, $this->imagetargetrecord->qimage, $this->answers); - parent::process($progresstrace, $depth);//outputs progress message + parent::process($renderer);//outputs progress message } } @@ -69,8 +70,9 @@ require_capability('moodle/question:config', $context); admin_externalpage_setup('qtypeddmarkerfromimagetarget'); // Header. -echo $OUTPUT->header(); -echo $OUTPUT->heading_with_help(get_string('imagetargetconverter', 'qtype_ddmarker'), '', 'qtype_ddmarker'); +$renderer = $PAGE->get_renderer('qtype_ddmarker', 'list'); +echo $renderer->header(); +echo $renderer->heading_with_help(get_string('imagetargetconverter', 'qtype_ddmarker'), '', 'qtype_ddmarker'); $params = array(); @@ -105,14 +107,24 @@ if (!count($questions)) { $contextids[] = $question->contextid; } - $contextlist = new qtype_ddmarker_context_list(array_unique($contextids)); - $categorylist = new qtype_ddmarker_category_list($contextids, $contextlist); - $questionlist = new qtype_ddmarker_question_converter_list($questions, $categorylist); + $questionsselected = (bool) ($categoryid || $qcontextid || $questionid); + if (!$confirm) { + if (!$questionsselected) { + $pagestate = 'listall'; + } else { + $pagestate = 'confirm'; + } + } else if (confirm_sesskey()) { + $pagestate = 'processing'; + } + $link = ($pagestate == 'listall'); + $contextlist = new qtype_ddmarker_context_list($pagestate, $link, array_unique($contextids)); + $categorylist = new qtype_ddmarker_category_list($pagestate, $link, $contextids, $contextlist); + $questionlist = new qtype_ddmarker_question_converter_list($pagestate, $link, $questions, $categorylist); foreach ($questions as $question) { $questionlist->leaf_node($question->id, 1); } - $questionsselected = (bool) ($categoryid || $qcontextid || $questionid); if ($questionid) { $top = $questionlist->get_instance($questionid); } else if ($categoryid) { @@ -122,22 +134,25 @@ if (!count($questions)) { } else { $top = $contextlist->root_node(); } - if (!$confirm) { - if ($questionsselected) { - echo $contextlist->render('listitemaction', false, $top); + switch ($pagestate) { + case 'listall' : + echo $renderer->render_qtype_ddmarker_list($top); + break; + case 'confirm' : + echo $renderer->render_qtype_ddmarker_list($top); $cofirmedurl = new moodle_url($PAGE->url, compact('categoryid', 'contextid', 'questionid') + array('confirm'=>1)); $cancelurl = new moodle_url($PAGE->url); - echo $OUTPUT->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); - } else { - echo $contextlist->render('listitemlist', true, $top); - } - } else if (confirm_sesskey()) { - require_once(dirname(__FILE__).'/lib.php'); - $questionlist->prepare_for_processing($top); - echo '
        '; - $top->process(); - echo '
      '; + echo $renderer->confirm(get_string('confirmimagetargetconversion', 'qtype_ddmarker'), $cofirmedurl, $cancelurl); + break; + case 'processing' : + $questionlist->prepare_for_processing($top); + echo '
        '; + $top->process($renderer); + echo '
      '; + break; + default : + break; } } // Footer. -echo $OUTPUT->footer(); +echo $renderer->footer(); diff --git a/question/type/ddmarker/lang/en/qtype_ddmarker.php b/question/type/ddmarker/lang/en/qtype_ddmarker.php index 30fb9b249e9..06615ba2224 100644 --- a/question/type/ddmarker/lang/en/qtype_ddmarker.php +++ b/question/type/ddmarker/lang/en/qtype_ddmarker.php @@ -58,12 +58,12 @@ $string['formerror_unrecognisedwidthheightpart'] = 'We do not recognise the widt $string['formerror_unrecognisedxypart'] = 'We do not recognise the x,y coordinates you have specified. Your coordinates for a {$a->shape} should be expressed as - {$a->coordsstring}.'; $string['imagetargetconverter'] = 'Convert image target questions to drag and drop marker'; $string['infinite'] = 'Infinite'; -$string['listitemactioncategory'] = 'About to convert all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemactioncontext'] = 'About to convert all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemactionquestion'] = 'About to convert question "{$a->name}"'; -$string['listitemlistcategory'] = 'Select all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemlistcontext'] = 'Select all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; -$string['listitemlistquestion'] = 'Select question "{$a->name}"'; +$string['listitemconfirmcategory'] = 'About to convert all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemconfirmcontext'] = 'About to convert all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemconfirmquestion'] = 'About to convert question "{$a->name}"'; +$string['listitemlistallcategory'] = 'Select all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemlistallcontext'] = 'Select all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; +$string['listitemlistallquestion'] = 'Select question "{$a->name}"'; $string['listitemprocessingcategory'] = 'Converting all imagetarget questions in category "{$a->name}" (contains {$a->qcount} imagetarget questions)'; $string['listitemprocessingcontext'] = 'Converting all imagetarget questions in context "{$a->name}" (contains {$a->qcount} imagetarget questions)'; $string['listitemprocessingquestion'] = 'Converted question "{$a->name}"'; diff --git a/question/type/ddmarker/questionlists.php b/question/type/ddmarker/questionlists.php index 9f8a0ba9f4d..df17ff52a7c 100644 --- a/question/type/ddmarker/questionlists.php +++ b/question/type/ddmarker/questionlists.php @@ -24,7 +24,8 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2012 Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -abstract class qtype_ddmarker_list_item { +abstract class qtype_ddmarker_list_item implements renderable { + /** * @var count of questions contained in this item and sub items. */ @@ -34,8 +35,20 @@ abstract class qtype_ddmarker_list_item { */ protected $children = array(); + protected $stringidentifier; + protected $link; protected $record; + protected $list; + protected $parentlist; + protected $listtype = null; + public function __construct($stringidentifier, $link, $record, $list, $parentlist = null) { + $this->stringidentifier = $stringidentifier; + $this->link = $link; + $this->record = $record; + $this->list = $list; + $this->parentlist = $parentlist; + } public function add_child($child) { $this->children[] = $child; @@ -46,12 +59,32 @@ abstract class qtype_ddmarker_list_item { abstract protected function parent_node (); - public function render($stringidentifier, $link) { - return $this->render_item($stringidentifier, $link).$this->render_children($stringidentifier, $link); + + public function item_name() { + return $this->record->name; } - abstract protected function render_item($stringidentifier, $link); - + public function id_param_name() { + return $this->listtype.'id'; + } + public function get_id() { + return $this->record->id; + } + public function get_q_count() { + return $this->qcount; + } + public function get_string_identifier() { + return $this->stringidentifier; + } + public function get_linked() { + return $this->link; + } + public function get_list_type() { + return $this->listtype; + } + public function get_children() { + return $this->children; + } public function leaf_to_root($qcount) { $this->qcount += $qcount; $parent = $this->parent_node(); @@ -61,18 +94,18 @@ abstract class qtype_ddmarker_list_item { } } - public function process() { + public function process($renderer) { echo '
    • '; - echo $this->render_item('listitemprocessing', false); - $this->process_children(); + echo $renderer->item($this); + $this->process_children($renderer); echo '
    • '; flush(); } - protected function process_children() { + protected function process_children($renderer) { echo '
        '; foreach ($this->children as $child) { - $child->process(); + $child->process($renderer); } echo '
      '; } @@ -89,13 +122,6 @@ abstract class qtype_ddmarker_list_item { return $ids; } - protected function render_children($stringidentifier, $link) { - $children = array(); - foreach ($this->children as $child) { - $children[] = $child->render($stringidentifier, $link); - } - return html_writer::alist($children); - } public function __toString() { return get_class($this).' '.$this->record->id; @@ -110,12 +136,7 @@ abstract class qtype_ddmarker_list_item { } class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { - - public function __construct($record, $list, $parentlist) { - $this->record = $record; - $this->list = $list; - $this->parentlist = $parentlist; - } + protected $listtype = 'category'; public function parent_node() { if ($this->record->parent == 0) { @@ -124,58 +145,20 @@ class qtype_ddmarker_category_list_item extends qtype_ddmarker_list_item { return $this->list->get_instance($this->record->parent); } } - - protected function render_item ($stringidentifier, $link) { - global $PAGE; - $a = new stdClass(); - $a->qcount = $this->qcount; - $a->name = $this->record->name; - $thisitem = get_string($stringidentifier.'category', 'qtype_ddmarker', $a); - if ($link) { - $actionurl = new moodle_url($PAGE->url, array('categoryid'=> $this->record->id)); - $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); - } - - return $thisitem; - } } class qtype_ddmarker_question_list_item extends qtype_ddmarker_list_item { - - public function __construct($record, $list, $parentlist) { - $this->record = $record; - $this->list = $list; - $this->parentlist = $parentlist; - } + protected $listtype = 'question'; public function parent_node() { return $this->parentlist->get_instance($this->record->category); } - protected function render_item ($stringidentifier, $link) { - global $PAGE; - $a = new stdClass(); - $a->name = $this->record->name; - $thisitem = get_string($stringidentifier.'question', 'qtype_ddmarker', $a); - if ($link) { - $actionurl = new moodle_url($PAGE->url, array('questionid'=> $this->record->id)); - $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); - } - return $thisitem; - } public function question_ids() { return array($this->record->id); } } class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { - - protected $list; - protected $parentlist = null; - - public function __construct($record, $list) { - $this->record = $record; - $this->list = $list; - } - + protected $listtype = 'context'; public function parent_node() { $pathids = explode('/', $this->record->path); if (count($pathids) >= 3) { @@ -185,17 +168,8 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { } } - protected function render_item ($stringidentifier, $link) { - global $PAGE; - $a = new stdClass(); - $a->qcount = $this->qcount; - $a->name = print_context_name($this->record); - $thisitem = get_string($stringidentifier.'context', 'qtype_ddmarker', $a); - if ($link) { - $actionurl = new moodle_url($PAGE->url, array('contextid'=> $this->record->id)); - $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); - } - return $thisitem; + public function item_name() { + return print_context_name($this->record); } public function course_context_id() { @@ -212,11 +186,11 @@ class qtype_ddmarker_context_list_item extends qtype_ddmarker_list_item { abstract class qtype_ddmarker_list { protected $records = array(); protected $instances = array(); - abstract protected function new_list_item($record); - protected function make_list_item_instances_from_records ($contextids = null) { + abstract protected function new_list_item($stringidentifier, $link, $record); + protected function make_list_item_instances_from_records($stringidentifier, $link) { if (!empty($this->records)) { foreach ($this->records as $id => $record) { - $this->instances[$id] = $this->new_list_item($record); + $this->instances[$id] = $this->new_list_item($stringidentifier, $link, $record); } } } @@ -233,11 +207,11 @@ abstract class qtype_ddmarker_list { class qtype_ddmarker_context_list extends qtype_ddmarker_list { - protected function new_list_item($record) { - return new qtype_ddmarker_context_list_item($record, $this); + protected function new_list_item($stringidentifier, $link, $record) { + return new qtype_ddmarker_context_list_item($stringidentifier, $link, $record, $this); } - public function __construct($contextids) { + public function __construct($stringidentifier, $link, $contextids) { global $DB; $this->records = array(); foreach ($contextids as $contextid) { @@ -252,13 +226,13 @@ class qtype_ddmarker_context_list extends qtype_ddmarker_list { } } } - parent::make_list_item_instances_from_records ($contextids); + $this->make_list_item_instances_from_records($stringidentifier, $link); } - public function render($stringidentifier, $link, $roottorender = null) { + public function render($roottorender = null) { if ($roottorender === null) { $roottorender = $this->root_node(); } - $rootitem = html_writer::tag('li', $roottorender->render($stringidentifier, $link)); + $rootitem = html_writer::tag('li', $roottorender->render()); return html_writer::tag('ul', $rootitem); } public function root_node () { @@ -270,29 +244,29 @@ class qtype_ddmarker_context_list extends qtype_ddmarker_list { class qtype_ddmarker_category_list extends qtype_ddmarker_list { protected $contextlist; - protected function new_list_item($record) { - return new qtype_ddmarker_category_list_item($record, $this, $this->contextlist); + protected function new_list_item($stringidentifier, $link, $record) { + return new qtype_ddmarker_category_list_item($stringidentifier, $link, $record, $this, $this->contextlist); } - public function __construct($contextids, $contextlist) { + public function __construct($stringidentifier, $link, $contextids, $contextlist) { global $DB; $this->contextlist = $contextlist; //probably most efficient way to reconstruct question category tree is to load all q cats in relevant contexts list($sql, $params) = $DB->get_in_or_equal($contextids); $this->records = $DB->get_records_select('question_categories', "contextid ".$sql, $params); - parent::make_list_item_instances_from_records ($contextids); + $this->make_list_item_instances_from_records($stringidentifier, $link); } } class qtype_ddmarker_question_list extends qtype_ddmarker_list { protected $categorylist; - protected function new_list_item($record) { - return new qtype_ddmarker_question_list_item($record, $this, $this->categorylist); + protected function new_list_item($stringidentifier, $link, $record) { + return new qtype_ddmarker_question_list_item($stringidentifier, $link, $record, $this, $this->categorylist); } - public function __construct($questions, $categorylist) { + public function __construct($stringidentifier, $link, $questions, $categorylist) { global $DB; $this->categorylist = $categorylist; $this->records = $questions; - parent::make_list_item_instances_from_records (); + $this->make_list_item_instances_from_records($stringidentifier, $link); } public function prepare_for_processing($top) { } diff --git a/question/type/ddmarker/renderer.php b/question/type/ddmarker/renderer.php index ef1285dd1f9..48952905e49 100644 --- a/question/type/ddmarker/renderer.php +++ b/question/type/ddmarker/renderer.php @@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die(); +require_once($CFG->dirroot . '/question/type/rendererbase.php'); require_once($CFG->dirroot . '/question/type/ddimageortext/rendererbase.php'); @@ -158,4 +159,36 @@ class qtype_ddmarker_renderer extends qtype_ddtoimage_renderer_base { $output .= parent::hint($qa, $hint); return $output; } + } +class qtype_ddmarker_list_renderer extends plugin_renderer_base { + + public function render_qtype_ddmarker_list(qtype_ddmarker_list_item $top) { + $list = html_writer::tag('ul', html_writer::tag('li', $this->render_qtype_ddmarker_list_item($top))); + return $this->output->container($list, 'listofquestions'); + } + public function render_qtype_ddmarker_list_item(qtype_ddmarker_list_item $listitem) { + return $this->item($listitem).$this->children($listitem); + } + + public function item(qtype_ddmarker_list_item $item) { + global $PAGE; + $a = new stdClass(); + $a->qcount = $item->get_q_count(); + $a->name = $item->item_name(); + $thisitem = get_string('listitem'.$item->get_string_identifier().$item->get_list_type(), 'qtype_ddmarker', $a); + if ($item->get_linked()) { + $actionurl = new moodle_url($PAGE->url, array($item->id_param_name() => $item->get_id())); + $thisitem = html_writer::tag('a', $thisitem, array('href' => $actionurl)); + } + return $thisitem; + } + + protected function children(qtype_ddmarker_list_item $item) { + $children = array(); + foreach ($item->get_children() as $child) { + $children[] = $this->render_qtype_ddmarker_list_item($child); + } + return html_writer::alist($children); + } +} \ No newline at end of file From ac4abff022a66ac2a2f8f4d36e219d487e60ffdf Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Sun, 8 Apr 2012 19:28:06 +0700 Subject: [PATCH 26/28] MDL-47494 ddmarker: NOBUG couple of small fixes --- question/type/ddmarker/imagetargetconverter.php | 2 +- question/type/ddmarker/settings.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/question/type/ddmarker/imagetargetconverter.php b/question/type/ddmarker/imagetargetconverter.php index e1d89dce46a..1ab0f542c35 100644 --- a/question/type/ddmarker/imagetargetconverter.php +++ b/question/type/ddmarker/imagetargetconverter.php @@ -72,7 +72,7 @@ admin_externalpage_setup('qtypeddmarkerfromimagetarget'); // Header. $renderer = $PAGE->get_renderer('qtype_ddmarker', 'list'); echo $renderer->header(); -echo $renderer->heading_with_help(get_string('imagetargetconverter', 'qtype_ddmarker'), '', 'qtype_ddmarker'); +echo $renderer->heading(get_string('imagetargetconverter', 'qtype_ddmarker'), 2); $params = array(); diff --git a/question/type/ddmarker/settings.php b/question/type/ddmarker/settings.php index e79d78ef513..2dd2cc81d6e 100644 --- a/question/type/ddmarker/settings.php +++ b/question/type/ddmarker/settings.php @@ -15,7 +15,6 @@ // along with Moodle. If not, see . /** - * Admin settings for the Opaque question type. * * @package qtype * @subpackage ddmarker From aee03a6b74a095f5b2cc0c19ca9f52ac1a75ba3e Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 10 Apr 2012 20:13:10 +0700 Subject: [PATCH 27/28] MDL-47494 ddmarker: NOBUG added instructions to README about converting imagetarget qs and renamed README.txt to README.md --- question/type/ddmarker/README.md | 131 ++++++++++++++++++++++++++++++ question/type/ddmarker/README.txt | 31 ------- 2 files changed, 131 insertions(+), 31 deletions(-) create mode 100644 question/type/ddmarker/README.md delete mode 100644 question/type/ddmarker/README.txt diff --git a/question/type/ddmarker/README.md b/question/type/ddmarker/README.md new file mode 100644 index 00000000000..29cddfa6509 --- /dev/null +++ b/question/type/ddmarker/README.md @@ -0,0 +1,131 @@ +Drag-and-drop markers question type +----------------------------------- + +You can use markers with text labels as drag items onto rectangular, and in +Moodle 2.2+ version circular and polygon defined drop zones on a background image. + +This question type requires that gapselect question type +https://github.com/moodleou/moodle-qtype_ddimageortext/ and +https://github.com/moodleou/moodle-qtype_gapselect/ +to be installed in order to work. + +This question type was written by Jamie Pratt (http://jamiep.org/). + +This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or +2.2+ (master branch). + +###Installation + +####Installation Using Git + +To install using git for a 2.2+ Moodle installation, type this command in the +root of your Moodle install: + +git clone git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker + +To install using git for a 2.1+ Moodle installation, type this command in the +root of your Moodle install: + +git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker + +Then add question/type/ddmarker to your git ignore. + +####Installation From Downloaded zip file + +Alternatively, download the zip from : + +* Moodle 2.2+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/master +* Moodle 2.1+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/MOODLE_21_STABLE + +unzip it into the question/type folder, and then rename the new folder to ddmarker. + +###Converting 'image target' type questions to this type + +The imagetarget question type question type will not be upgraded to use with Moodle beyond version 1.9 it seems. + +But you can convert your existing image target questions and question attempt data to be drag and drop marker questions and they +will work as the image target previously worked. + +There are two ways to convert your imagetarget questions to ddmarker question types. + +####Automatic Conversion (recommended) + +Conversion will happen automatically when you upgrade for Moodle 2.0. + +It is recommended you follow the following steps : + +Upgrade your site to Moodle 2.0. This involves : + +* Upgrade the code base to Moodle 2.0 +* Remove the imagetarget question type code from question/type/imagetarget/ +* Go to your http://{moodleroot}/admin/ to trigger the upgrade of the db + +At this point your imagetarget questions won't work and will show up as 'missing type' but once that upgrade is +done change your Moodle code to Moodle 2.2+ + +* install the ddmarker question type code in question type ddmarker. +* then go to your http://{moodleroot}/admin/ to trigger the upgrade of the db + +This will convert all your imagetarget questions to ddmarker automatically. + +####Manual Conversion + +You can also use a manual script to convert imagetarget questions to ddmarker after upgrading to Moodle 2.1 or greater. + +* Log in as admin. +* You will find a script in the admin menu under plugins/question types/ to convert your imagetarget questions to ddmarker. +(This just converts your questions themselves.) +* In order to convert your question attempt data to be used with the ddmarker question type and Moodle 2.1 or greater you need to +find the 'question engine upgrade helper' which will appear at the root of the admin menu. Use this script to : +* _Reset the upgrade of all attempt data._ +* _Run the attempt data upgrade again._ + +###Issues with converting image target question type questions + +####Background image shrinkage + +The ddmarker question type will shrink the background image of your questions to be within a maximum size and width while at the +time preserving aspect ratio of the image. The default max width is 600 pixels and height 400 pixels. + +The ddmarker question type does this whenever you edit a question and save it again. + +Unfortunately when you open up a question to edit it this means that if the image is to big it will be shrunk but at present the +position of your drop zones are not moved to compensate for this shrinkage. There won't be a problem until you try to edit and save +a question but when you open it in the editor the drop zones will not be in the correct position. If you save the question they +they will then be saved in the wrong position. + +####Work around for background image shrinkage + +Either : + +* do not edit questions which have sizes above the allowed max. +* or you can change the allowed maximum size of images there are two constant at the top of question/type/ddmarker/questiontype.php +that define the size limits. + +The limit is just there to shrink outrageously large images down to a reasonable size automatically. You could set the value of the +constants defining the max size to a very large value to effectively disable the image size constraints all together. + +####Lack of drag label in imagetarget questions + +Normally each draggable marker in the ddmarker question type has a text label. There are no labels for the imagetarget markers +though, I needed to pick something that will work in any language as the label for the single imagetarget draggable marker +so I picked 'X'. + +####Work around for lack of drag label in imagetarget questions + +Your teachers can edit this label after the question has been created. And they might also like to take advantage of the ability in +the ddmarker question type to be able to specify the correct drop zones for more than one drag marker onto the same image, +giving each drag marker a different label. + +You can change the default drag marker label which you can find defined in a constant at the top of question/type/ddmarker/lib.php + +####No automatic feedback telling the user whether they got the question right, partially right or wrong. + +In the imagetarget question you get a text message telling the user whether they got the question correct, partially correct or +wrong. In many of the new question types in Moodle 2.1 onwards the teacher is expected to enter the message that the user will +see in the question definition. This is called 'combined feedback' and by default it is blank. So questions that have been +converted from per 2.1 Moodle, from imagetarget question types that used to give some feedback to the user will no longer do so. + +####Work around for lack of automatic feedback telling the user whether they got the question right, partially right or wrong. + +You can use this plug in https://github.com/jamiepratt/moodle-admin_tool_questionaddfeedback to bulk add feedback to questions. diff --git a/question/type/ddmarker/README.txt b/question/type/ddmarker/README.txt deleted file mode 100644 index f096c4f1606..00000000000 --- a/question/type/ddmarker/README.txt +++ /dev/null @@ -1,31 +0,0 @@ -Drag-and-drop markers question type - -You can use markers with text labels as drag items onto rectangular, and in -Moodle 2.2+ version circular and polygon defined drop zones on a background image. - -This question type requires that gapselect question type -https://github.com/moodleou/moodle-qtype_ddimageortext/ and -https://github.com/moodleou/moodle-qtype_gapselect/ -to be installed in order to work. - -This question type was written by Jamie Pratt (http://jamiep.org/). - -This question type is compatible with Moodle 2.1+ (MOODLE_21_STABLE branch) or -2.2+ (master branch). - -To install using git for a 2.2+ Moodle installation, type this command in the -root of your Moodle install: - -git clone git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker - -To install using git for a 2.1+ Moodle installation, type this command in the -root of your Moodle install: - -git clone -b MOODLE_21_STABLE git://github.com/moodleou/moodle-qtype_ddmarker.git question/type/ddmarker - -Then add question/type/ddmarker to your git ignore. - -Alternatively, download the zip from - Moodle 2.2+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/master - Moodle 2.1+ - https://github.com/moodleou/moodle-qtype_ddmarker/zipball/MOODLE_21_STABLE -unzip it into the question/type folder, and then rename the new folder to ddmarker. From d7423110fde2df6e9c74e52d92369a49c07ce13a Mon Sep 17 00:00:00 2001 From: Jamie Pratt Date: Tue, 19 Jun 2012 19:14:08 +0700 Subject: [PATCH 28/28] MDL-47494 ddmarker: NOBUG fixing sql for mysql. Thanks to Alain Roussel. removed usage of 'drop' keyword as table alias --- question/type/ddmarker/db/install.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/question/type/ddmarker/db/install.php b/question/type/ddmarker/db/install.php index 45d415c6502..7d46131f560 100644 --- a/question/type/ddmarker/db/install.php +++ b/question/type/ddmarker/db/install.php @@ -46,7 +46,7 @@ function xmldb_qtype_ddmarker_install() { $dragssql = 'SELECT drag.* '.$from.', {qtype_ddmarker_drags} drag'.$where.' AND drag.questionid = q.id'; $drags = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dragssql)); - $dropssql = 'SELECT drop.* '.$from.', {qtype_ddmarker_drops} drop'.$where.' AND drop.questionid = q.id'; + $dropssql = 'SELECT drp.* '.$from.', {qtype_ddmarker_drops} drp'.$where.' AND drp.questionid = q.id'; $drops = xmldb_qtype_ddmarker_index_array_of_records_by_key('questionid', $DB->get_records_sql($dropssql)); $answerssql = 'SELECT answer.* '.$from.', {question_answers} answer'.$where.' AND answer.question = q.id';