Index: lib/listlib.php
===================================================================
RCS file: /cvsroot/moodle/moodle/lib/listlib.php,v
retrieving revision 1.14.2.1
diff -u -r1.14.2.1 listlib.php
--- lib/listlib.php 27 Nov 2008 10:53:40 -0000 1.14.2.1
+++ lib/listlib.php 20 Mar 2010 16:14:13 -0000
@@ -74,10 +74,21 @@
var $editable;
/**
- * Key is child id, value is parent.
- * @var array
+ * Cache of all items contained in list
+ * Presents only in top-level list
+ * @var array that contains from:
+ * [id]['sortorder'] => sortorder
+ * [id]['parent'] => parentid
+ * [id]['item'] => reference to item object
*/
- var $childparent;
+ var $itemscache = null;
+
+ /**
+ * Used to get $itemscache
+ * @var reference to top-level list
+ */
+ var $toplevellist = null;
+
//------------------------------------------------------
//vars used for pagination.
@@ -101,9 +112,10 @@
* @param integer $page if 0 no pagination. (These three params only used in top level list.)
* @param string $pageparamname name of url param that is used for passing page no
* @param integer $itemsperpage no of top level items.
+ * @param reference to the top-level list that contained $itemscache
* @return moodle_list
*/
- function moodle_list($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20) {
+ function moodle_list($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $toplevellist=null) {
$this->editable = $editable;
$this->attributes = $attributes;
$this->type = $type;
@@ -116,6 +128,51 @@
} else {
$this->pageurl = $pageurl;
}
+
+ if ($toplevellist==null) {
+ $this->toplevellist = $this;
+ $this->toplevellist->itemscache = array();
+ } else {
+ $this->toplevellist = $toplevellist;
+ }
+ }
+
+ /**
+ * Change move state
+ * @param ineger $mode id of item to move or 0 to stop moving
+ */
+ function set_moving_item($mode) {
+ global $USER;
+ $paramname = get_class($this).'moving';
+ if ($mode>0) {
+ $USER->$paramname = $mode;
+ } else {
+ unset($USER->$paramname);
+ }
+ }
+
+ /**
+ * Returns id of item to move
+ * @return integer id of item to move or 0
+ */
+ function get_moving_item() {
+ global $USER;
+ if ($this->is_moving_active()) {
+ $paramname = get_class($this).'moving';
+ return $USER->$paramname;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns state of list: moving or not
+ * @return bool state
+ */
+ function is_moving_active() {
+ global $USER;
+ $paramname = get_class($this).'moving';
+ return isset($USER->$paramname);
}
/**
@@ -124,6 +181,7 @@
* @param integer $indent depth of indentation.
*/
function to_html($indent=0, $extraargs=array()) {
+ global $CFG;
if (count($this->items)) {
$tabs = str_repeat("\t", $indent);
$first = true;
@@ -132,15 +190,39 @@
$html = '';
foreach ($this->items as $item) {
+ // ignoring item which ig going to be moved
+ if ($this->get_moving_item() == $item->id) continue;
+
$last = (count($this->items) == $itemiter);
if ($this->editable) {
$item->set_icon_html($first, $last, $lastitem);
}
+
+ // inserting "movebefore" action in the beginnig of the top-level list
+ if ($this->is_moving_active() && $first && !isset($this->parentitem)) {
+ $action = array('actionname'=>'movebefore','actionargs'=>$item->id);
+ $html .= "
attributes))?(' '.$item->attributes):'').">";
+ $html .= "";
+ $html .= "
";
+ $html .= "\n";
+ }
+
+ // generating HTML-code of an item
if ($itemhtml = $item->to_html($indent+1, $extraargs)) {
$html .= "$tabs\tattributes))?(' '.$item->attributes):'').">";
$html .= $itemhtml;
$html .= "\n";
}
+
+ // inserting "moveafter" action after every list item
+ if ($this->is_moving_active()) {
+ $action = array('actionname'=>'moveafter','actionargs'=>$item->id);
+ $html .= "attributes))?(' '.$item->attributes):'').">";
+ $html .= "";
+ $html .= "
";
+ $html .= "\n";
+ }
+
$first = false;
$lastitem = $item;
$itemiter++;
@@ -217,14 +299,15 @@
$this->lastitem = $this->firstitem + $this->itemsperpage - 1;
}
$itemiter = $offset;
- //make a simple array which is easier to search
- $this->childparent = array();
foreach ($records as $record) {
- $this->childparent[$record->id] = $record->parent;
+ // Caching items to prevent a lot of database queries in future
+ $this->toplevellist->itemscache[$record->id] = array();
+ $this->toplevellist->itemscache[$record->id]['sortorder'] = $record->sortorder;
+ $this->toplevellist->itemscache[$record->id]['parent'] = $record->parent;
}
//create top level list items and they're responsible for creating their children
foreach ($records as $record) {
- if (!array_key_exists($record->parent, $this->childparent)) {
+ if (!array_key_exists($record->parent, $this->toplevellist->itemscache)) {
//if this record is not a child of another record then
$inpage = ($itemiter >= $this->firstitem && $itemiter <= $this->lastitem);
@@ -234,11 +317,10 @@
$newattributes = $this->parentitem->attributes;
} else {
$newattributes = '';
-
}
$this->items[$itemiter] =& new $this->listitemclassname($record, $this, $newattributes, $inpage);
if ($inpage) {
- $this->items[$itemiter]->create_children($records, $this->childparent, $record->id);
+ $this->items[$itemiter]->create_children($records, $this->toplevellist->itemscache, $record->id);
} else {
//don't recurse down the tree for items that are not on this page
$this->paged = true;
@@ -278,10 +360,10 @@
}
return $html;
}
-
/**
* Returns an array of ids of peers of an item.
*
+ * @deprecated should be deleted with process_actions
* @param int itemid - if given, restrict records to those with this parent id.
* @return array peer ids
*/
@@ -307,6 +389,7 @@
/**
* Move a record up or down
*
+ * @deprecated should be deleted with process_actions
* @param string $direction up / down
* @param integer $id
*/
@@ -337,6 +420,9 @@
$this->reorder_peers($peers);
}
+ /**
+ * @deprecated should be deleted with process_actions
+ */
function reorder_peers($peers) {
foreach ($peers as $key => $peer) {
if (!set_field("{$this->table}", "sortorder", $key, "id", $peer)) {
@@ -346,6 +432,7 @@
}
/**
+ * @deprecated should be deleted with process_actions
* @param integer $id an item index.
* @return object the item that used to be the parent of the item moved.
*/
@@ -374,6 +461,7 @@
/**
* Make item with id $id the child of the peer that is just above it in the sort order.
*
+ * @deprecated should be deleted with process_actions
* @param integer $id
*/
function move_item_right($id) {
@@ -405,6 +493,7 @@
* @param integer $moveup id of item to move up
* @param integer $movedown id of item to move down
* @return unknown
+ * @deprecated use process_action instead
*/
function process_actions($left, $right, $moveup, $movedown) {
//should this action be processed by this list object?
@@ -447,6 +536,90 @@
}
/**
+ * Process any action
+ * @param string $action name of action. Can be: startmove, cancelmove,
+ * movebefore, moveafter, movefirstchild
+ * @param integer $value id of item
+ */
+ function process_action($action,$value) {
+ global $CFG;
+
+ if ($action=='movebefore' || $action=='moveafter' || $action=='movefirstchild') {
+ $itemtomove = $this->toplevellist->itemscache[$this->get_moving_item()];
+ $itemtomove['id'] = $this->get_moving_item();
+ $anchor = $this->toplevellist->itemscache[$value];
+ $anchor['id'] = $value;
+ }
+
+ switch ($action){
+ case 'startmove': // pushed "Move" button
+ $this->set_moving_item($value);
+ break;
+ case 'cancelmove': // pushed "Cancel" button
+ $this->set_moving_item(0);
+ break;
+ case 'movebefore': // use this to move in the beginning of the group
+ $extendsortorders = "UPDATE ".$CFG->prefix.$this->table."
+ SET sortorder = sortorder + 1
+ WHERE parent = ".$anchor['parent'];
+ $move = "UPDATE ".$CFG->prefix.$this->table."
+ SET
+ parent = ".$anchor['parent'].",
+ sortorder = 0
+ WHERE id = ".$itemtomove['id'];
+ $reducesortorders = "UPDATE ".$CFG->prefix.$this->table."
+ SET sortorder = sortorder - 1
+ WHERE parent = ".$itemtomove['parent'].
+ " AND sortorder > ".$itemtomove['sortorder'];
+ execute_sql($extendsortorders,false);
+ execute_sql($move,false);
+ execute_sql($reducesortorders,false);
+ $this->set_moving_item(0);
+ break;
+ case 'moveafter': // move item after selected item
+ $extendsortorders = "UPDATE ".$CFG->prefix.$this->table."
+ SET sortorder = sortorder + 1
+ WHERE parent = ".$anchor['parent']." AND sortorder >".$anchor['sortorder'];
+ $move = "UPDATE ".$CFG->prefix.$this->table."
+ SET
+ parent = ".$anchor['parent'].",
+ sortorder = ".$anchor['sortorder']." + 1
+ WHERE id = ".$itemtomove['id'];
+ $reducesortorders = "UPDATE ".$CFG->prefix.$this->table."
+ SET sortorder = sortorder - 1
+ WHERE parent = ".$itemtomove['parent'].
+ " AND sortorder > ".$itemtomove['sortorder'];
+ execute_sql($extendsortorders,false);
+ execute_sql($move,false);
+ execute_sql($reducesortorders,false);
+ $this->set_moving_item(0);
+ break;
+ case 'movefirstchild': // insert list item as subitem
+ $extendsortorders = "UPDATE ".$CFG->prefix.$this->table."
+ SET sortorder = sortorder + 1
+ WHERE parent = ".$anchor['id'];
+ $move = "UPDATE ".$CFG->prefix.$this->table."
+ SET
+ parent = ".$anchor['id'].",
+ sortorder = 0
+ WHERE id = ".$itemtomove['id'];
+ $reducesortorders = "UPDATE ".$CFG->prefix.$this->table."
+ SET sortorder = sortorder - 1
+ WHERE parent = ".$itemtomove['parent'].
+ " AND sortorder > ".$itemtomove['sortorder'];
+ execute_sql($extendsortorders,false);
+ execute_sql($move,false);
+ execute_sql($reducesortorders,false);
+ $this->set_moving_item(0);
+ break;
+ default:
+ return false;
+ }
+
+ redirect($this->pageurl->out());
+ }
+
+ /**
* @param integer $itemid an item id.
* @return boolean Is the item with the given id the first top-level item on
* the current page?
@@ -544,55 +717,42 @@
* @return string html
*/
function to_html($indent=0, $extraargs = array()) {
+ global $CFG;
if (!$this->display) {
return '';
}
$tabs = str_repeat("\t", $indent);
+ // inserting "movefirstchild" action in the beginning of every list
+ if ($this->parentlist->is_moving_active()) {
+ $action = array('actionname'=>'movefirstchild','actionargs'=>$this->id);
+ $childrenhtml .= "\n";
+ }
if (isset($this->children)) {
- $childrenhtml = $this->children->to_html($indent+1, $extraargs);
+ $childrenhtml .= $this->children->to_html($indent+1, $extraargs);
} else {
- $childrenhtml = '';
+ $childrenhtml .= '';
}
return $this->item_html($extraargs).' '.(join($this->icons, '')).(($childrenhtml !='')?("\n".$childrenhtml):'');
}
function set_icon_html($first, $last, &$lastitem) {
global $CFG;
- $strmoveup = get_string('moveup');
- $strmovedown = get_string('movedown');
- $strmoveleft = get_string('maketoplevelitem', 'question');
+ $strmove = get_string('move');
$pixpath = $CFG->pixpath;
- if (isset($this->parentlist->parentitem)) {
- $parentitem =& $this->parentlist->parentitem;
- if (isset($parentitem->parentlist->parentitem)) {
- $action = get_string('makechildof', 'question', $parentitem->parentlist->parentitem->name);
+ if (!$this->parentlist->is_moving_active()) {
+ // "Move"-icon must be drawn in all list-items except alone item in list
+ if (!isset($this->parentlist->parentitem)) {
+ if (count($this->parentlist->items)>1) {
+ $this->icons['move'] = $this->image_icon($strmove, $this->parentlist->pageurl->out_action(array('actionname'=>'startmove','actionargs'=>$this->id)), 'move');
+ }
} else {
- $action = $strmoveleft;
+ $this->icons['move'] = $this->image_icon($strmove, $this->parentlist->pageurl->out_action(array('actionname'=>'startmove','actionargs'=>$this->id)), 'move');
}
- $this->icons['left'] = $this->image_icon($action, $this->parentlist->pageurl->out_action(array('left'=>$this->id)), 'left');
- } else {
- $this->icons['left'] = $this->image_spacer();
- }
-
- if (!$first) {
- $this->icons['up'] = $this->image_icon($strmoveup, $this->parentlist->pageurl->out_action(array('moveup'=>$this->id)), 'up');
- } else {
- $this->icons['up'] = $this->image_spacer();
- }
-
- if (!$last) {
- $this->icons['down'] = $this->image_icon($strmovedown, $this->parentlist->pageurl->out_action(array('movedown'=>$this->id)), 'down');
- } else {
- $this->icons['down'] = $this->image_spacer();
- }
-
- if (!empty($lastitem)) {
- $makechildof = get_string('makechildof', 'question', $lastitem->name);
- $this->icons['right'] = $this->image_icon($makechildof, $this->parentlist->pageurl->out_action(array('right'=>$this->id)), 'right');
- } else {
- $this->icons['right'] = $this->image_spacer();
}
}
@@ -617,8 +777,13 @@
* @param integer $thisrecordid
*/
function create_children(&$records, &$children, $thisrecordid) {
- //keys where value is $thisrecordid
- $thischildren = array_keys($children, $thisrecordid);
+ //keys where parent is $thisrecordid
+ $children[$thisrecordid]['item'] = $this;
+ $thischildren = array();
+ foreach($children as $id => $item) {
+ if ($item['parent']==$thisrecordid)
+ $thischildren[]=$id;
+ }
if (count($thischildren)) {
foreach ($thischildren as $child) {
$thisclass = get_class($this);
Index: question/category.php
===================================================================
RCS file: /cvsroot/moodle/moodle/question/category.php,v
retrieving revision 1.24.2.5
diff -u -r1.24.2.5 category.php
--- question/category.php 2 Nov 2009 17:15:19 -0000 1.24.2.5
+++ question/category.php 20 Mar 2010 16:52:29 -0000
@@ -7,45 +7,28 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package questionbank
*/
-
require_once("../config.php");
require_once($CFG->dirroot."/question/editlib.php");
require_once($CFG->dirroot."/question/category_class.php");
-
list($thispageurl, $contexts, $cmid, $cm, $module, $pagevars) = question_edit_setup('categories');
// get values from form for actions on this page
$param = new stdClass();
- $param->moveup = optional_param('moveup', 0, PARAM_INT);
- $param->movedown = optional_param('movedown', 0, PARAM_INT);
- $param->moveupcontext = optional_param('moveupcontext', 0, PARAM_INT);
- $param->movedowncontext = optional_param('movedowncontext', 0, PARAM_INT);
- $param->tocontext = optional_param('tocontext', 0, PARAM_INT);
- $param->left = optional_param('left', 0, PARAM_INT);
- $param->right = optional_param('right', 0, PARAM_INT);
$param->delete = optional_param('delete', 0, PARAM_INT);
$param->confirm = optional_param('confirm', 0, PARAM_INT);
- $param->cancel = optional_param('cancel', '', PARAM_ALPHA);
- $param->move = optional_param('move', 0, PARAM_INT);
- $param->moveto = optional_param('moveto', 0, PARAM_INT);
+ $param->actionname = optional_param('actionname', 'noaction', PARAM_ALPHA);
+ $param->actionargs = optional_param('actionargs', 0, PARAM_INT);
$param->edit = optional_param('edit', 0, PARAM_INT);
-
$qcobject = new question_category_object($pagevars['cpage'], $thispageurl, $contexts->having_one_edit_tab_cap('categories'), $param->edit, $pagevars['cat'], $param->delete,
$contexts->having_cap('moodle/question:add'));
-
$streditingcategories = get_string('editcategories', 'quiz');
- if ($param->left || $param->right || $param->moveup || $param->movedown|| $param->moveupcontext || $param->movedowncontext){
- require_sesskey();
- foreach ($qcobject->editlists as $list){
- //processing of these actions is handled in the method where appropriate and page redirects.
- $list->process_actions($param->left, $param->right, $param->moveup, $param->movedown,
- $param->moveupcontext, $param->movedowncontext, $param->tocontext);
- }
- }
+
+ $qcobject->process_action($param->actionname, $param->actionargs);
+
if ($param->delete && ($questionstomove = count_records("question", "category", $param->delete))){
if (!$category = get_record("question_categories", "id", $param->delete)) { // security
error("No such category {$param->delete}!", $thispageurl->out());
Index: question/category_class.php
===================================================================
RCS file: /cvsroot/moodle/moodle/question/category_class.php,v
retrieving revision 1.32.2.10
diff -u -r1.32.2.10 category_class.php
--- question/category_class.php 19 Nov 2009 17:46:17 -0000 1.32.2.10
+++ question/category_class.php 28 Mar 2010 14:53:20 -0000
@@ -28,14 +28,43 @@
var $context = null;
- function question_category_list($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $context = null){
- parent::moodle_list('ul', '', $editable, $pageurl, $page, 'cpage', $itemsperpage);
+ function question_category_list($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $context = null, $toplevellist=null){
+ parent::moodle_list('ul', '', $editable, $pageurl, $page, 'cpage', $itemsperpage, $toplevellist);
$this->context = $context;
}
+ function list_from_records($paged = false, $offset = 0) {
+ $result = parent::list_from_records($paged, $offset);
+ foreach ($this->records as $record) {
+ // context will used for moving items between contexts
+ $this->toplevellist->itemscache[$record->id]['context'] = $this->context->id;
+ }
+ return $result;
+ }
+
function get_records() {
$this->records = get_categories_for_contexts($this->context->id, $this->sortby);
}
+
+ /**
+ * Returns array that contains id's of all element which ares childs of this list
+ * @return array which contains id's if all child elements
+ */
+ function get_child_ids_recursive() {
+ $childs = array();
+ if (isset($this->items)) {
+ foreach ($this->items as $child) {
+ $childs[] = $child->id;
+ $recurs = $child->children->get_child_ids_recursive();
+ $childs = array_merge($childs,$recurs);
+ }
+ }
+ return $childs;
+ }
+
+ /**
+ * @deprecated use process_action instead
+ */
function process_actions($left, $right, $moveup, $movedown, $moveupcontext, $movedowncontext, $tocontext){
global $CFG;
//parent::procces_actions redirects after any action
@@ -54,27 +83,44 @@
$this->pageurl->get_query_string(compact('cattomove', 'totop', 'toparent')));
}
}
+
+ function process_action($action, $value) {
+ if (($action=='movefirstchild' || $action=='moveafter' || $action=='movebefore')
+ // Changing context if item to move and anchor item are in defferent contexts
+ && $this->toplevellist->itemscache[$this->get_moving_item()]['context']!=$this->toplevellist->itemscache[$value]['context']) {
+ global $CFG;
+ $itemstorecontext = $this->toplevellist->itemscache[$this->get_moving_item()]['item']->children->get_child_ids_recursive();
+ $itemstorecontext[] = $this->get_moving_item();
+
+ $changecontext = 'UPDATE '.$CFG->prefix.$this->table.'
+ SET contextid = '.$this->toplevellist->itemscache[$value]['context'].'
+ WHERE id IN ('.implode(',',$itemstorecontext).')';
+ execute_sql($changecontext,false);
+ }
+
+ // parent::process_action redirects after any action
+ parent::process_action($action, $value);
+ }
}
+
class question_category_list_item extends list_item {
+ function question_category_list_item($item, &$parent, $attributes='', $display = true) {
+ parent::list_item($item, $parent, $attributes, $display);
+ }
function set_icon_html($first, $last, &$lastitem){
global $CFG;
- $category = $this->item;
- $this->icons['edit']= $this->image_icon(get_string('editthiscategory', 'question'),
- "{$CFG->wwwroot}/question/category.php?".$this->parentlist->pageurl->get_query_string(array('edit'=>$category->id)), 'edit');
- parent::set_icon_html($first, $last, $lastitem);
- $toplevel = ($this->parentlist->parentitem === null);//this is a top level item
- if (($this->parentlist->nextlist !== null) && $last && $toplevel && (count($this->parentlist->items)>1)){
- $this->icons['down'] = $this->image_icon(get_string('shareincontext', 'question', print_context_name($this->parentlist->nextlist->context)),
- $this->parentlist->pageurl->out_action(array('movedowncontext'=>$this->id, 'tocontext'=>$this->parentlist->nextlist->context->id)), 'down');
- }
- if (($this->parentlist->lastlist !== null) && $first && $toplevel && (count($this->parentlist->items)>1)){
- $this->icons['up'] = $this->image_icon(get_string('shareincontext', 'question', print_context_name($this->parentlist->lastlist->context)),
- $this->parentlist->pageurl->out_action(array('moveupcontext'=>$this->id, 'tocontext'=>$this->parentlist->lastlist->context->id)), 'up');
+
+ if (!$this->parentlist->is_moving_active()) {
+ $category = $this->item;
+ $this->icons['edit']= $this->image_icon(get_string('editthiscategory'),
+ "{$CFG->wwwroot}/question/category.php?".$this->parentlist->pageurl->get_query_string(array('edit'=>$category->id)), 'edit');
}
+ parent::set_icon_html($first, $last, $lastitem);
}
+
function item_html($extraargs = array()){
global $CFG;
$pixpath = $CFG->pixpath;
@@ -91,14 +137,14 @@
$item .= ' '. $category->info;
- if (count($this->parentlist->records)!=1){ // don't allow delete if this is the last category in this context.
+ // don't allow delete if there is only 1 category in this context.
+ if (count($this->parentlist->records)!=1 && !$this->parentlist->is_moving_active()){
$item .= '
';
}
return $item;
}
-
}
@@ -131,6 +177,18 @@
var $catform;
/**
+ * Cache of all items contained in list
+ * Presents only in top-level list.
+ * For question category list top-level list is question_category_object
+ * @var array that contains from:
+ * [id]['sortorder'] => sortorder
+ * [id]['parent'] => parentid
+ * [id]['item'] => reference to item object
+ * [id]['context'] => question category context
+ */
+ var $itemscache = null;
+
+ /**
* Constructor
*
* Gets necessary strings and sets relevant path information
@@ -146,8 +204,6 @@
$this->str->questions = get_string('questions', 'quiz');
$this->str->add = get_string('add');
$this->str->delete = get_string('delete');
- $this->str->moveup = get_string('moveup');
- $this->str->movedown = get_string('movedown');
$this->str->edit = get_string('editthiscategory', 'question');
$this->str->hide = get_string('hide');
$this->str->publish = get_string('publish', 'quiz');
@@ -176,8 +232,9 @@
*/
function initialize($page, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
$lastlist = null;
+ $this->itemscache = array();
foreach ($contexts as $context){
- $this->editlists[$context->id] = new question_category_list('ul', '', true, $this->pageurl, $page, 'cpage', QUESTION_PAGE_LENGTH, $context);
+ $this->editlists[$context->id] = new question_category_list('ul', '', true, $this->pageurl, $page, 'cpage', QUESTION_PAGE_LENGTH, $context, $this);
$this->editlists[$context->id]->lastlist =& $lastlist;
if ($lastlist!== null){
$lastlist->nextlist =& $this->editlists[$context->id];
@@ -195,6 +252,21 @@
$this->catform->set_data(array('parent'=>$defaultcategory));
}
}
+
+ /**
+ * Handles question category list actions
+ * @param string $action action name
+ * @param string $value action argument
+ */
+ function process_action($action, $value) {
+ if ($action != 'noaction') {
+ global $USER;
+ confirm_sesskey();
+ $context = $this->itemscache[$value]['context'];
+ $this->editlists[$context]->process_action($action, $value);
+ }
+ }
+
/**
* Displays the user interface
*
@@ -219,6 +291,25 @@
$this->catform->display();
}
+ /**
+ * Outputs a link to cancel moving category
+ */
+ function print_cancel_moving_link() {
+ global $COURSE,$USER;
+ $itemtomove = 0;
+ if (count($this->editlists)>0){
+ reset($this->editlists);
+ $itemtomove = current($this->editlists)->get_moving_item();
+ }
+
+ if ($itemtomove != 0) {
+ $itemname = $this->itemscache[$itemtomove]['item']->name;
+ echo "".get_string('movingcategory','question').
+ ": ".$itemname." (".get_string('cancel').")
";
+ }
+ }
/**
* Outputs a list to allow editing/rearranging of existing categories
@@ -228,6 +319,7 @@
*/
function output_edit_lists() {
print_heading_with_help(get_string('editcategories', 'quiz'), 'categories', 'question');
+ $this->print_cancel_moving_link();
foreach ($this->editlists as $context => $list){
$listhtml = $list->to_html(0, array('str'=>$this->str));
if ($listhtml){
@@ -240,8 +332,6 @@
echo $list->display_page_numbers();
}
-
-
/**
* gets all the courseids for the given categories
*
@@ -378,7 +468,15 @@
$cat->contextid = $contextid;
$cat->name = $newcategory;
$cat->info = $newinfo;
- $cat->sortorder = 999;
+
+ // There are shouldn't be two items in one list with the same sortorder
+ $cat->sortorder = 0;
+ $neighbors = $this->itemscache[$cat->parent]['item']->children->items;
+ foreach ($neighbors as $item) {
+ if ($item->item->sortorder>=$cat->sortorder)
+ $cat->sortorder = $item->item->sortorder + 1;
+ }
+
$cat->stamp = make_unique_id_code();
if (!insert_record("question_categories", $cat)) {
error("Could not insert the new question category '$newcategory'");
@@ -402,6 +500,14 @@
if (!empty($newparent) && !$lastcategoryinthiscontext) {
list($parentid, $tocontextid) = explode(',', $newparent);
+
+ // If parent changed category will moved in the end of list
+ $newsortorder = 0;
+ $neighbors = $this->itemscache[$parentid]['item']->children->items;
+ foreach ($neighbors as $item) {
+ if ($item->item->sortorder>=$newsortorder)
+ $newsortorder = $item->item->sortorder + 1;
+ }
} else {
$parentid = $oldcat->parent;
$tocontextid = $oldcat->contextid;
@@ -423,6 +529,7 @@
$cat->name = $newname;
$cat->info = $newinfo;
$cat->parent = $parentid;
+ $cat->sortorder = $newsortorder;
// We don't change $cat->contextid here, if necessary we redirect to contextmove.php later.
if (!update_record("question_categories", $cat)) {
error("Could not update the category '$newname'", $this->pageurl->out());