]> git.mjollnir.org Git - moodle.git/commitdiff
Hierarchical question categories from mediagonal, see http://moodle.org/bugs/bug...
authorgustav_delius <gustav_delius>
Sun, 2 Jan 2005 15:10:50 +0000 (15:10 +0000)
committergustav_delius <gustav_delius>
Sun, 2 Jan 2005 15:10:50 +0000 (15:10 +0000)
12 files changed:
lang/de/quiz.php
lang/en/help/quiz/categories.html
lang/en/help/quiz/categories_edit.html [new file with mode: 0644]
lang/en/quiz.php
lang/fr/quiz.php
mod/quiz/category.php
mod/quiz/db/mysql.php
mod/quiz/db/mysql.sql
mod/quiz/db/postgres7.php
mod/quiz/db/postgres7.sql
mod/quiz/lib.php
mod/quiz/version.php

index 9c821760ed9e7c59d8005a79e4a6c9f65bace99f..2f2e6000489690e776e9cfe0e04e7e9441849ced 100644 (file)
@@ -3,6 +3,7 @@
 
 
 $string['acceptederror'] = 'Akzeptierter Fehler';
+$string['addcategory'] = 'Kategorie hinzufügen';
 $string['addingquestions'] = 'Diese Spalte der Seite ist zum Verwalten von Testfragen. Fragen werden in Kategorien gespeichert, um sie besser organisieren zu können, und können von jedem Test Ihres Kurses oder sogar von anderen Kursen (Wenn man \'veröffentlichen\' ausgewählt hat) benutzt werden. <br /><br />Nachdem Sie eine Kategorie erzeugt haben, können Sie Fragen erzeugen oder bearbeiten. Sie können jede dieser Fragen auswählen und Ihrem Test in der anderen Spalte hinzufügen.';
 $string['addquestions'] = 'Fragen hinzufügen';
 $string['addquestionstoquiz'] = 'Frage zu aktuellem Test hinzufügen';
@@ -41,6 +42,7 @@ $string['category'] = 'Kategorie';
 $string['categoryinfo'] = 'Kategorie-Information';
 $string['categorymove'] = 'Die Kategorie \'$a->name\' enthält $a->count Fragen. Bitte wählen Sie eine andere Kategorie, um sie zu verschieben.';
 $string['categorymoveto'] = 'In diese Kategorie verschieben';
+$string['categoryupdated'] = 'Änderung an Kategorie gespeichert';
 $string['checkanswer'] = 'Prüfen';
 $string['choice'] = 'Auswahl';
 $string['choices'] = 'Verfügbare Auswahl';
@@ -72,6 +74,7 @@ $string['description'] = 'Beschreibung';
 $string['discrimination'] = 'Index für die Abgrenzung';
 $string['eachattemptbuildsonthelast'] = 'Jeder Versuch basiert auf dem Letzten';
 $string['editcategories'] = 'Kategorien bearbeiten';
+$string['editcategory'] = 'Kategorie bearbeiten';
 $string['editdatasets'] = 'Datensatz bearbeiten';
 $string['editingcalculated'] = 'Bearbeiten einer  Rechen-Frage';
 $string['editingdescription'] = 'Eine Beschreibung bearbeiten';
@@ -167,6 +170,7 @@ $string['numerical'] = 'Numerisch';
 $string['optional'] = 'optional';
 $string['overdue'] = 'Überfällig';
 $string['paragraphquestion'] = 'Fragezeichen in Zeile $a wird nicht unterstützt. Die Frage wird ignoriert.';
+$string['parent'] = 'Übergeordnete Kategorie';
 $string['passworderror'] = 'Das eingegebene Passwort war falsch';
 $string['percentcorrect'] = 'Richtig in Prozent';
 $string['preview'] = 'Vorschau';
@@ -240,6 +244,7 @@ $string['timesup'] = 'Zeitraum ist abgelaufen';
 $string['timetaken'] = 'Verbrauchte Zeit';
 $string['tolerance'] = 'Toleranz';
 $string['toomanyrandom'] = 'Die Anzahl der benötigten Zufallsfragen ist größer als die, die die Kategorie enthält! ($a)';
+$string['top'] = 'Oberste Ebene';
 $string['true'] = 'Wahr';
 $string['truefalse'] = 'Wahr/Falsch';
 $string['type'] = 'Typ';
index 5d22556e6c47dba5b49447ec7cbf37ccfe959ca6..ea1a95fa755307a630a72f2cadd9c9f95d5388e9 100644 (file)
@@ -1,17 +1,23 @@
 <p align="center"><b>Question categories</b></p>
 
 <p>Rather than keeping all your questions in one big list,
-   you can create categories to keep them in.
+   you can create categories to keep them in.</p>
 
-<p>Each category consists of a name and a short description.
+<p>Each category consists of a name and a short description.</p>
 
 <p>Each category can also be "published", which means 
    that the category (and all questions in it) will be 
    available to all courses on this server, so that 
-   other courses can use your questions in their quizzes.
+   other courses can use your questions in their quizzes.</p>
 
 <p>Categories can also be created or deleted at will.
    However, if you try to delete a category containing
    questions, then you will be asked to specify another
-   category to move them to.
+   category to move them to.</p>
 
+<p>You can also arrange the categories in a heirarchy so
+   that they are easier to manage.  The 'Move category to'
+   field lets you move a category to another category.</p>
+
+<p>By clicking on the arrows in the 'Order' field, you
+   can change the order in which the categories are listed.</p> 
\ No newline at end of file
diff --git a/lang/en/help/quiz/categories_edit.html b/lang/en/help/quiz/categories_edit.html
new file mode 100644 (file)
index 0000000..0efab74
--- /dev/null
@@ -0,0 +1,24 @@
+<p align="center"><b>Question categories</b></p>
+
+<p>Rather than keeping all your questions in one big list,
+   you can create categories to keep them in.</p>
+
+<p>Each category consists of a name and a short description.</p>
+
+<p>Each category can also be "published", which means 
+   that the category (and all questions in it) will be 
+   available to all courses on this server, so that 
+   other courses can use your questions in their quizzes.</p>
+
+<p><b>Field descriptions</b></p>
+
+<p><b>Parent:</b> The category in which this one will be placed.  If
+   no other categories have been created, only 'Top' will be
+   available</p>
+
+<p><b>Category:</b> The name of the category.</p>
+
+<p><b>Category info:</b> A brief description of the category.</p>
+
+<p><b>Publish:</b> Whether or not to immediately publish this
+      category.</p>
index e683ba58b070a6ed064753df7a3018524e97659e..17474deb103693a66ab003a4e46ddbd0233e242d 100644 (file)
@@ -3,6 +3,7 @@
 
 
 $string['acceptederror'] = 'Accepted error';
+$string['addcategory'] = 'Add category';
 $string['addingquestions'] = 'This side of the page is where you manage your database of questions.  Questions are stored in categories to help you keep them organised, and can be used by any quiz in your course or even other courses if you choose to \'publish\' them. <br /><br />After you select or create a question category you will be able to create or edit questions.  You can select any of these questions to add to your quiz over on the other side of this page.';
 $string['addquestions'] = 'Add questions';
 $string['addquestionstoquiz'] = 'Add questions to current quiz';
