Moving quiz-independent question scripts to their new location. In a following commit...
[moodle.git] / question / category_class.php
CommitLineData
516cf3eb 1<? // $Id:
2/**
3* Class quiz_category_object
4*
5* Used for handling changes to the quiz categories
6*
7*/
8
9// number of categories to display on page
10define( "PAGE_LENGTH",25 );
11
12class quiz_category_object {
13
14 var $str;
15 var $pixpath;
16 var $edittable;
17 var $newtable;
18 var $tab;
19 var $tabsize = 3;
20 var $categories;
21 var $categorystrings;
22 var $defaultcategory;
23 var $course;
24 var $topcount;
25
26/**
27* Constructor
28*
29* Gets necessary strings and sets relevant path information
30*
31*/
32 function quiz_category_object() {
33 global $CFG;
34
35 $this->tab = str_repeat('&nbsp;', $this->tabsize);
36
37 $this->str->course = get_string('course');
38 $this->str->category = get_string('category', 'quiz');
39 $this->str->categoryinfo = get_string('categoryinfo', 'quiz');
40 $this->str->questions = get_string('questions', 'quiz');
41 $this->str->add = get_string('add');
42 $this->str->delete = get_string('delete');
43 $this->str->moveup = get_string('moveup');
44 $this->str->movedown = get_string('movedown');
45 $this->str->edit = get_string('editthiscategory');
46 $this->str->hide = get_string('hide');
47 $this->str->publish = get_string('publish', 'quiz');
48 $this->str->order = get_string('order');
49 $this->str->parent = get_string('parent', 'quiz');
50 $this->str->add = get_string('add');
51 $this->str->action = get_string('action');
52 $this->str->top = get_string('top', 'quiz');
53 $this->str->addcategory = get_string('addcategory', 'quiz');
54 $this->str->editcategory = get_string('editcategory', 'quiz');
55 $this->str->cancel = get_string('cancel');
56 $this->str->editcategories = get_string('editcategories', 'quiz');
57 $this->str->page = get_string('page');
58 $this->pixpath = $CFG->pixpath;
59
60 }
61
62/**
63* Sets the course for this object
64*
65* @param object course
66*/
67 function set_course($course) {
68 $this->course = $course;
69 }
70
71/**
72* Displays the user interface
73*
74* @param object modform
75* @param int $page page number to display (0=don't paginate)
76*/
77 function display_user_interface($page=0) {
78 $this->initialize();
79
80 /// Interface for adding a new category:
81 print_heading_with_help($this->str->addcategory, 'categories_edit', 'quiz');
82 $this->output_new_table();
83 echo '<br />';
84
85 /// Interface for editing existing categories
86 print_heading_with_help($this->str->editcategories, 'categories', 'quiz');
87 $this->output_edit_table($page);
88 if ($this->topcount>PAGE_LENGTH) {
89 $this->display_page_numbers($page);
90 }
91 echo '<br />';
92
93 }
94
95
96/**
97* Initializes this classes general category-related variables
98*
99*/
100 function initialize() {
101
102 /// Get the existing categories
103 if (!$this->defaultcategory = quiz_get_default_category($this->course->id)) {
104 error("Error: Could not find or make a category!");
105 }
106
107 $this->categories = $this->get_quiz_categories(null, "parent, sortorder, name ASC");
108
109 $this->categories = $this->arrange_categories($this->categories);
110
111 // create the array of id=>full_name strings
112 $this->categorystrings = $this->expanded_category_strings($this->categories);
113
114 // for pagination calculate number of 'top' categories and hence number of pages
115 // (pagination only based on top categories)
116 $count = 0;
117 foreach( $this->categories as $category ) {
118 if ($category->parent==0) {
119 ++$count;
120 }
121 }
122 $this->topcount = $count;
123 $this->pagecount = (integer) ceil( $count / PAGE_LENGTH );
124 }
125
126/**
127 * display list of page numbers for navigation
128 */
129 function display_page_numbers( $page=0 ) {
130 global $USER;
131
132 echo "<div class=\"paging\">{$this->str->page}:\n";
133 foreach (range(1,$this->pagecount) as $currentpage) {
134 if ($page == $currentpage) {
135 echo " $currentpage \n";
136 }
137 else {
138 echo "<a href=\"category.php?id={$this->course->id}&amp;page=$currentpage&amp;sesskey={$USER->sesskey}\">";
139 echo " $currentpage </a>\n";
140 }
141 }
142 echo "</div>";
143 }
144
145/**
146* Outputs a table to allow entry of a new category
147*
148*/
149 function output_new_table() {
150 global $USER;
151 $publishoptions[0] = get_string("no");
152 $publishoptions[1] = get_string("yes");
153
154 $this->newtable->head = array ($this->str->parent, $this->str->category, $this->str->categoryinfo, $this->str->publish, $this->str->action);
155 $this->newtable->width = 200;
156 $this->newtable->data[] = array();
157 $this->newtable->tablealign = 'center';
158
159 /// Each section below adds a data cell to the table row
160
161
162 $viableparents[0] = $this->str->top;
163 $viableparents = $viableparents + $this->categorystrings;
164 $this->newtable->align['parent'] = "left";
165 $this->newtable->wrap['parent'] = "nowrap";
166 $row['parent'] = choose_from_menu ($viableparents, "newparent", $this->str->top, "", "", "", true);
167
168 $this->newtable->align['category'] = "left";
169 $this->newtable->wrap['category'] = "nowrap";
170 $row['category'] = '<input type="text" name="newcategory" value="" size="15" />';
171
172 $this->newtable->align['info'] = "left";
173 $this->newtable->wrap['info'] = "nowrap";
174 $row['info'] = '<input type="text" name="newinfo" value="" size="50" />';
175
176 $this->newtable->align['publish'] = "left";
177 $this->newtable->wrap['publish'] = "nowrap";
178 $row['publish'] = choose_from_menu ($publishoptions, "newpublish", "", "", "", "", true);
179
180 $this->newtable->align['action'] = "left";
181 $this->newtable->wrap['action'] = "nowrap";
182 $row['action'] = '<input type="submit" value="' . $this->str->add . '" />';
183
184
185 $this->newtable->data[] = $row;
186
187 // wrap the table in a form and output it
188 echo '<form action="category.php" method="post">';
189 echo "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />";
190 echo '<input type="hidden" name="id" value="'. $this->course->id . '" />';
191 echo '<input type="hidden" name="addcategory" value="true" />';
192 print_table($this->newtable);
193 echo '</form>';
194 }
195
196/**
197* Outputs a table to allow editing/rearranging of existing categories
198*
199* $this->initialize() must have already been called
200*
201* @param object course
202* @param int $page page to display (0=do not paginate)
203*/
204 function output_edit_table($page=0) {
205 $this->edittable->head = array ($this->str->category, $this->str->categoryinfo, $this->str->questions, $this->str->publish,
206 $this->str->delete, $this->str->order, $this->str->parent);
207 $this->edittable->width = 200;
208 $this->edittable->tablealign = 'center';
209
210 $courses = $this->course->shortname;
211
212 // if pagination required work out range
213 if (!empty($page)) {
214 $firstcat = ($page-1) * PAGE_LENGTH + 1;
215 $lastcat = $firstcat + PAGE_LENGTH - 1;
216 }
217 else {
218 $firstcat = 1;
219 $lastcat = $this->topcount;
220 }
221//echo "$firstcat $lastcat $page"; die;
222 $this->build_edit_table_body($this->categories, $page, $firstcat, $lastcat);
223 print_table($this->edittable);
224 }
225/**
226* Recursively builds up the edit-categories table body
227*
228* @param array categories contains category objects in a tree representation
229* @param mixed courses String with shortname of course | array containing courseid=>shortname
230* @param int depth controls the indenting
231*/
232 function build_edit_table_body($categories, $page = 0, $firstcat = 1, $lastcat = 99999, $depth = 0) {
233 $countcats = count($categories);
234 $count = 0;
235 $first = true;
236 $last = false;
237 $topcount = 0;
238
239 foreach ($categories as $category) {
240 $count++;
241 if ($count == $countcats) {
242 $last = true;
243 }
244 // check if this category is on the display page
245 if ($depth==0) {
246 $topcount++;
247 if (($topcount<$firstcat) or ($topcount>$lastcat)) {
248 continue;
249 }
250 }
251 $up = $first ? false : true;
252 $down = $last ? false : true;
253 $first = false;
254 $this->quiz_edit_category_row($category, $depth, $up, $down, $page);
255 if (isset($category->children)) {
256 $this->build_edit_table_body($category->children, $page, $firstcat, $lastcat, $depth + 1);
257 }
258 }
259 }
260
261/**
262* gets all the courseids for the given categories
263*
264* @param array categories contains category objects in a tree representation
265* @return array courseids flat array in form categoryid=>courseid
266*/
267 function get_course_ids($categories) {
268 $courseids = array();
269 foreach ($categories as $key=>$cat) {
270 $courseids[$key] = $cat->course;
271 if (!empty($cat->children)) {
272 $courseids = array_merge($courseids, $this->get_course_ids($cat->children));
273 }
274 }
275 return $courseids;
276 }
277
278/**
279* Constructs each row of the edit-categories table
280*
281* @param object category
282* @param int depth controls the indenting
283* @param string shortname short name of the course
284* @param boolean up can it be moved up?
285* @param boolean down can it be moved down?
286* @param int page page number
287*/
288 function quiz_edit_category_row($category, $depth, $up = false, $down = false, $page = 0) {
289 global $USER;
290 $fill = str_repeat($this->tab, $depth);
291
292 $linkcss = $category->publish ? ' class="published"' : ' class="unpublished"';
293
294 if (!empty($page)) {
295 $pagelink="&amp;page=$page";
296 }
297 else {
298 $pagelink="";
299 }
300
301 /// Each section below adds a data cell to this table row
302
303 $this->edittable->align["$category->id.name"] = "left";
304 $this->edittable->wrap["$category->id.name"] = "nowrap";
305 $row["$category->id.name"] = '<a ' . $linkcss . 'title="' . $this->str->edit. '" href="category.php?id=' . $this->course->id .
306 '&amp;edit=' . $category->id . '&amp;sesskey='.$USER->sesskey.$pagelink.'"><img src="' . $this->pixpath . '/t/edit.gif" height="11" width="11" border="0"
307 alt="' .$this->str->edit. '" /> ' . $fill . $category->name . '</a>';
308
309 $this->edittable->align["$category->id.info"] = "left";
310 $this->edittable->wrap["$category->id.info"] = "nowrap";
311 $row["$category->id.info"] = '<a ' . $linkcss . 'title="' . $this->str->edit .'" href="category.php?id=' . $this->course->id .
312 '&amp;edit=' . $category->id . '&amp;sesskey='.$USER->sesskey.$pagelink.'">' . $category->info . '</a>';
313
314 $this->edittable->align["$category->id.qcount"] = "center";
315 $row["$category->id.qcount"] = $category->questioncount;
316
317 $this->edittable->align["$category->id.publish"] = "center";
318 $this->edittable->wrap["$category->id.publish"] = "nowrap";
319 if (!empty($category->publish)) {
320 $row["$category->id.publish"] = '<a title="' . $this->str->hide . '" href="category.php?id=' . $this->course->id . '&amp;hide=' . $category->id .
321 '&amp;sesskey='.$USER->sesskey.$pagelink.'"><img src="' . $this->pixpath . '/t/hide.gif" height="11" width="11" border="0" alt="' .$this->str->hide. '" /></a> ';
322 } else {
323 $row["$category->id.publish"] = '<a title="' . $this->str->publish . '" href="category.php?id=' . $this->course->id . '&amp;publish=' . $category->id .
324 '&amp;sesskey='.$USER->sesskey.$pagelink.'"><img src="' . $this->pixpath . '/t/show.gif" height="11" width="11" border="0" alt="' .$this->str->publish. '" /></a> ';
325 }
326
327 if ($category->id != $this->defaultcategory->id) {
328 $this->edittable->align["$category->id.delete"] = "center";
329 $this->edittable->wrap["$category->id.delete"] = "nowrap";
330 $row["$category->id.delete"] = '<a title="' . $this->str->delete . '" href="category.php?id=' . $this->course->id .
331 '&amp;delete=' . $category->id . '&amp;sesskey='.$USER->sesskey.$pagelink.'"><img src="' . $this->pixpath . '/t/delete.gif" height="11" width="11" border="0" alt="' .$this->str->delete. '" /></a> ';
332 } else {
333 $row["$category->id.delete"] = '';
334 }
335
336 $this->edittable->align["$category->id.order"] = "left";
337 $this->edittable->wrap["$category->id.order"] = "nowrap";
338 $icons = '';
339 if ($up) {
340 $icons .= '<a title="' . $this->str->moveup .'" href="category.php?id=' . $this->course->id . '&amp;moveup=' . $category->id . '&amp;sesskey='.$USER->sesskey.$pagelink.'">
341 <img src="' . $this->pixpath . '/t/up.gif" height="11" width="11" border="0" alt="' . $this->str->moveup. '" /></a> ';
342 }
343 if ($down) {
344 $icons .= '<a title="' . $this->str->movedown .'" href="category.php?id=' . $this->course->id . '&amp;movedown=' . $category->id . '&amp;sesskey='.$USER->sesskey.$pagelink.'">
345 <img src="' . $this->pixpath . '/t/down.gif" height="11" width="11" border="0" alt="' .$this->str->movedown. '" /></a> ';
346 }
347 $row["$category->id.order"]= $icons;
348
349 $this->edittable->align["$category->id.moveto"] = "left";
350 $this->edittable->wrap["$category->id.moveto"] = "nowrap";
351 if ($category->id != $this->defaultcategory->id) {
352 $viableparents = $this->categorystrings;
353 $this->set_viable_parents($viableparents, $category);
354 $viableparents = array(0=>$this->str->top) + $viableparents;
355
356 $row["$category->id.moveto"] = popup_form ("category.php?id={$this->course->id}&amp;move={$category->id}&amp;sesskey=$USER->sesskey$pagelink&amp;moveto=",
357 $viableparents, "moveform{$category->id}", "$category->parent", "", "", "", true);
358 } else {
359 $row["$category->id.moveto"]='---';
360 }
361
362
363 $this->edittable->data[$category->id] = $row;
364 }
365
366
367 function edit_single_category($categoryid,$page=1) {
368 /// Interface for adding a new category
369 global $USER;
370 $this->initialize();
371
372 /// Interface for editing existing categories
373 if ($category = get_record("quiz_categories", "id", $categoryid)) {
374 echo '<h2 align="center">';
375 echo $this->str->edit;
376 helpbutton("categories_edit", $this->str->editcategory, "quiz");
377 echo '</h2>';
378 echo '<table width="100%"><tr><td>';
379 $this->output_edit_single_table($category,$page);
380 echo '</td></tr></table>';
381 echo '<p><div align="center"><form action="category.php" method="get">
382 <input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />
383 <input type="hidden" name="id" value="' . $this->course->id . '" />
384 <input type="submit" value="' . $this->str->cancel . '" /></form></div></p>';
385 print_footer($this->course);
386 exit;
387 } else {
388 error("Category $categoryid not found", "category.php?id={$this->course->id}");
389 }
390 }
391
392
393/**
394* Outputs a table to allow editing of an existing category
395*
396* @param object category
397* @param int page current page
398*/
399 function output_edit_single_table($category, $page=1) {
400 global $USER;
401 $publishoptions[0] = get_string("no");
402 $publishoptions[1] = get_string("yes");
403 $strupdate = get_string('update');
404
405 unset ($edittable);
406
407 $edittable->head = array ($this->str->parent, $this->str->category, $this->str->categoryinfo, $this->str->publish, $this->str->action);
408 $edittable->width = 200;
409 $edittable->data[] = array();
410 $edittable->tablealign = 'center';
411
412 /// Each section below adds a data cell to the table row
413
414 $viableparents = $this->categorystrings;
415 $this->set_viable_parents($viableparents, $category);
416 $viableparents = array(0=>$this->str->top) + $viableparents;
417 $edittable->align['parent'] = "left";
418 $edittable->wrap['parent'] = "nowrap";
419 $row['parent'] = choose_from_menu ($viableparents, "updateparent", "{$category->parent}", "", "", "", true);
420
421 $edittable->align['category'] = "left";
422 $edittable->wrap['category'] = "nowrap";
423 $row['category'] = '<input type="text" name="updatename" value="' . $category->name . '" size="15" />';
424
425 $edittable->align['info'] = "left";
426 $edittable->wrap['info'] = "nowrap";
427 $row['info'] = '<input type="text" name="updateinfo" value="' . $category->info . '" size="50" />';
428
429 $edittable->align['publish'] = "left";
430 $edittable->wrap['publish'] = "nowrap";
431 $selected = (boolean)$category->publish ? 1 : 0;
432 $row['publish'] = choose_from_menu ($publishoptions, "updatepublish", $selected, "", "", "", true);
433
434 $edittable->align['action'] = "left";
435 $edittable->wrap['action'] = "nowrap";
436 $row['action'] = '<input type="submit" value="' . $strupdate . '" />';
437
438 $edittable->data[] = $row;
439
440 // wrap the table in a form and output it
441 echo '<p><form action="category.php" method="post">';
442 echo "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />";
443 echo '<input type="hidden" name="id" value="'. $this->course->id . '" />';
444 echo '<input type="hidden" name="updateid" value="' . $category->id . '" />';
445 echo "<input type=\"hidden\" name=\"page\" value=\"$page\" />";
446 print_table($edittable);
447 echo '</form></p>';
448 }
449
450
451/**
452* Creates an array of "full-path" category strings
453* Structure:
454* key => string
455* where key is the category id, and string contains the name of all ancestors as well as the particular category name
456* E.g. '123'=>'Language / English / Grammar / Modal Verbs"
457*
458* @param array $categories an array containing categories arranged in a tree structure
459*/
460 function expanded_category_strings($categories, $parent=null) {
461 $prefix = is_null($parent) ? '' : "$parent / ";
462 $categorystrings = array();
463 foreach ($categories as $key => $category) {
464 $expandedname = "$prefix$category->name";
465 $categorystrings[$key] = $expandedname;
466 if (isset($category->children)) {
467 $categorystrings = $categorystrings + $this->expanded_category_strings($category->children, $expandedname);
468 }
469 }
470 return $categorystrings;
471 }
472
473
474/**
475* Arranges the categories into a hierarchical tree
476*
477* If a category has children, it's "children" property holds an array of children
478* The questioncount for each category is also calculated
479*
480* @param array records a flat list of the categories
481* @return array categorytree a hierarchical list of the categories
482*/
483 function arrange_categories($records) {
484 //todo: get the question count for all records with one sql statement: select category, count(*) from quiz_questions group by category
485 $levels = array();
486
487 // build a levels array, which places each record according to it's depth from the top level
488 $parents = array(0);
489 while (!empty($parents)) {
490 $children = array();
491 foreach ($records as $record) {
492 if (in_array($record->parent, $parents)) {
493 $children[] = $record->id;
494 }
495 }
496 if (!empty($children)) {
497 $levels[] = $children;
498 }
499 $parents = $children;
500 }
501 // if there is no hierarchy (e.g., if all records have parent == 0), set level[0] to these keys
502 if (empty($levels)) {
503 $levels[0] = array_keys($records);
504 }
505
506 // build a hierarchical array that depicts the parent-child relationships of the categories
507 $categorytree = array();
508 for ($index = count($levels) - 1; $index >= 0; $index--) {
509 foreach($levels[$index] as $key) {
510 $parentkey = $records[$key]->parent;
511 if (!($records[$key]->questioncount = count_records('quiz_questions', 'category', $records[$key]->id, 'hidden', 0, 'parent', '0'))) {
512 $records[$key]->questioncount = 0;
513 }
514 if ($parentkey == 0) {
515 $categorytree[$key] = $records[$key];
516 } else {
517 $records[$parentkey]->children[$key] = $records[$key];
518 }
519 }
520 }
521 return $categorytree;
522 }
523
524
525/**
526* Sets the viable parents
527*
528* Viable parents are any except for the category itself, or any of it's descendants
529* The parentstrings parameter is passed by reference and changed by this function.
530*
531* @param array parentstrings a list of parentstrings
532* @param object category
533*/
534 function set_viable_parents(&$parentstrings, $category) {
535
536 unset($parentstrings[$category->id]);
537 if (isset($category->children)) {
538 foreach ($category->children as $child) {
539 $this->set_viable_parents($parentstrings, $child);
540 }
541 }
542 }
543
544/**
545* Gets quiz categories
546*
547* @param int parent - if given, restrict records to those with this parent id.
548* @param string sort - [[sortfield [,sortfield]] {ASC|DESC}]
549* @return array categories
550*/
551 function get_quiz_categories($parent=null, $sort="sortorder ASC") {
552
553 if (is_null($parent)) {
554 $categories = get_records('quiz_categories', 'course', "{$this->course->id}", $sort);
555 } else {
556 $select = "parent = '$parent' AND course = '{$this->course->id}'";
557 $categories = get_records_select('quiz_categories', $select, $sort);
558 }
559 return $categories;
560 }
561
562
563/**
564* Deletes an existing quiz category
565*
566* @param int deletecat id of category to delete
567* @param int destcategoryid id of category which will inherit the orphans of deletecat
568*/
569 function delete_category($deletecat, $destcategoryid = null) {
570 global $USER;
571
572 if (!$category = get_record("quiz_categories", "id", $deletecat)) { // security
573 error("No such category $deletecat!", "category.php?id={$this->course->id}");
574 }
575
576 if (!is_null($destcategoryid)) { // Need to move some questions before deleting the category
577 if (!$category2 = get_record("quiz_categories", "id", $destcategoryid)) { // security
578 error("No such category $destcategoryid!", "category.php?id={$this->course->id}");
579 }
580 if (! set_field('quiz_questions', 'category', $category2, 'category', $category1)) {
581 error("Error while moving questions from category '$category->name' to '$category2->name'", "category.php?id={$this->course->id}");
582 }
583
584 } else {
585 // todo: delete any hidden questions that are not actually in use any more
586 if ($count = count_records("quiz_questions", "category", $category->id)) {
587 $vars->name = $category->name;
588 $vars->count = $count;
589 print_simple_box(get_string("categorymove", "quiz", $vars), "center");
590 $this->initialize();
591 $categorystrings = $this->categorystrings;
592 unset ($categorystrings[$category->id]);
593 echo "<p><div align=\"center\"><form action=\"category.php\" method=\"get\">";
594 echo "<input type=\"hidden\" name=\"sesskey\" value=\"$USER->sesskey\" />";
595 echo "<input type=\"hidden\" name=\"id\" value=\"{$this->course->id}\" />";
596 echo "<input type=\"hidden\" name=\"delete\" value=\"$category->id\" />";
597 choose_from_menu($categorystrings, "confirm", "", "");
598 echo "<input type=\"submit\" value=\"". get_string("categorymoveto", "quiz") . "\" />";
599 echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->str->cancel}\" />";
600 echo "</form></div></p>";
601 print_footer($this->course);
602 exit;
603 }
604 }
605 delete_records("quiz_categories", "id", $category->id);
606
607 /// Send the children categories to live with their grandparent
608 if ($childcats = get_records("quiz_categories", "parent", $category->id)) {
609 foreach ($childcats as $childcat) {
610 if (! set_field("quiz_categories", "parent", $category->parent, "id", $childcat->id)) {
611 error("Could not update a child category!", "category.php?id={$this->course->id}");
612 }
613 }
614 }
615
616 /// Finally delete the category itself
617 if (delete_records("quiz_categories", "id", $category->id)) {
618 notify(get_string("categorydeleted", "quiz", $category->name), 'green');
619 }
620 }
621
622/**
623* Moves a category up or down in the display order
624*
625* @param string direction up|down
626* @param int categoryid id of category to move
627*/
628 function move_category_up_down ($direction, $categoryid) {
629 /// Move a category up or down
630 $swapcategory = NULL;
631 $movecategory = NULL;
632
633 if ($direction == 'up') {
634 if ($movecategory = get_record("quiz_categories", "id", $categoryid)) {
635 $categories = $this->get_quiz_categories("$movecategory->parent", 'parent, sortorder, name');
636
637 foreach ($categories as $category) {
638 if ($category->id == $movecategory->id) {
639 break;
640 }
641 $swapcategory = $category;
642 }
643 }
644 }
645 if ($direction == 'down') {
646 if ($movecategory = get_record("quiz_categories", "id", $categoryid)) {
647 $categories = $this->get_quiz_categories("$movecategory->parent", 'parent, sortorder, name');
648 $choosenext = false;
649 foreach ($categories as $category) {
650 if ($choosenext) {
651 $swapcategory = $category;
652 break;
653 }
654 if ($category->id == $movecategory->id) {
655 $choosenext = true;
656 }
657 }
658 }
659 }
660 if ($swapcategory and $movecategory) { // Renumber everything for robustness
661 $count=0;
662 foreach ($categories as $category) {
663 $count++;
664 if ($category->id == $swapcategory->id) {
665 $category = $movecategory;
666 } else if ($category->id == $movecategory->id) {
667 $category = $swapcategory;
668 }
669 if (! set_field("quiz_categories", "sortorder", $count, "id", $category->id)) {
670 notify("Could not update that category!");
671 }
672 }
673 }
674 }
675
676/**
677* Changes the parent of a category
678*
679* @param int categoryid
680* @param int parentid
681*/
682 function move_category($categoryid, $parentid) {
683 /// Move a category to a new parent
684
685 if ($tempcat = get_record("quiz_categories", "id", $categoryid)) {
686 if ($tempcat->parent != $parentid) {
687 if (! set_field("quiz_categories", "parent", $parentid, "id", $tempcat->id)) {
688 notify("Could not update that category!");
689 }
690 }
691 }
692 }
693
694/**
695* Changes the published status of a category
696*
697* @param boolean publish
698* @param int categoryid
699*/
700 function publish_category($publish, $categoryid) {
701 /// Hide or publish a category
702
703 $publish = ($publish == false) ? 0 : 1;
704 $tempcat = get_record("quiz_categories", "id", $categoryid);
705 if ($tempcat) {
706 if (! set_field("quiz_categories", "publish", $publish, "id", $tempcat->id)) {
707 notify("Could not update that category!");
708 }
709 }
710 }
711
712/**
713* Creates a new category with given params
714*
715* @param int $newparent id of the parent category
716* @param string $newcategory the name for the new category
717* @param string $newinfo the info field for the new category
718* @param int $newpublish whether to publish the category
719* @param int $newcourse the id of the associated course
720*/
721 function add_category($newparent, $newcategory, $newinfo, $newpublish, $newcourse) {
722
723 if ($newparent) {
724 // first check that the parent category is in the correct course
725 if(!(get_field('quiz_categories', 'course', 'id', $newparent) == $newcourse)) {
726 return false;
727 }
728 }
729
730 $cat = NULL;
731 $cat->parent = $newparent;
732 $cat->name = $newcategory;
733 $cat->info = $newinfo;
734 $cat->publish = $newpublish;
735 $cat->course = $newcourse;
736 $cat->sortorder = 999;
737 $cat->stamp = make_unique_id_code();
738 if (!insert_record("quiz_categories", $cat)) {
739 error("Could not insert the new quiz category '$newcategory'", "category.php?id={$newcourse}");
740 } else {
741 notify(get_string("categoryadded", "quiz", $newcategory), 'green');
742 }
743
744 }
745
746/**
747* Updates an existing category with given params
748*
749* @param int updateid
750* @param int updateparent
751* @param string updatename
752* @param string updateinfo
753* @param int updatepublish
754* @param int courseid the id of the associated course
755*/
756 function update_category($updateid, $updateparent, $updatename, $updateinfo, $updatepublish, $courseid) {
757
758 $cat = NULL;
759 $cat->id = $updateid;
760 $cat->parent = $updateparent;
761 $cat->name = $updatename;
762 $cat->info = $updateinfo;
763 $cat->publish = $updatepublish;
764 if (!update_record("quiz_categories", $cat)) {
765 error("Could not update the category '$updatename'", "category.php?id={$courseid}");
766 } else {
767 notify(get_string("categoryupdated", 'quiz'), 'green');
768 }
769 }
770
771}
772
773?>