[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/question/ -> category_class.php (source)

   1  <?php // $Id: category_class.php,v 1.32.2.7 2008/09/05 03:38:17 tjhunt Exp $
   2  /**
   3   * Class representing question categories
   4   *
   5   * @author Martin Dougiamas and many others. {@link http://moodle.org}
   6   * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
   7   * @package questionbank
   8   */
   9  
  10  // number of categories to display on page
  11  define("QUESTION_PAGE_LENGTH", 25);
  12  
  13  require_once("$CFG->libdir/listlib.php");
  14  require_once("$CFG->dirroot/question/category_form.php");
  15  require_once ('move_form.php');
  16  
  17  class question_category_list extends moodle_list {
  18      var $table = "question_categories";
  19      var $listitemclassname = 'question_category_list_item';
  20      /**
  21       * @var reference to list displayed below this one.
  22       */
  23      var $nextlist = null;
  24      /**
  25       * @var reference to list displayed above this one.
  26       */
  27      var $lastlist = null;
  28  
  29      var $context = null;
  30  
  31      function question_category_list($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $context = null){
  32          parent::moodle_list('ul', '', $editable, $pageurl, $page, 'cpage', $itemsperpage);
  33          $this->context = $context;
  34      }
  35  
  36      function get_records() {
  37          $this->records = get_categories_for_contexts($this->context->id, $this->sortby);
  38      }
  39      function process_actions($left, $right, $moveup, $movedown, $moveupcontext, $movedowncontext, $tocontext){
  40          global $CFG;
  41          //parent::procces_actions redirects after any action
  42          parent::process_actions($left, $right, $moveup, $movedown);
  43          if ($tocontext == $this->context->id){
  44              //only called on toplevel list
  45              if ($moveupcontext){
  46                  $cattomove = $moveupcontext;
  47                  $totop = 0;
  48              } elseif ($movedowncontext){
  49                  $cattomove = $movedowncontext;
  50                  $totop = 1;
  51              }
  52              $toparent = "0,{$this->context->id}";
  53              redirect($CFG->wwwroot.'/question/contextmove.php?'.
  54                  $this->pageurl->get_query_string(compact('cattomove', 'totop', 'toparent')));
  55          }
  56      }
  57  }
  58  
  59  class question_category_list_item extends list_item {
  60  
  61  
  62      function set_icon_html($first, $last, &$lastitem){
  63          global $CFG;
  64          $category = $this->item;
  65          $this->icons['edit']= $this->image_icon(get_string('editthiscategory'),
  66                  "{$CFG->wwwroot}/question/category.php?".$this->parentlist->pageurl->get_query_string(array('edit'=>$category->id)), 'edit');
  67          parent::set_icon_html($first, $last, $lastitem);
  68          $toplevel = ($this->parentlist->parentitem === null);//this is a top level item
  69          if (($this->parentlist->nextlist !== null) && $last && $toplevel && (count($this->parentlist->items)>1)){
  70              $this->icons['down'] = $this->image_icon(get_string('shareincontext', 'question', print_context_name($this->parentlist->nextlist->context)),
  71                  $this->parentlist->pageurl->out_action(array('movedowncontext'=>$this->id, 'tocontext'=>$this->parentlist->nextlist->context->id)), 'down');
  72          }
  73          if (($this->parentlist->lastlist !== null) && $first && $toplevel && (count($this->parentlist->items)>1)){
  74              $this->icons['up'] = $this->image_icon(get_string('shareincontext', 'question', print_context_name($this->parentlist->lastlist->context)),
  75                   $this->parentlist->pageurl->out_action(array('moveupcontext'=>$this->id, 'tocontext'=>$this->parentlist->lastlist->context->id)), 'up');
  76          }
  77      }
  78      function item_html($extraargs = array()){
  79          global $CFG;
  80          $pixpath = $CFG->pixpath;
  81          $str = $extraargs['str'];
  82          $category = $this->item;
  83  
  84          $editqestions = get_string('editquestions', 'quiz');
  85  
  86          /// Each section adds html to be displayed as part of this list item
  87          $questionbankurl = "{$CFG->wwwroot}/question/edit.php?".
  88                  $this->parentlist->pageurl->get_query_string(array('category'=>"$category->id,$category->contextid"));
  89          $catediturl = $this->parentlist->pageurl->out(false, array('edit'=>$this->id));
  90          $item = "<b><a title=\"{$str->edit}\" href=\"$catediturl\">".$category->name ."</a></b> <a title=\"$editqestions\" href=\"$questionbankurl\">".'('.$category->questioncount.')</a>';
  91  
  92          $item .= '&nbsp;'. $category->info;
  93  
  94          if (count($this->parentlist->records)!=1){ // don't allow delete if this is the last category in this context.
  95              $item .=  '<a title="' . $str->delete . '" href="'.$this->parentlist->pageurl->out_action(array('delete'=>$this->id)).'">
  96                      <img src="' . $pixpath . '/t/delete.gif" class="iconsmall" alt="' .$str->delete. '" /></a>';
  97          }
  98  
  99          return $item;
 100      }
 101  
 102  }
 103  
 104  
 105  /**
 106   * Class representing question categories
 107   *
 108   * @package questionbank
 109   */
 110  class question_category_object {
 111  
 112      var $str;
 113      var $pixpath;
 114      /**
 115       * Nested lists to display categories.
 116       *
 117       * @var array
 118       */
 119      var $editlists = array();
 120      var $newtable;
 121      var $tab;
 122      var $tabsize = 3;
 123  //------------------------------------------------------
 124      /**
 125       * @var moodle_url Object representing url for this page
 126       */
 127      var $pageurl;
 128      /**
 129       * @var question_category_edit_form Object representing form for adding / editing categories.
 130       */
 131      var $catform;
 132  
 133      /**
 134       * Constructor
 135       *
 136       * Gets necessary strings and sets relevant path information
 137       */
 138      function question_category_object($page, $pageurl, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
 139          global $CFG, $COURSE;
 140  
 141          $this->tab = str_repeat('&nbsp;', $this->tabsize);
 142  
 143          $this->str->course         = get_string('course');
 144          $this->str->category       = get_string('category', 'quiz');
 145          $this->str->categoryinfo   = get_string('categoryinfo', 'quiz');
 146          $this->str->questions      = get_string('questions', 'quiz');
 147          $this->str->add            = get_string('add');
 148          $this->str->delete         = get_string('delete');
 149          $this->str->moveup         = get_string('moveup');
 150          $this->str->movedown       = get_string('movedown');
 151          $this->str->edit           = get_string('editthiscategory');
 152          $this->str->hide           = get_string('hide');
 153          $this->str->publish        = get_string('publish', 'quiz');
 154          $this->str->order          = get_string('order');
 155          $this->str->parent         = get_string('parent', 'quiz');
 156          $this->str->add            = get_string('add');
 157          $this->str->action         = get_string('action');
 158          $this->str->top            = get_string('top', 'quiz');
 159          $this->str->addcategory    = get_string('addcategory', 'quiz');
 160          $this->str->editcategory   = get_string('editcategory', 'quiz');
 161          $this->str->cancel         = get_string('cancel');
 162          $this->str->editcategories = get_string('editcategories', 'quiz');
 163          $this->str->page           = get_string('page');
 164          $this->pixpath = $CFG->pixpath;
 165  
 166          $this->pageurl = $pageurl;
 167  
 168          $this->initialize($page, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts);
 169  
 170      }
 171  
 172  
 173  
 174      /**
 175       * Initializes this classes general category-related variables
 176       */
 177      function initialize($page, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
 178          $lastlist = null;
 179          foreach ($contexts as $context){
 180              $this->editlists[$context->id] = new question_category_list('ul', '', true, $this->pageurl, $page, 'cpage', QUESTION_PAGE_LENGTH, $context);
 181              $this->editlists[$context->id]->lastlist =& $lastlist;
 182              if ($lastlist!== null){
 183                  $lastlist->nextlist =& $this->editlists[$context->id];
 184              }
 185              $lastlist =& $this->editlists[$context->id];
 186          }
 187  
 188          $count = 1;
 189          $paged = false;
 190          foreach ($this->editlists as $key => $list){
 191              list($paged, $count) = $this->editlists[$key]->list_from_records($paged, $count);
 192          }
 193          $this->catform = new question_category_edit_form($this->pageurl, compact('contexts', 'currentcat'));
 194          if (!$currentcat){
 195              $this->catform->set_data(array('parent'=>$defaultcategory));
 196          }
 197      }
 198      /**
 199       * Displays the user interface
 200       *
 201       */
 202      function display_user_interface() {
 203  
 204          /// Interface for editing existing categories
 205          $this->output_edit_lists();
 206  
 207  
 208          echo '<br />';
 209          /// Interface for adding a new category:
 210          $this->output_new_table();
 211          echo '<br />';
 212  
 213      }
 214  
 215      /**
 216       * Outputs a table to allow entry of a new category
 217       */
 218      function output_new_table() {
 219          $this->catform->display();
 220      }
 221  
 222  
 223      /**
 224       * Outputs a list to allow editing/rearranging of existing categories
 225       *
 226       * $this->initialize() must have already been called
 227       *
 228       */
 229      function output_edit_lists() {
 230          print_heading_with_help(get_string('editcategories', 'quiz'), 'categories', 'question');
 231          foreach ($this->editlists as $context => $list){
 232              $listhtml = $list->to_html(0, array('str'=>$this->str));
 233              if ($listhtml){
 234                  print_box_start('boxwidthwide boxaligncenter generalbox questioncategories contextlevel' . $list->context->contextlevel);
 235                  print_heading(get_string('questioncatsfor', 'question', print_context_name(get_context_instance_by_id($context))), '', 3);
 236                  echo $listhtml;
 237                  print_box_end();
 238              }
 239          }
 240          echo $list->display_page_numbers();
 241       }
 242  
 243  
 244  
 245      /**
 246       * gets all the courseids for the given categories
 247       *
 248       * @param array categories contains category objects in  a tree representation
 249       * @return array courseids flat array in form categoryid=>courseid
 250       */
 251      function get_course_ids($categories) {
 252          $courseids = array();
 253          foreach ($categories as $key=>$cat) {
 254              $courseids[$key] = $cat->course;
 255              if (!empty($cat->children)) {
 256                  $courseids = array_merge($courseids, $this->get_course_ids($cat->children));
 257              }
 258          }
 259          return $courseids;
 260      }
 261  
 262  
 263  
 264      function edit_single_category($categoryid) {
 265      /// Interface for adding a new category
 266          global $COURSE;
 267          /// Interface for editing existing categories
 268          if ($category = get_record("question_categories", "id", $categoryid)) {
 269  
 270              $category->parent = "$category->parent,$category->contextid";
 271              $category->submitbutton = get_string('savechanges');
 272              $category->categoryheader = $this->str->edit;
 273              $this->catform->set_data($category);
 274              $this->catform->display();
 275          } else {
 276              error("Category $categoryid not found");
 277          }
 278      }
 279  
 280  
 281      /**
 282       * Sets the viable parents
 283       *
 284       *  Viable parents are any except for the category itself, or any of it's descendants
 285       *  The parentstrings parameter is passed by reference and changed by this function.
 286       *
 287       * @param    array parentstrings a list of parentstrings
 288       * @param   object category
 289       */
 290      function set_viable_parents(&$parentstrings, $category) {
 291  
 292          unset($parentstrings[$category->id]);
 293          if (isset($category->children)) {
 294              foreach ($category->children as $child) {
 295                  $this->set_viable_parents($parentstrings, $child);
 296              }
 297          }
 298      }
 299  
 300      /**
 301       * Gets question categories
 302       *
 303       * @param    int parent - if given, restrict records to those with this parent id.
 304       * @param    string sort - [[sortfield [,sortfield]] {ASC|DESC}]
 305       * @return   array categories
 306       */
 307      function get_question_categories($parent=null, $sort="sortorder ASC") {
 308          global $COURSE;
 309          if (is_null($parent)) {
 310              $categories = get_records('question_categories', 'course', "{$COURSE->id}", $sort);
 311          } else {
 312              $select = "parent = '$parent' AND course = '{$COURSE->id}'";
 313              $categories = get_records_select('question_categories', $select, $sort);
 314          }
 315          return $categories;
 316      }
 317  
 318      /**
 319       * Deletes an existing question category
 320       *
 321       * @param    int deletecat  id of category to delete
 322       */
 323      function delete_category($categoryid) {
 324          global $CFG;
 325          question_can_delete_cat($categoryid);
 326          if (!$category = get_record("question_categories", "id", $categoryid)) {  // security
 327              error("No such category $cat!", $this->pageurl->out());
 328          }
 329          /// Send the children categories to live with their grandparent
 330          if (!set_field("question_categories", "parent", $category->parent, "parent", $category->id)) {
 331              error("Could not update a child category!", $this->pageurl->out());
 332          }
 333  
 334          /// Finally delete the category itself
 335          if (delete_records("question_categories", "id", $category->id)) {
 336              notify(get_string("categorydeleted", "quiz", format_string($category->name)), 'notifysuccess');
 337              redirect($this->pageurl->out());//always redirect after successful action
 338          }
 339      }
 340      function move_questions_and_delete_category($oldcat, $newcat){
 341          question_can_delete_cat($oldcat);
 342          $this->move_questions($oldcat, $newcat);
 343          $this->delete_category($oldcat);
 344      }
 345  
 346      function display_move_form($questionsincategory, $category){
 347          $vars = new stdClass;
 348          $vars->name = $category->name;
 349          $vars->count = $questionsincategory;
 350          print_simple_box(get_string("categorymove", "quiz", $vars), "center");
 351          $this->moveform->display();
 352      }
 353  
 354      function move_questions($oldcat, $newcat){
 355          $questionids = get_records_select_menu('question', "category = $oldcat AND (parent = 0 OR parent = id)", '', 'id,1');
 356          if (!question_move_questions_to_category(implode(',', array_keys($questionids)), $newcat)) {
 357              print_error('errormovingquestions', 'question', $returnurl, $ids);
 358          }
 359      }
 360  
 361      /**
 362       * Creates a new category with given params
 363       *
 364       */
 365      function add_category($newparent, $newcategory, $newinfo) {
 366          if (empty($newcategory)) {
 367              print_error('categorynamecantbeblank', 'quiz');
 368          }
 369          list($parentid, $contextid) = explode(',', $newparent);
 370          //moodle_form makes sure select element output is legal no need for further cleaning
 371          require_capability('moodle/question:managecategory', get_context_instance_by_id($contextid));
 372  
 373          if ($parentid) {
 374              if(!(get_field('question_categories', 'contextid', 'id', $parentid) == $contextid)) {
 375                  error("Could not insert the new question category '$newcategory' illegal contextid '$contextid'.");
 376              }
 377          }
 378  
 379          $cat = new object();
 380          $cat->parent = $parentid;
 381          $cat->contextid = $contextid;
 382          $cat->name = $newcategory;
 383          $cat->info = $newinfo;
 384          $cat->sortorder = 999;
 385          $cat->stamp = make_unique_id_code();
 386          if (!insert_record("question_categories", $cat)) {
 387              error("Could not insert the new question category '$newcategory'");
 388          } else {
 389              redirect($this->pageurl->out());//always redirect after successful action
 390          }
 391      }
 392  
 393      /**
 394       * Updates an existing category with given params
 395       *
 396       */
 397      function update_category($updateid, $newparent, $newname, $newinfo) {
 398          global $CFG, $QTYPES;
 399          if (empty($newname)) {
 400              print_error('categorynamecantbeblank', 'quiz');
 401          }
 402  
 403          list($parentid, $tocontextid) = explode(',', $newparent);
 404  
 405          $oldcat = get_record('question_categories', 'id', $updateid);
 406          $fromcontext = get_context_instance_by_id($oldcat->contextid);
 407          require_capability('moodle/question:managecategory', $fromcontext);
 408          if ($oldcat->contextid == $tocontextid){
 409              $tocontext = get_context_instance_by_id($tocontextid);
 410              require_capability('moodle/question:managecategory', $tocontext);
 411          }
 412          $cat = NULL;
 413          $cat->id = $updateid;
 414          $cat->name = $newname;
 415          $cat->info = $newinfo;
 416          //never move category where it is the default
 417          if (1 != count_records_sql("SELECT count(*) FROM {$CFG->prefix}question_categories c1, {$CFG->prefix}question_categories c2 WHERE c2.id = $updateid AND c1.contextid = c2.contextid")){
 418              // If the question name has changed, rename any random questions in that category.
 419              if (addslashes($oldcat->name) != $cat->name) {
 420                  $randomqname = $QTYPES[RANDOM]->question_name($cat);
 421                  set_field('question', 'name', addslashes($randomqname), 'category', $cat->id, 'qtype', RANDOM);
 422                  // Ignore errors here. It is not a big deal if the questions are not renamed.
 423              }
 424  
 425              // Then update the category itself.
 426              if ($oldcat->contextid == $tocontextid){ // not moving contexts
 427                  $cat->parent = $parentid;
 428                  if (!update_record("question_categories", $cat)) {
 429                      error("Could not update the category '$newname'", $this->pageurl->out());
 430                  } else {
 431                      redirect($this->pageurl->out());
 432                  }
 433              } else {
 434                  if (!update_record("question_categories", $cat)) {
 435                      error("Could not update the category '$newname'", $this->pageurl->out());
 436                  } else {
 437                      redirect($CFG->wwwroot.'/question/contextmove.php?'.
 438                                  $this->pageurl->get_query_string(array('cattomove' => $updateid,
 439                                                                          'toparent'=>$newparent)));
 440                  }
 441              }
 442          } else {
 443              error("Cannot move the category '$newname'. It is the last in this context.", $this->pageurl->out());
 444          }
 445      }
 446  
 447      function move_question_from_cat_confirm($fromcat, $fromcourse, $tocat=null, $question=null){
 448          global $QTYPES;
 449          if (!$question){
 450              $questions[] = $question;
 451          } else {
 452              $questions = get_records('question', 'category', $tocat->id);
 453          }
 454          $urls = array();
 455          foreach ($questions as $question){
 456              $urls = array_merge($urls, $QTYPES[$question->qtype]->find_file_links_in_question($question));
 457          }
 458          if ($fromcourse){
 459              $append = 'tocourse';
 460          } else {
 461              $append = 'tosite';
 462          }
 463          if ($tocat){
 464              echo '<p>'.get_string('needtomovethesefilesincat','question').'</p>';
 465          } else {
 466              echo '<p>'.get_string('needtomovethesefilesinquestion','question').'</p>';
 467          }
 468      }
 469  
 470  
 471  
 472  
 473  }
 474  
 475  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7