@@ -44,6 +45,7 @@ $string['category'] = 'Category';
 $string['categoryinfo'] = 'Category info';
 $string['categorymove'] = 'The category \'$a->name\' contains $a->count questions.  Please choose another category to move them to.';
 $string['categorymoveto'] = 'Move them to this category';
+$string['categoryupdated'] = 'The category was successfully updated';
 $string['checkanswer'] = 'Check';
 $string['choice'] = 'Choice';
 $string['choices'] = 'Available choices';
@@ -78,6 +80,7 @@ $string['description'] = 'Description';
 $string['discrimination'] = 'Discrim. Index';
 $string['eachattemptbuildsonthelast'] = 'Each attempt builds on the last';
 $string['editcategories'] = 'Edit categories';
+$string['editcategory'] = 'Edit category';
 $string['editdatasets'] = 'Edit the datasets';
 $string['editingcalculated'] = 'Editing a Calculated question';
 $string['editingdescription'] = 'Editing a Description';
@@ -182,6 +185,7 @@ $string['numerical'] = 'Numerical';
 $string['optional'] = 'optional';
 $string['overdue'] = 'Overdue';
 $string['paragraphquestion'] = 'Paragraph Question not supported at line $a. The question will be ignored';
+$string['parent'] = 'Parent';
 $string['passworderror'] = 'The password entered was incorrect';
 $string['percentcorrect'] = 'Percent Correct';
 $string['popup'] = 'Show quiz in a \"secure\" window';
@@ -265,6 +269,7 @@ $string['timetaken'] = 'Time taken';
 $string['tolerance'] = 'Tolerance';
 $string['tolerancetype'] = 'Tolerance Type';
 $string['toomanyrandom'] = 'The number of random questions required is more than this category contains! ($a)';
+$string['top'] = 'Top';
 $string['true'] = 'True';
 $string['truefalse'] = 'True/False';
 $string['type'] = 'Type';
index 0c5999ff6782831839419aea57fcb12dd43fca01..76c83bdb0fe0f1e548f558400c8abb1b42902655 100644 (file)
@@ -1,6 +1,7 @@
 <?php // $Id$ 
 
 $string['acceptederror'] = 'Erreur acceptée';
+$string['addcategory'] = 'Nouvelle catégorie';
 $string['addingquestions'] = 'Vous gérez votre base de données de questions dans cette partie de la page. Les questions sont réparties en catégories, afin de les organiser. Elles peuvent être utilisées dans n\'importe lequel de vos cours, ou même dans d\'autres cours si vous les « publiez ».<br /><br />Créez d\'abord une catégorie. Vous pourrez ensuite créer ou modifier des questions. Vous pouvez choisir une de ces questions pour l\'ajouter à votre test dans l\'autre partie de la page.';
 $string['addquestions'] = 'Ajouter des questions';
 $string['addquestionstoquiz'] = 'Ajouter ces questions au test en cours';
@@ -42,6 +43,7 @@ $string['category'] = 'Cat
 $string['categoryinfo'] = 'Information sur la catégorie';
 $string['categorymove'] = 'La catégorie « $a->name » contient $a->count questions. Choisir une autre catégorie dans laquelle les déplacer.';
 $string['categorymoveto'] = 'Les déplacer dans cette catégorie';
+$string['categoryupdated'] = 'Catégorie enregistrée';
 $string['checkanswer'] = 'Vérifier';
 $string['choice'] = 'Proposition';
 $string['choices'] = 'Propositions';
@@ -76,6 +78,7 @@ $string['description'] = 'Description';
 $string['discrimination'] = 'Index de discrimination';
 $string['eachattemptbuildsonthelast'] = 'Chaque tentative complète la précédente';
 $string['editcategories'] = 'Modifier les catégories';
+$string['editcategory'] = 'Modifier la catégorie';
 $string['editdatasets'] = 'Modifier les jeux de données';
 $string['editingcalculated'] = 'Modifier une question calculée';
 $string['editingdescription'] = 'Modifier une description';
@@ -180,6 +183,7 @@ $string['numerical'] = 'Num
 $string['optional'] = 'facultatif';
 $string['overdue'] = 'En retard';
 $string['paragraphquestion'] = 'Question paragraphe non supportée à la ligne $a. La question sera ignorée.';
+$string['parent'] = 'Catégorie supérieure';
 $string['passworderror'] = 'La clef n\'est pas correcte';
 $string['percentcorrect'] = 'Pourcentage de réponses correctes';
 $string['popup'] = 'Afficher le test dans une fenêtre «&nbsp;sécurisée&nbsp;»';
@@ -257,6 +261,7 @@ $string['timesup'] = 'Le chrono est enclench
 $string['tolerance'] = 'Tolerance';
 $string['tolerancetype'] = 'Type de tolerance';
 $string['toomanyrandom'] = 'Le nombre de questions aléatoires demandées est plus grand que le total ($a) des questions de cette catégorie !';
+$string['top'] = 'Catégorie racine';
 $string['true'] = 'Vrai';
 $string['truefalse'] = 'Vrai/Faux';
 $string['type'] = 'Type';
index c7c2f058f0bc66104514450ecb7c9ab8d24bb332..6f97ec93a62b6dd1ac1fe9b0c2ec05cd9850f316 100644 (file)
 
     require_login($course->id);
 
-    if (!isteacher($course->id)) {
-        error("Only teachers can use this page!");
+    if (!isteacheredit($course->id)) {
+        error("Only teachers authorized to edit the course '{$course->fullname}' can use this page!");
+    }
+    
+    /// CHECK FOR AND ACT UPON VARIABLES SUBMITTED VIA GET OR POST
+    $qcobject = new quiz_category_object();
+    $qcobject->set_course($course);
+    
+    if (isset($delete) and !isset($cancel)) {
+    /// Delete category if the user wants to delete it
+        if (isset($confirm)) {
+            /// 'confirm' is the category to move existing questions to
+            $qcobject->delete_category($delete, $confirm);
+        } else {
+            $qcobject->delete_category($delete);
+        }
+    } else if (isset($moveup)) {
+        $qcobject->move_category_up_down('up', $moveup);
+    } else if (isset($movedown)) {
+        $qcobject->move_category_up_down('down', $movedown);
+    } else if (isset($hide)) {
+        $qcobject->publish_category(false, $hide);
+    } else if (isset($move) and isset($moveto)) {
+        $qcobject->move_category($move, $moveto);
+    } else if (isset($publish)) {
+        $qcobject->publish_category(true, $publish);
+    } else if (isset($addcategory)) {
+        require_variable($newparent);
+        require_variable($newcategory);
+        require_variable($newinfo);
+        require_variable($newpublish);
+        $qcobject->add_category($newparent, $newcategory, $newinfo, $newpublish, $course->id);
+    } else if (isset($edit)) {
+        $qcobject->edit_single_category($edit);
+    } else if (isset($updateid)) {
+        require_variable($updateparent);
+        require_variable($updatename);
+        require_variable($updateinfo);
+        require_variable($updatepublish);
+        $qcobject->update_category($updateid, $updateparent, $updatename, $updateinfo, $updatepublish, $course->id);
     }
 
+    /// DISPLAY THE NORMAL USER INTERFACE
+    if (isset($modform)) {
+        $qcobject->display_user_interface($modform);    
+    } else {
+        $qcobject->display_user_interface();    
+    }
 
-/// Print headings
+/**
+* Class quiz_category_object
+*
+* Used for handling changes to the quiz categories
+*
+*/
+class quiz_category_object {
+
+    var $str;
+    var $pixpath;
+    var $edittable;
+    var $newtable;
+    var $tab;
+    var $tabsize = 3;
+    var $categories;
+    var $categorystrings;
+    var $defaultcategory;
+    var $course;
+    
+/**
+* Constructor
+*
+* Gets necessary strings and sets relevant path information
+*
+*/
+    function quiz_category_object() {
+        global $CFG;
+        
+        $this->tab = str_repeat('&nbsp;', $this->tabsize);
+
+        $this->str->course         = get_string('course');
+        $this->str->category       = get_string('category', 'quiz');
+        $this->str->categoryinfo   = get_string('categoryinfo', 'quiz');
+        $this->str->questions      = get_string('questions', 'quiz');
+        $this->str->add            = get_string('add');
+        $this->str->movecategoryto = get_string('movecategoryto');
+        $this->str->delete         = get_string('delete');
+        $this->str->moveup         = get_string('moveup');
+        $this->str->movedown       = get_string('movedown');
+        $this->str->edit           = get_string('editthiscategory');
+        $this->str->hide           = get_string('hide');
+        $this->str->publish        = get_string('publish', 'quiz');
+        $this->str->order          = get_string('order');
+        $this->str->parent         = get_string('parent', 'quiz');
+        $this->str->add            = get_string('add');
+        $this->str->action         = get_string('action');
+        $this->str->top            = get_string('top', 'quiz');
+        $this->str->addcategory    = get_string('addcategory', 'quiz');
+        $this->str->editcategory   = get_string('editcategory', 'quiz');
+        $this->str->cancel         = get_string('cancel');
+        $this->str->editcategories = get_string('editcategories', 'quiz');
+        $this->pixpath = $CFG->pixpath;
+
+        /// Header:
+        print_header_simple($this->str->editcategories, '',
+                 "<a href=\"index.php?id=$this->course->id\">".get_string('modulenameplural', 'quiz').'</a>'.
+                 " -> {$this->str->editcategories}");
 
-    $strcategory = get_string("category", "quiz");
-    $strcategoryinfo = get_string("categoryinfo", "quiz");
-    $strquestions = get_string("questions", "quiz");
-    $strpublish = get_string("publish", "quiz");
-    $strdelete = get_string("delete");
-    $straction = get_string("action");
-    $stradd = get_string("add");
-    $strcancel = get_string("cancel");
-    $strsavechanges = get_string("savechanges");
-    $strbacktoquiz = get_string("backtoquiz", "quiz");
+    }
 
-    $streditingquiz = get_string(isset($modform->instance) ? "editingquiz"
-                                                           : "editquestions",
-                                 "quiz");
-    $streditcategories = get_string("editcategories", "quiz");
+/**
+* Sets the course for this object
+*
+* @param object course 
+*/
+    function set_course($course) {
+        $this->course = $course;
+    }
+    
+/**
+* Displays the user interface
+*
+* @param object modform 
+*/
+    function display_user_interface($modform = null) {
+        $this->initialize();
+        
+        /// Interface for adding a new category:
+        echo '<h2 align="center">';
+        echo $this->str->addcategory;
+        helpbutton("categories_edit", $this->str->addcategory, "quiz");
+        echo '</h2>';
+        echo '<table width="100%"><tr><td>';
+        $this->output_new_table();
+        echo '</td></tr></table>';
+    
+        /// Interface for editing existing categories
+        echo '<h2 align="center">';
+        echo $this->str->editcategories;
+        helpbutton("categories", $this->str->editcategories, "quiz");
+        echo '</h2>';
+        echo '<table width="100%"><tr><td>';
+        $this->output_edit_table();
+        echo '</td></tr></table>';
+        print_continue('edit.php');
+        print_footer($this->course);
+    }
 
-    print_header_simple("$streditcategories", " $streditcategories",
-                 "<a href=\"edit.php\">$streditingquiz</a> -> $streditcategories");
+/**
+* Initializes this classes general category-related variables
+*
+*/
+    function initialize() {
+        
+        /// Get the existing categories
+        if (!$this->categories = $this->get_quiz_categories(null, "parent, sortorder, name ASC")) {
+            unset($this->categories);
+            $defaultcategory = quiz_get_default_category($this->course->id);
+            if (!$defaultcategory) {
+                error("Error: Could not find or make a category!");
+            } else {
+                $this->categories[$defaultcategory->id] = $defaultcategory;
+                $this->defaultcategory = $defaultcategory->id;
+            }
+        } else {
+               /// Find lowest ID category for this course - this is the default category
+            $this->defaultcategory = 99999;
+            foreach ($this->categories as $category) {
+                if ($category->course == $this->course->id && $category->id < $this->defaultcategory) {
+                    $this->defaultcategory = $category->id;
+                }
+            }
+        }
+        
+        $this->categories = $this->arrange_categories($this->categories);
+        
+        // create the array of id=>full_name strings
+        $this->categorystrings = $this->expanded_category_strings($this->categories);
+    }
 
+    
+
+/**
+* Outputs a table to allow entry of a new category
+*
+*/
+    function output_new_table() {
+        $publishoptions[0] = get_string("no");
+        $publishoptions[1] = get_string("yes");
+        
+        $this->newtable->head  = array ($this->str->parent, $this->str->category, $this->str->categoryinfo, $this->str->publish, $this->str->action);
+        $this->newtable->width = 200;
+        $this->newtable->data[] = array();
+        $this->newtable->tablealign = 'left';
+        
+        /// Each section below adds a data cell to the table row
+        
+        
+        $viableparents[0] = $this->str->top;
+        $viableparents = $viableparents + $this->categorystrings;
+        $this->newtable->align['parent'] =  "left";
+        $this->newtable->wrap['parent'] = "nowrap";
+        $row['parent'] = choose_from_menu ($viableparents, "newparent", $this->str->top, "", "", "", true);
+        
+        $this->newtable->align['category'] =  "left";
+        $this->newtable->wrap['category'] = "nowrap";
+        $row['category'] = '<input type="text" name="newcategory" value="" size="15" />';
+        
+        $this->newtable->align['info'] =  "left";
+        $this->newtable->wrap['info'] = "nowrap";
+        $row['info'] = '<input type="text" name="newinfo" value="" size="50" />';
+        
+        $this->newtable->align['publish'] =  "left";
+        $this->newtable->wrap['publish'] = "nowrap";
+        $row['publish'] = choose_from_menu ($publishoptions, "newpublish", "", "", "", "", true);
+        
+        $this->newtable->align['action'] =  "left";
+        $this->newtable->wrap['action'] = "nowrap";
+        $row['action'] = '<input type="submit" value="' . $this->str->add . '" />';
+        
+        
+        $this->newtable->data[] = $row;
+        
+        // wrap the table in a form and output it
+        echo '<form action="category.php" method="post">';
+        echo '<input type="hidden" name="id" value="'. $this->course->id . '" />';
+        echo '<input type="hidden" name="addcategory" value="true" />';
+        echo make_table($this->newtable);
+        echo '</form>';
+    }
+    
+/**
+* Outputs a table to allow editing/rearranging of existing categories
+*
+* $this->initialize() must have already been called
+*
+* @param object course 
+*/
+    function output_edit_table() {
+        $this->edittable->head  = array ($this->str->course, $this->str->category, $this->str->categoryinfo, $this->str->questions, $this->str->publish, 
+                                    $this->str->delete, $this->str->order, $this->str->movecategoryto);
+        $this->edittable->width = 200;
+        $this->edittable->tablealign = 'left';
+        
+        // get list of short names to add to the course display.  Only necessary if user has admin view.
+        if (isadmin()) {
+            $keys = implode(',', $this->get_course_ids($this->categories));
+            $courses = get_records_select_menu('course', "id in ($keys)", '', 'id, shortname');
+        } else {
+            $courses = $this->course->shortname;
+        }
+        $this->build_edit_table_body($this->categories, $courses);
+        echo make_table($this->edittable);
+    }
+/**
+* Recursively builds up the edit-categories table body
+*
+* @param array categories contains category objects in  a tree representation
+* @param mixed courses String with shortname of course | array containing courseid=>shortname
+* @param int depth controls the indenting
+*/
+    function build_edit_table_body($categories, $courses, $depth = 0) {
+        $countcats = count($categories);
+        $count = 0;
+        $first = true;
+        $last = false;
+        
+        foreach ($categories as $category) {
+            $count++;
+            if ($count == $countcats) {
+                $last = true;
+            }
+            $up = $first ? false : true;
+            $down = $last ? false : true;
+            $first = false;
+            $courseshortname = is_string($courses) ? $courses : $courses[$category->course];
+            $this->quiz_edit_category_row($category, $courseshortname, $depth, $up, $down);
+            if (isset($category->children)) {
+                $this->build_edit_table_body($category->children, $courses, $depth + 1);
+            }
+        }
+    }
+    
+/**
+* gets all the courseids for the given categories
+*
+* @param array categories contains category objects in  a tree representation
+* @return array courseids flat array in form categoryid=>courseid
+*/
+    function get_course_ids($categories) {
+        $courseids = array();
+        foreach ($categories as $key=>$cat) {
+            $courseids[$key] = $cat->course;
+            if (!empty($cat->children)) {
+                $courseids = array_merge($courseids, $this->get_course_ids($cat->children));
+            }
+        }
+        return $courseids;
+    }
+    
+/**
+* Constructs each row of the edit-categories table
+*
+* @param object category
+* @param int depth controls the indenting
+* @param string shortname short name of the course
+* @param boolean up can it be moved up?
+* @param boolean down can it be moved down?
+*/
+    function quiz_edit_category_row($category, $shortname, $depth, $up = false, $down = false) {
+        $fill = str_repeat($this->tab, $depth); 
+        
+        $linkcss = $category->publish ? '' : ' class="dimmed"';
+        
+        /// Each section below adds a data cell to this table row
+        $this->edittable->align["$category->id.course"] =  "left";
+        $this->edittable->wrap["$category->id.course"] = "nowrap";
+        $row["$category->id.course"] = $shortname;
+        
+        $this->edittable->align["$category->id.name"] =  "left";
+        $this->edittable->wrap["$category->id.name"] = "nowrap";
+        $row["$category->id.name"] = '<a ' . $linkcss . 'title="' . $this->str->edit. '" href="category.php?id=' . $this->course->id . 
+            '&amp;edit=' . $category->id . '"><img src="' . $this->pixpath . '/t/edit.gif" height="11" width="11" border="0" 
+            alt="' .$this->str->edit. '" /> ' . $fill . $category->name . '</a>';
+        
+        $this->edittable->align["$category->id.info"] =  "left";
+        $this->edittable->wrap["$category->id.info"] = "nowrap";
+        $row["$category->id.info"] = '<a ' . $linkcss . 'title="' . $this->str->edit .'" href="category.php?id=' . $this->course->id . 
+            '&amp;edit=' . $category->id . '">' . $category->info . '</a>';
+        
+        $this->edittable->align["$category->id.qcount"] = "center";
+        $row["$category->id.qcount"] = $category->questioncount;
+        
+        $this->edittable->align["$category->id.publish"] =  "center";
+        $this->edittable->wrap["$category->id.publish"] = "nowrap";
+        if (!empty($category->publish)) {
+              $row["$category->id.publish"] = '<a title="' . $this->str->hide . '" href="category.php?id=' . $this->course->id . '&amp;hide=' . $category->id . 
+              '"><img src="' . $this->pixpath . '/t/hide.gif" height="11" width="11" border="0" alt="' .$this->str->hide. '" /></a> ';
+        } else {
+            $row["$category->id.publish"] = '<a title="' . $this->str->publish . '" href="category.php?id=' . $this->course->id . '&amp;publish=' . $category->id .
+                 '"><img src="' . $this->pixpath . '/t/show.gif" height="11" width="11" border="0" alt="' .$this->str->publish. '" /></a> ';
+        }
+        
+        if ($category->id != $this->defaultcategory) {
+            $this->edittable->align["$category->id.delete"] =  "center";
+            $this->edittable->wrap["$category->id.delete"] = "nowrap";
+            $row["$category->id.delete"] =  '<a title="' . $this->str->delete . '" href="category.php?id=' . $this->course->id . 
+                    '&amp;delete=' . $category->id . '"><img src="' . $this->pixpath . '/t/delete.gif" height="11" width="11" border="0" alt="' .$this->str->delete. '" /></a> ';
+        } else {
+            $row["$category->id.delete"] = '';
+        }
+             
+        $this->edittable->align["$category->id.order"] =  "left";
+        $this->edittable->wrap["$category->id.order"] = "nowrap";
+        $icons = '';
+        if ($up) {
+            $icons .= '<a title="' . $this->str->moveup .'" href="category.php?id=' . $this->course->id . '&amp;moveup=' . $category->id . '">
+                <img src="' . $this->pixpath . '/t/up.gif" height="11" width="11" border="0" alt="' . $this->str->moveup. '" /></a> ';
+        }
+        if ($down) {
+            $icons .= '<a title="' . $this->str->movedown .'" href="category.php?id=' . $this->course->id . '&amp;movedown=' . $category->id . '">
+                 <img src="' . $this->pixpath . '/t/down.gif" height="11" width="11" border="0" alt="' .$this->str->movedown. '" /></a> ';
+        }
+        $row["$category->id.order"]= $icons;
+        
+        $this->edittable->align["$category->id.moveto"] =  "left";
+        $this->edittable->wrap["$category->id.moveto"] = "nowrap";
+        if ($category->id != $this->defaultcategory) {
+            $viableparents = $this->categorystrings;
+            $this->set_viable_parents($viableparents, $category);
+            $viableparents = array(0=>$this->str->top) + $viableparents;
+        
+            $row["$category->id.moveto"] = popup_form ("category.php?id={$this->course->id}&amp;move={$category->id}&amp;moveto=", 
+               $viableparents, "moveform{$category->id}", "$category->parent", "", "", "", true);
+        } else {
+            $row["$category->id.moveto"]='---';
+        }
+        
+        
+        $this->edittable->data[$category->id] = $row;
+    }
 
-/// Delete category if the user wants to delete it
+    
+    function edit_single_category($categoryid) {
+    /// Interface for adding a new category
+        $this->initialize();
+
+        /// Interface for editing existing categories
+        if ($category = get_record("quiz_categories", "id", $categoryid)) {
+            echo '<h2 align="center">';
+            echo $this->str->edit;
+            helpbutton("categories_edit", $this->str->editcategory, "quiz");
+            echo '</h2>';
+            echo '<table width="100%"><tr><td>';
+            $this->output_edit_single_table($category);
+            echo '</td></tr></table>';
+            echo '<p><div align="center"><form action="category.php" method="get">
+                <input type="hidden" name="id" value="' . $this->course->id . '" />
+                <input type="submit" value="' . $this->str->cancel . '" /></form></div></p>';
+            print_footer($this->course);
+            exit;
+        } else {
+            error("Category $categoryid not found", "category.php?id={$this->course->id}");
+        }
+    }
+    
+    
+/**
+* Outputs a table to allow editing of an existing category
+*
+* @param object category
+*/
+    function output_edit_single_table($category) {
+         $publishoptions[0] = get_string("no");
+        $publishoptions[1] = get_string("yes");
+        $strupdate = get_string('update');
+        
+        unset ($edittable);
+
+        $edittable->head  = array ($this->str->parent, $this->str->category, $this->str->categoryinfo, $this->str->publish, $this->str->action);
+        $edittable->width = 200;
+        $edittable->data[] = array();
+        $edittable->tablealign = 'center';
+
+           /// Each section below adds a data cell to the table row
+
+        
+        $viableparents = $this->categorystrings;
+        $this->set_viable_parents($viableparents, $category);
+        $viableparents = array(0=>$this->str->top) + $viableparents;
+        $edittable->align['parent'] =  "left";
+        $edittable->wrap['parent'] = "nowrap";
+        $row['parent'] = choose_from_menu ($viableparents, "updateparent", "{$category->parent}", "", "", "", true);
+
+        $edittable->align['category'] =  "left";
+        $edittable->wrap['category'] = "nowrap";
+        $row['category'] = '<input type="text" name="updatename" value="' . $category->name . '" size="15" />';
+
+        $edittable->align['info'] =  "left";
+        $edittable->wrap['info'] = "nowrap";
+        $row['info'] = '<input type="text" name="updateinfo" value="' . $category->info . '" size="50" />';
+
+        $edittable->align['publish'] =  "left";
+        $edittable->wrap['publish'] = "nowrap";
+        $selected = (boolean)$category->publish ? 1 : 0;
+        $row['publish'] = choose_from_menu ($publishoptions, "updatepublish", $selected, "", "", "", true);
+
+        $edittable->align['action'] =  "left";
+        $edittable->wrap['action'] = "nowrap";
+        $row['action'] = '<input type="submit" value="' . $strupdate . '" />';
+
+        $edittable->data[] = $row;
+
+        // wrap the table in a form and output it
+        echo '<p><form action="category.php" method="post">';
+        echo '<input type="hidden" name="id" value="'. $this->course->id . '" />';
+        echo '<input type="hidden" name="updateid" value=' . $category->id . '" />';
+        echo make_table($edittable);
+        echo '</form></p>';
+    }
 
-    if (isset($delete) and !isset($cancel)) {
-        if (!$category = get_record("quiz_categories", "id", $delete)) {  // security
-            error("No such category $delete!");
+
+/**
+* Creates an array of "full-path" category strings
+* Structure:
+*    key => string
+*    where key is the category id, and string contains the name of all ancestors as well as the particular category name
+*   E.g. '123'=>'Language / English / Grammar / Modal Verbs"
+*
+* @param array $categories an array containing categories arranged in a tree structure
+*/
+    function expanded_category_strings($categories, $parent=null) {
+        $prefix = is_null($parent) ? '' : "$parent / ";
+        $categorystrings = array();
+        foreach ($categories as $key => $category) {
+            $expandedname = "$prefix$category->name";
+            $categorystrings[$key] = $expandedname;
+            if (isset($category->children)) {
+                $categorystrings = $categorystrings + $this->expanded_category_strings($category->children, $expandedname);
+            }
+        }
+        return $categorystrings;
+    }
+    
+    
+/**
+* Arranges the categories into a heirarchical tree
+*
+* If a category has children, it's "children" property holds an array of children
+* The questioncount for each category is also calculated
+*
+* @param    array records a flat list of the categories
+* @return   array categorytree a hierarchical list of the categories
+*/
+    function arrange_categories($records) {
+    //todo: get the question count for all records with one sql statement: select category, count(*) from quiz_questions group by category
+        $levels = array();
+    
+        // build a levels array, which places each record according to it's depth from the top level
+        $parents = array(0);
+        while (!empty($parents)) {
+            $children = array();
+            foreach ($records as $record) {
+                if (in_array($record->parent, $parents)) {
+                    $children[] = $record->id;
+                }
+            }
+            if (!empty($children)) {
+                $levels[] = $children;
+            }
+            $parents = $children;
+        }
+        // if there is no heirarchy (e.g., if all records have parent == 0), set level[0] to these keys 
+        if (empty($levels)) {
+            $levels[0] = array_keys($records);
+        }
+        
+        // build a heirarchical array that depicts the parent-child relationships of the categories
+        $categorytree = array();
+        for ($index = count($levels) - 1; $index >= 0; $index--) {
+            foreach($levels[$index] as $key) {
+                $parentkey = $records[$key]->parent;
+                if (!($records[$key]->questioncount = count_records('quiz_questions', 'category', $records[$key]->id))) {
+                    $records[$key]->questioncount = 0;
+                }
+                if ($parentkey == 0) {
+                    $categorytree[$key] = $records[$key];
+                } else {
+                    $records[$parentkey]->children[$key] = $records[$key];
+                }
+            }
+        }
+        return $categorytree;
+    }
+        
+    
+/**
+* Sets the viable parents
+*
+*  Viable parents are any except for the category itself, or any of it's descendants
+*  The parentstrings parameter is passed by reference and changed by this function.
+*
+* @param    array parentstrings a list of parentstrings
+* @param   object category 
+*/
+    function set_viable_parents(&$parentstrings, $category) {
+    
+        unset($parentstrings[$category->id]);
+        if (isset($category->children)) {
+            foreach ($category->children as $child) {
+                $this->set_viable_parents($parentstrings, $child);
+            }
+        }
+    }
+/**
+* Gets quiz categories
+*
+* @param    int parent - if given, restrict records to those with this parent id.  
+* @param    string sort - [[sortfield [,sortfield]] {ASC|DESC}]
+* @return   array categories
+*/
+    function get_quiz_categories($parent=null, $sort="sortorder ASC") {
+
+        $admin = isadmin();
+        if ($admin) {
+            if (is_null($parent)) {
+                $categories = get_records("quiz_categories", "", "", $sort);
+            } else {
+                $categories = get_records("quiz_categories", "parent", $parent, $sort);
+            }
+        } else {            
+            if (is_null($parent)) {
+                $categories = get_records('quiz_categories', 'course', "{$this->course->id}", $sort);
+            } else {
+                $select = "parent = '$parent' AND course = '{$this->course->id}'";
+                $categories = get_records_select('quiz_categories', $select, $sort);
+            }
+        }
+        return $categories;
+    }
+
+
+/**
+* Deletes an existing quiz category
+*
+* @param    int deletecat  id of category to delete
+* @param    int destcategoryid id of category which will inherit the orphans of deletecat
+*/
+    function delete_category($deletecat, $destcategoryid = null) {
+        
+        if (!$category = get_record("quiz_categories", "id", $deletecat)) {  // security
+            error("No such category $deletecat!", "category.php?id={$this->course->id}");
         }
 
-        if (isset($confirm)) { // Need to move some questions before deleting the category
-            if (!$category2 = get_record("quiz_categories", "id", $confirm)) {  // security
-                error("No such category $confirm!");
+        if (!is_null($destcategoryid)) { // Need to move some questions before deleting the category
+            if (!$category2 = get_record("quiz_categories", "id", $destcategoryid)) {  // security
+                error("No such category $destcategoryid!", "category.php?id={$this->course->id}");
             }
             if (! quiz_move_questions($category->id, $category2->id)) {
-                error("Error while moving questions from category '$category->name' to '$category2->name'");
+                error("Error while moving questions from category '$category->name' to '$category2->name'", "category.php?id={$this->course->id}");
             }
 
         } else {
             if ($count = count_records("quiz_questions", "category", $category->id)) {
                 $vars->name = $category->name;
                 $vars->count = $count;
-                print_simple_box(get_string("categorymove", "quiz", $vars), "CENTER");
-                $categories = quiz_get_category_menu($course->id);
-                unset($categories[$category->id]);
-                echo "<center><p><form action=\"category.php\" method=\"get\">";
-                echo "<input type=\"hidden\" name=\"id\" value=\"$course->id\" />";
+                print_simple_box(get_string("categorymove", "quiz", $vars), "center");
+                $this->initialize();
+                $categorystrings = $this->categorystrings;
+                unset ($categorystrings[$category->id]);
+                echo "<p><div align=\"center\"><form action=category.php method=get>";
+                echo "<input type=\"hidden\" name=\"id\" value=\"{$this->course->id}\" />";
                 echo "<input type=\"hidden\" name=\"delete\" value=\"$category->id\" />";
-                choose_from_menu($categories, "confirm", "", "");
-                echo "<input type=\"submit\" value=\"".get_string("categorymoveto", "quiz")."\" />";
-                echo "<input type=\"submit\" name=\"cancel\" value=\"$strcancel\" />";
-                echo "</form></p></center>";
-                print_footer($course);
+                choose_from_menu($categorystrings, "confirm", "", "");
+                echo "<input type=\"submit\" value=\"". get_string("categorymoveto", "quiz") . "\" />";
+                echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->str->cancel}\" />";
+                echo "</form></div></p>";
+                print_footer($this->course);
                 exit;
             }
         }
         delete_records("quiz_categories", "id", $category->id);
-        notify(get_string("categorydeleted", "", $category->name));
+        
+        /// Send the children categories to live with their grandparent
+        if ($childcats = get_records("quiz_categories", "parent", $category->id)) {
+            foreach ($childcats as $childcat) {
+                if (! set_field("quiz_categories", "parent", $category->parent, "id", $childcat->id)) {
+                    error("Could not update a child category!", "category.php?id={$this->course->id}");
+                }
+            }
+        }
+       
+        /// Finally delete the category itself
+        if (delete_records("quiz_categories", "id", $category->id)) {
+            notify(get_string("categorydeleted", "", $category->name), 'green');
+        }
     }
 
-/// Print heading
-
-    echo "<p align=\"center\"><font size=\"3\">";
-    echo $streditcategories;
-    helpbutton("categories", $streditcategories, "quiz");
-    echo "</font></p>";
-
-/// If data submitted, then process and store.
-
-    if ($form = data_submitted()) {
-
-        $form = (array)$form;
-
-        // Peel out all the data from variable names.
-        foreach ($form as $key => $val) {
-            $cat = NULL;
-            if ($key == "new" and $val != "") {
-                $cat->name = $val;
-                $cat->info = $form['newinfo'];
-                $cat->publish = $form['newpublish'];
-                $cat->course = $course->id;
-                $cat->stamp = make_unique_id_code();
-                if (!insert_record("quiz_categories", $cat)) {
-                    error("Could not insert the new quiz category '$val'");
-                } else {
-                    notify(get_string("categoryadded", "", $val));
+/**
+* Moves a category up or down in the display order
+*
+* @param    string direction  up|down
+* @param    int categoryid id of category to move
+*/
+    function move_category_up_down ($direction, $categoryid) {
+    /// Move a category up or down
+        $swapcategory = NULL;
+        $movecategory = NULL;
+
+        if ($direction == 'up') {
+            if ($movecategory = get_record("quiz_categories", "id", $categoryid)) {
+                $categories = $this->get_quiz_categories("$movecategory->parent", 'parent, sortorder, name');
+
+                foreach ($categories as $category) {
+                    if ($category->id == $movecategory->id) {
+                        break;
+                    }
+                    $swapcategory = $category;
                 }
-            
-            } else if (substr($key,0,1) == "c") {
-                $cat->id  = substr($key,1);
-                $cat->name = $val;
-                $cat->info = $form["i$cat->id"];
-                $cat->publish = $form["p$cat->id"];
-                $cat->course = $course->id;
-                if (!update_record("quiz_categories", $cat)) {
-                    error("Could not update the quiz category '$val'");
+            }
+        }
+        if ($direction == 'down') {
+            if ($movecategory = get_record("quiz_categories", "id", $categoryid)) {
+                $categories = $this->get_quiz_categories("$movecategory->parent", 'parent, sortorder, name');
+                $choosenext = false;
+                foreach ($categories as $category) {
+                    if ($choosenext) {
+                        $swapcategory = $category;
+                        break;
+                    }
+                    if ($category->id == $movecategory->id) {
+                        $choosenext = true;
+                    }
                 }
             }
         }
+        if ($swapcategory and $movecategory) {        // Renumber everything for robustness
+            $count=0;
+            foreach ($categories as $category) {
+                $count++;
+                if ($category->id == $swapcategory->id) {
+                    $category = $movecategory;
+                } else if ($category->id == $movecategory->id) {
+                    $category = $swapcategory;
+                }
+                if (! set_field("quiz_categories", "sortorder", $count, "id", $category->id)) {
+                    notify("Could not update that category!");
+                } 
+            }
+        } 
     }
 
-
-/// Get the existing categories
-    if (!$categories = get_records("quiz_categories", "course", $course->id, "id ASC")) {
-        unset($categories);
-        if (!$categories[] = quiz_get_default_category($course->id)) {
-            error("Error: Could not find or make a category!");
+/**
+* Changes the parent of a category
+*
+* @param    int categoryid 
+* @param    int parentid  
+*/
+    function move_category($categoryid, $parentid) {
+    /// Move a category to a new parent
+
+        if ($tempcat = get_record("quiz_categories", "id", $categoryid)) {
+            if ($tempcat->parent != $parentid) {
+                if (! set_field("quiz_categories", "parent", $parentid, "id", $tempcat->id)) {
+                    notify("Could not update that category!");
+                }
+            }
         }
     }
 
-
-/// Find lowest ID category - this is the default category
-    $default = 99999;
-    foreach ($categories as $category) {
-        if ($category->id < $default) {
-            $default = $category->id;
+/**
+* Changes the published status of a category
+*
+* @param    boolean publish  
+* @param    int categoryid 
+*/
+    function publish_category($publish, $categoryid) {
+    /// Hide or publish a category 
+
+        $publish = ($publish == false) ? 0 : 1;
+        $tempcat = get_record("quiz_categories", "id", $categoryid);
+        if ($tempcat) {
+            if (! set_field("quiz_categories", "publish", $publish, "id", $tempcat->id)) {
+                notify("Could not update that category!");
+            }
         }
     }
 
+/**
+* Creates a new category with given params
+*
+* @param    int newparent
+* @param    string newcategory  the name
+* @param    string newinfo 
+* @param    int newpublish
+* @param    int newcourse the id of the associated course
+*/
+    function add_category($newparent, $newcategory, $newinfo, $newpublish, $newcourse) {
+    
+        $cat = NULL;
+        $cat->parent = $newparent;
+        $cat->name = $newcategory;
+        $cat->info = $newinfo;
+        $cat->publish = $newpublish;
+        $cat->course = $newcourse;
+        $cat->sortorder = 999;
+        $cat->stamp = make_unique_id_code();
+        if (!insert_record("quiz_categories", $cat)) {
+            error("Could not insert the new quiz category '$newcategory'", "category.php?id={$newcourse}");
+        } else {
+            notify(get_string("categoryadded", "", $newcategory), 'green');
+        }
 
-    $publishoptions[0] = get_string("no");
-    $publishoptions[1] = get_string("yes");
-
-
-/// Print the table of all categories
-    $table->head  = array ($strcategory, $strcategoryinfo, $strpublish, $strquestions, $straction);
-    $table->align = array ("left", "left", "center", "center", "center");
-    $table->size = array ("80", "80", "40", "40", "50");
-    $table->width = 200;
-    $table->nowrap = true;
-
-    echo "<form action=\"category.php\" method=\"post\">";
-    foreach ($categories as $category) {
-        $count = count_records("quiz_questions", "category", $category->id);
-        if ($category->id == $default) { 
-            $delete = "";  // Can't delete default category
+    }
+    
+/**
+* Updates an existing category with given params
+*
+* @param    int updateid
+* @param    int updateparent
+* @param    string updatename
+* @param    string updateinfo 
+* @param    int updatepublish
+* @param    int courseid the id of the associated course
+*/
+    function update_category($updateid, $updateparent, $updatename, $updateinfo, $updatepublish, $courseid) {
+    
+        $cat = NULL;
+        $cat->id = $updateid;
+        $cat->parent = $updateparent;
+        $cat->name = $updatename;
+        $cat->info = $updateinfo;
+        $cat->publish = $updatepublish;
+        if (!update_record("quiz_categories", $cat)) {
+            error("Could not update the category '$updatename'", "category.php?id={$courseid}");
         } else {
-            $delete = "<a href=\"category.php?id=$course->id&amp;delete=$category->id\">$strdelete</a>";
-        }
-        $table->data[] = array ("<input type=\"text\" name=\"c$category->id\" value=\"$category->name\" size=\"15\" />",
-                                "<input type=\"text\" name=\"i$category->id\" value=\"$category->info\" size=\"50\" />",
-                                choose_from_menu ($publishoptions, "p$category->id", "$category->publish", "", "", "", true),
-                                "$count", 
-                                $delete);
-    }
-    $table->data[] = array ("<input type=\"text\" name=\"new\" value=\"\" size=\"15\" />", 
-                            "<input type=\"text\" name=\"newinfo\" value=\"\" size=\"50\" />", 
-                            choose_from_menu ($publishoptions, "newpublish", "", "", "", "", true),
-                            "", 
-                            "$stradd");
-    print_table($table);
-    echo "<input type=\"hidden\" name=\"id\" value=\"$course->id\" />";
-    echo "<center><br /><input type=\"submit\" value=\"$strsavechanges\" /> ";
-    echo "<br /><br /><input type=\"submit\" name=\"backtoquiz\" value=\"$strbacktoquiz\" /> ";
-    echo "</center>";
-    echo "</form>";
-
-    print_footer();
+            notify(get_string("categoryupdated", 'quiz'), 'green');
+        }
+    }
 
+}
 ?>
index a3b15f8d9e11973c6a71010a71f52ed090d9a181..ce3f8a7ffb2a1a56d7bf0b08e4496f9aedef8173 100644 (file)
@@ -296,7 +296,12 @@ function quiz_upgrade($oldversion) {
     if ($oldversion < 2004121400) {  // New field to determine popup window behaviour
         table_column("quiz", "", "popup", "integer", "4", "", "0", "not null", "subnet");
     }
-    
+
+    if ($oldversion < 2005010201) {
+        table_column('quiz_categories', '', 'parent');
+        table_column('quiz_categories', '', 'sortorder', '', '', '', '999');
+    }
+
     return true;
 }
 
index d881a43a722de0daf0cdd7fa50b7a9be66b42dd8..a99cb95d11d8ff7f4e05dee9e394a02278732d75 100644 (file)
@@ -119,6 +119,8 @@ CREATE TABLE `prefix_quiz_categories` (
   `info` text NOT NULL,
   `publish` tinyint(4) NOT NULL default '0',
   `stamp` varchar(255) NOT NULL default '',
+  `parent` int(10) unsigned NOT NULL default '0',
+  `sortorder` int(10) unsigned NOT NULL default '999',
   PRIMARY KEY  (`id`),
   KEY `course` (`course`)
 ) TYPE=MyISAM COMMENT='Categories are for grouping questions';
index 2d290078cab50c10a2b3261dfd1042526e0ab48b..874388c426c6dd36716b04beee45dd64f6427c68 100644 (file)
@@ -282,6 +282,11 @@ function quiz_upgrade($oldversion) {
         table_column("quiz", "", "popup", "integer", "4", "", "0", "not null", "subnet");
     }
 
+    if ($oldversion < 2005010201) {
+        table_column('quiz_categories', '', 'parent');
+        table_column('quiz_categories', '', 'sortorder', '', '', '', '999');
+    }
+
     return true;
 }
 
index f788d5ad64f32f626ffe81a2e9b0e8526041a596..ff3ca3b8bf0c0266cb2c7eb073d09cab90b3cc3b 100644 (file)
@@ -89,7 +89,9 @@ CREATE TABLE prefix_quiz_categories (
   name varchar(255) NOT NULL default '',
   info text NOT NULL default '',
   publish integer NOT NULL default '0',
-  stamp varchar(255) NOT NULL default ''
+  stamp varchar(255) NOT NULL default '',
+  parent integer NOT NULL default '0',
+  sortorder integer NOT NULL default '999',
 );
 
 CREATE INDEX prefix_quiz_categories_course_idx ON prefix_quiz_categories (course);
@@ -344,4 +346,3 @@ INSERT INTO prefix_log_display VALUES ('quiz', 'report', 'quiz', 'name');
 INSERT INTO prefix_log_display VALUES ('quiz', 'attempt', 'quiz', 'name');
 INSERT INTO prefix_log_display VALUES ('quiz', 'submit', 'quiz', 'name');
 INSERT INTO prefix_log_display VALUES ('quiz', 'review', 'quiz', 'name');
-
index ea6233e313e66afd5ed07522f70bc4ad70ed3fda..6afb62d47e695bc2e5fb76d7cf594ed1092c1e51 100644 (file)
@@ -42,6 +42,7 @@ define("QUIZ_PICTURE_MAX_WIDTH",  "600");   // Not currently implemented
 define("QUIZ_MAX_NUMBER_ANSWERS", "10");
 
 define("QUIZ_MAX_EVENT_LENGTH", "432000");   // 5 days maximum
+define("QUIZ_CATEGORIES_SORTORDER", "999");
 
 define('QUIZ_REVIEW_AFTER', 1);
 define('QUIZ_REVIEW_BEFORE', 2);
@@ -1105,6 +1106,8 @@ function quiz_get_default_category($courseid) {
     $category->name = get_string("default", "quiz");
     $category->info = get_string("defaultinfo", "quiz");
     $category->course = $courseid;
+    $category->parent = 0;
+    $category->sortorder = QUIZ_CATEGORIES_SORTORDER;
     $category->publish = 0;
     $category->stamp = make_unique_id_code();
 
@@ -1121,7 +1124,26 @@ function quiz_get_category_menu($courseid, $published=false) {
     if ($published) {
         $publish = "OR publish = '1'";
     }
-    return get_records_select_menu("quiz_categories", "course='$courseid' $publish", "name ASC", "id,name");
+    
+    if (!isadmin()) {
+        $categories = get_records_select("quiz_categories", "course = '$courseid' $publish", 'parent, sortorder, name ASC');
+    } else {
+        $categories = get_records_select("quiz_categories", '', 'parent, sortorder, name ASC');
+    }
+    if (!$categories) {
+        return false;
+    }
+    $categories = add_indented_names($categories);
+
+    foreach ($categories as $category) {
+       if ($catcourse = get_record("course", "id", $category->course)) {
+           if ($category->publish && ($category->course != $courseid)) {
+               $category->indentedname .= " ($catcourse->shortname)";
+           }
+           $catmenu[$category->id] = $category->indentedname;
+       }
+    }
+    return $catmenu;
 }
 
 function quiz_print_category_form($course, $current) {
@@ -1135,16 +1157,17 @@ function quiz_print_category_form($course, $current) {
     }
 
 /// Get all the existing categories now
-    if (!$categories = get_records_select("quiz_categories", "course = '$course->id' OR publish = '1'", "name ASC")) {
+    if (!$categories = get_records_select("quiz_categories", "course = '{$course->id}' OR publish = '1'", "parent, sortorder, name ASC")) {
         notify("Could not find any question categories!");
         return false;    // Something is really wrong
     }
+    $categories = add_indented_names($categories);
     foreach ($categories as $key => $category) {
        if ($catcourse = get_record("course", "id", $category->course)) {
-           if ($category->publish) {
-               $category->name .= " ($catcourse->shortname)";
+           if ($category->publish && $category->course != $course->id) {
+               $category->indentedname .= " ($catcourse->shortname)";
            }
-           $catmenu[$category->id] = $category->name;
+           $catmenu[$category->id] = $category->indentedname;
        }
     }
     $strcategory = get_string("category", "quiz");
@@ -1163,6 +1186,26 @@ function quiz_print_category_form($course, $current) {
     echo "</td></tr></table>";
 }
 
+
+function add_indented_names(&$categories, $id = 0, $indent = 0) {
+// returns the categories with their names indented to show parent-child relationships
+    $fillstr = '&nbsp;&nbsp;&nbsp;';
+ $fill = str_repeat($fillstr, $indent);
+    $children = array();
+    $keys = array_keys($categories);
+
+    foreach ($keys as $key) {
+        if (!isset($categories[$key]->processed) && $categories[$key]->parent == $id) {
+            $children[$key] = $categories[$key];
+            $children[$key]->indentedname = $fill . $children[$key]->name;
+            $categories[$key]->processed = true;
+            $children = $children + add_indented_names($categories, $children[$key]->id, $indent + 1); 
+        }
+    }
+    return $children;
+}
+
+
 function quiz_category_select_menu($courseid,$published=false,$only_editable=false,$selected="") {
 /// displays a select menu of categories with appended coursenames
 /// optionaly non editable categories may be excluded
@@ -1172,11 +1215,19 @@ function quiz_category_select_menu($courseid,$published=false,$only_editable=fal
     if ($published) {
         $publishsql = "or publish=1";
     }
-    $categories = get_records_select("quiz_categories","course=$courseid $publishsql");
+    
+    if (!isadmin()) {
+        $categories = get_records_select("quiz_categories","course=$courseid $publishsql", 'parent, sortorder, name ASC');
+    } else {
+        $categories = get_records_select("quiz_categories", '', 'parent, sortorder, name ASC');
+    }
+    
+    $categories = add_indented_names($categories);
+
     echo "<select name=\"category\">\n";
     foreach ($categories as $category) {
         $cid = $category->id;
-        $cname = quiz_get_category_coursename( $category );
+        $cname = quiz_get_category_coursename($category, $courseid);
         $seltxt = "";
         if ($cid==$selected) {
             $seltxt = "selected=\"selected\"";
@@ -1188,12 +1239,12 @@ function quiz_category_select_menu($courseid,$published=false,$only_editable=fal
     echo "</select>\n";
 }
 
-function quiz_get_category_coursename($category) {
-/// if the category is published, adds on the course
+function quiz_get_category_coursename($category, $courseid = 0) {
+/// if the category is not from this course and is published , adds on the course
 /// name
-    $cname=$category->name;
-    if ($category->publish) {
-        if ($catcourse=get_record("course","id",$category->id)) {
+    $cname = (isset($category->indentedname)) ? $category->indentedname : $category->name;
+    if ($category->course != $courseid && $category->publish) {
+        if ($catcourse=get_record("course","id",$category->course)) {
             $cname .= " ($catcourse->shortname) ";
         }
     }
index 6535ddc3af894ee5a028855fbd6072031aad93c7..9d272aba9555acf0bedd894cf2879ab953ecc693 100644 (file)
@@ -5,8 +5,8 @@
 //  This fragment is called by moodle_needs_upgrading() and /admin/index.php
 ////////////////////////////////////////////////////////////////////////////////
 
-$module->version  = 2004121400;   // The (date) version of this module
-$module->requires = 2004112300;   // Requires this Moodle version
+$module->version  = 2005010201;   // The (date) version of this module
+$module->requires = 2005010100;   // Requires this Moodle version
 $module->cron     = 0;            // How often should cron check this module (seconds)?
 
 ?>