[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/question/ -> category_class.php (source)

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  
  17  /**
  18   * A class for representing question categories.
  19   *
  20   * @package    moodlecore
  21   * @subpackage questionbank
  22   * @copyright  1999 onwards Martin Dougiamas {@link http://moodle.com}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  // number of categories to display on page
  30  define('QUESTION_PAGE_LENGTH', 25);
  31  
  32  require_once($CFG->libdir . '/listlib.php');
  33  require_once($CFG->dirroot . '/question/category_form.php');
  34  require_once($CFG->dirroot . '/question/move_form.php');
  35  
  36  
  37  /**
  38   * Class representing a list of question categories
  39   *
  40   * @copyright  1999 onwards Martin Dougiamas {@link http://moodle.com}
  41   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  42   */
  43  class question_category_list extends moodle_list {
  44      public $table = "question_categories";
  45      public $listitemclassname = 'question_category_list_item';
  46      /**
  47       * @var reference to list displayed below this one.
  48       */
  49      public $nextlist = null;
  50      /**
  51       * @var reference to list displayed above this one.
  52       */
  53      public $lastlist = null;
  54  
  55      public $context = null;
  56      public $sortby = 'parent, sortorder, name';
  57  
  58      public function __construct($type='ul', $attributes='', $editable = false, $pageurl=null, $page = 0, $pageparamname = 'page', $itemsperpage = 20, $context = null){
  59          parent::__construct('ul', '', $editable, $pageurl, $page, 'cpage', $itemsperpage);
  60          $this->context = $context;
  61      }
  62  
  63      public function get_records() {
  64          $this->records = get_categories_for_contexts($this->context->id, $this->sortby);
  65      }
  66  }
  67  
  68  
  69  /**
  70   * An item in a list of question categories.
  71   *
  72   * @copyright  1999 onwards Martin Dougiamas {@link http://moodle.com}
  73   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  74   */
  75  class question_category_list_item extends list_item {
  76      public function set_icon_html($first, $last, $lastitem){
  77          global $CFG;
  78          $category = $this->item;
  79          $url = new moodle_url('/question/category.php', ($this->parentlist->pageurl->params() + array('edit'=>$category->id)));
  80          $this->icons['edit']= $this->image_icon(get_string('editthiscategory', 'question'), $url, 'edit');
  81          parent::set_icon_html($first, $last, $lastitem);
  82          $toplevel = ($this->parentlist->parentitem === null);//this is a top level item
  83          if (($this->parentlist->nextlist !== null) && $last && $toplevel && (count($this->parentlist->items)>1)){
  84              $url = new moodle_url($this->parentlist->pageurl, array('movedowncontext'=>$this->id, 'tocontext'=>$this->parentlist->nextlist->context->id, 'sesskey'=>sesskey()));
  85              $this->icons['down'] = $this->image_icon(
  86                  get_string('shareincontext', 'question', $this->parentlist->nextlist->context->get_context_name()), $url, 'down');
  87          }
  88          if (($this->parentlist->lastlist !== null) && $first && $toplevel && (count($this->parentlist->items)>1)){
  89              $url = new moodle_url($this->parentlist->pageurl, array('moveupcontext'=>$this->id, 'tocontext'=>$this->parentlist->lastlist->context->id, 'sesskey'=>sesskey()));
  90              $this->icons['up'] = $this->image_icon(
  91                  get_string('shareincontext', 'question', $this->parentlist->lastlist->context->get_context_name()), $url, 'up');
  92          }
  93      }
  94  
  95      public function item_html($extraargs = array()){
  96          global $CFG, $OUTPUT;
  97          $str = $extraargs['str'];
  98          $category = $this->item;
  99  
 100          $editqestions = get_string('editquestions', 'question');
 101  
 102          // Each section adds html to be displayed as part of this list item.
 103          $questionbankurl = new moodle_url('/question/edit.php', $this->parentlist->pageurl->params());
 104          $questionbankurl->param('cat', $category->id . ',' . $category->contextid);
 105          $catediturl = new moodle_url($this->parentlist->pageurl, array('edit' => $this->id));
 106          $item = '';
 107          $item .= html_writer::tag('b', html_writer::link($catediturl,
 108                  format_string($category->name, true, array('context' => $this->parentlist->context)),
 109                  array('title' => $str->edit))) . ' ';
 110          $item .= html_writer::link($questionbankurl, '(' . $category->questioncount . ')',
 111                  array('title' => $editqestions)) . ' ';
 112          $item .= format_text($category->info, $category->infoformat,
 113                  array('context' => $this->parentlist->context, 'noclean' => true));
 114  
 115          // don't allow delete if this is the last category in this context.
 116          if (!question_is_only_toplevel_category_in_context($category->id)) {
 117              $deleteurl = new moodle_url($this->parentlist->pageurl, array('delete' => $this->id, 'sesskey' => sesskey()));
 118              $item .= html_writer::link($deleteurl,
 119                      html_writer::empty_tag('img', array('src' => $OUTPUT->pix_url('t/delete'),
 120                              'class' => 'iconsmall', 'alt' => $str->delete)),
 121                      array('title' => $str->delete));
 122          }
 123  
 124          return $item;
 125      }
 126  }
 127  
 128  
 129  /**
 130   * Class representing q question category
 131   *
 132   * @copyright  1999 onwards Martin Dougiamas {@link http://moodle.com}
 133   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 134   */
 135  class question_category_object {
 136  
 137      /**
 138       * @var array common language strings.
 139       */
 140      public $str;
 141  
 142      /**
 143       * @var array nested lists to display categories.
 144       */
 145      public $editlists = array();
 146      public $newtable;
 147      public $tab;
 148      public $tabsize = 3;
 149  
 150      /**
 151       * @var moodle_url Object representing url for this page
 152       */
 153      public $pageurl;
 154  
 155      /**
 156       * @var question_category_edit_form Object representing form for adding / editing categories.
 157       */
 158      public $catform;
 159  
 160      /**
 161       * Constructor
 162       *
 163       * Gets necessary strings and sets relevant path information
 164       */
 165      public function __construct($page, $pageurl, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
 166          global $CFG, $COURSE, $OUTPUT;
 167  
 168          $this->tab = str_repeat('&nbsp;', $this->tabsize);
 169  
 170          $this->str = new stdClass();
 171          $this->str->course         = get_string('course');
 172          $this->str->category       = get_string('category', 'question');
 173          $this->str->categoryinfo   = get_string('categoryinfo', 'question');
 174          $this->str->questions      = get_string('questions', 'question');
 175          $this->str->add            = get_string('add');
 176          $this->str->delete         = get_string('delete');
 177          $this->str->moveup         = get_string('moveup');
 178          $this->str->movedown       = get_string('movedown');
 179          $this->str->edit           = get_string('editthiscategory', 'question');
 180          $this->str->hide           = get_string('hide');
 181          $this->str->order          = get_string('order');
 182          $this->str->parent         = get_string('parent', 'question');
 183          $this->str->add            = get_string('add');
 184          $this->str->action         = get_string('action');
 185          $this->str->top            = get_string('top');
 186          $this->str->addcategory    = get_string('addcategory', 'question');
 187          $this->str->editcategory   = get_string('editcategory', 'question');
 188          $this->str->cancel         = get_string('cancel');
 189          $this->str->editcategories = get_string('editcategories', 'question');
 190          $this->str->page           = get_string('page');
 191  
 192          $this->pageurl = $pageurl;
 193  
 194          $this->initialize($page, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts);
 195      }
 196  
 197      /**
 198       * Old syntax of class constructor. Deprecated in PHP7.
 199       *
 200       * @deprecated since Moodle 3.1
 201       */
 202      public function question_category_object($page, $pageurl, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
 203          debugging('Use of class name as constructor is deprecated', DEBUG_DEVELOPER);
 204          self::__construct($page, $pageurl, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts);
 205      }
 206  
 207      /**
 208       * Initializes this classes general category-related variables
 209       */
 210      public function initialize($page, $contexts, $currentcat, $defaultcategory, $todelete, $addcontexts) {
 211          $lastlist = null;
 212          foreach ($contexts as $context){
 213              $this->editlists[$context->id] = new question_category_list('ul', '', true, $this->pageurl, $page, 'cpage', QUESTION_PAGE_LENGTH, $context);
 214              $this->editlists[$context->id]->lastlist =& $lastlist;
 215              if ($lastlist!== null){
 216                  $lastlist->nextlist =& $this->editlists[$context->id];
 217              }
 218              $lastlist =& $this->editlists[$context->id];
 219          }
 220  
 221          $count = 1;
 222          $paged = false;
 223          foreach ($this->editlists as $key => $list){
 224              list($paged, $count) = $this->editlists[$key]->list_from_records($paged, $count);
 225          }
 226          $this->catform = new question_category_edit_form($this->pageurl, compact('contexts', 'currentcat'));
 227          if (!$currentcat){
 228              $this->catform->set_data(array('parent'=>$defaultcategory));
 229          }
 230      }
 231  
 232      /**
 233       * Displays the user interface
 234       *
 235       */
 236      public function display_user_interface() {
 237  
 238          /// Interface for editing existing categories
 239          $this->output_edit_lists();
 240  
 241  
 242          echo '<br />';
 243          /// Interface for adding a new category:
 244          $this->output_new_table();
 245          echo '<br />';
 246  
 247      }
 248  
 249      /**
 250       * Outputs a table to allow entry of a new category
 251       */
 252      public function output_new_table() {
 253          $this->catform->display();
 254      }
 255  
 256      /**
 257       * Outputs a list to allow editing/rearranging of existing categories
 258       *
 259       * $this->initialize() must have already been called
 260       *
 261       */
 262      public function output_edit_lists() {
 263          global $OUTPUT;
 264  
 265          echo $OUTPUT->heading_with_help(get_string('editcategories', 'question'), 'editcategories', 'question');
 266  
 267          foreach ($this->editlists as $context => $list){
 268              $listhtml = $list->to_html(0, array('str'=>$this->str));
 269              if ($listhtml){
 270                  echo $OUTPUT->box_start('boxwidthwide boxaligncenter generalbox questioncategories contextlevel' . $list->context->contextlevel);
 271                  $fullcontext = context::instance_by_id($context);
 272                  echo $OUTPUT->heading(get_string('questioncatsfor', 'question', $fullcontext->get_context_name()), 3);
 273                  echo $listhtml;
 274                  echo $OUTPUT->box_end();
 275              }
 276          }
 277          echo $list->display_page_numbers();
 278       }
 279  
 280      /**
 281       * gets all the courseids for the given categories
 282       *
 283       * @param array categories contains category objects in  a tree representation
 284       * @return array courseids flat array in form categoryid=>courseid
 285       */
 286      public function get_course_ids($categories) {
 287          $courseids = array();
 288          foreach ($categories as $key=>$cat) {
 289              $courseids[$key] = $cat->course;
 290              if (!empty($cat->children)) {
 291                  $courseids = array_merge($courseids, $this->get_course_ids($cat->children));
 292              }
 293          }
 294          return $courseids;
 295      }
 296  
 297      public function edit_single_category($categoryid) {
 298      /// Interface for adding a new category
 299          global $COURSE, $DB;
 300          /// Interface for editing existing categories
 301          if ($category = $DB->get_record("question_categories", array("id" => $categoryid))) {
 302  
 303              $category->parent = "{$category->parent},{$category->contextid}";
 304              $category->submitbutton = get_string('savechanges');
 305              $category->categoryheader = $this->str->edit;
 306              $this->catform->set_data($category);
 307              $this->catform->display();
 308          } else {
 309              print_error('invalidcategory', '', '', $categoryid);
 310          }
 311      }
 312  
 313      /**
 314       * Sets the viable parents
 315       *
 316       *  Viable parents are any except for the category itself, or any of it's descendants
 317       *  The parentstrings parameter is passed by reference and changed by this function.
 318       *
 319       * @param    array parentstrings a list of parentstrings
 320       * @param   object category
 321       */
 322      public function set_viable_parents(&$parentstrings, $category) {
 323  
 324          unset($parentstrings[$category->id]);
 325          if (isset($category->children)) {
 326              foreach ($category->children as $child) {
 327                  $this->set_viable_parents($parentstrings, $child);
 328              }
 329          }
 330      }
 331  
 332      /**
 333       * Gets question categories
 334       *
 335       * @param    int parent - if given, restrict records to those with this parent id.
 336       * @param    string sort - [[sortfield [,sortfield]] {ASC|DESC}]
 337       * @return   array categories
 338       */
 339      public function get_question_categories($parent=null, $sort="sortorder ASC") {
 340          global $COURSE, $DB;
 341          if (is_null($parent)) {
 342              $categories = $DB->get_records('question_categories', array('course' => $COURSE->id), $sort);
 343          } else {
 344              $select = "parent = ? AND course = ?";
 345              $categories = $DB->get_records_select('question_categories', $select, array($parent, $COURSE->id), $sort);
 346          }
 347          return $categories;
 348      }
 349  
 350      /**
 351       * Deletes an existing question category
 352       *
 353       * @param int deletecat id of category to delete
 354       */
 355      public function delete_category($categoryid) {
 356          global $CFG, $DB;
 357          question_can_delete_cat($categoryid);
 358          if (!$category = $DB->get_record("question_categories", array("id" => $categoryid))) {  // security
 359              print_error('unknowcategory');
 360          }
 361          /// Send the children categories to live with their grandparent
 362          $DB->set_field("question_categories", "parent", $category->parent, array("parent" => $category->id));
 363  
 364          /// Finally delete the category itself
 365          $DB->delete_records("question_categories", array("id" => $category->id));
 366      }
 367  
 368      public function move_questions_and_delete_category($oldcat, $newcat){
 369          question_can_delete_cat($oldcat);
 370          $this->move_questions($oldcat, $newcat);
 371          $this->delete_category($oldcat);
 372      }
 373  
 374      public function display_move_form($questionsincategory, $category){
 375          global $OUTPUT;
 376          $vars = new stdClass();
 377          $vars->name = $category->name;
 378          $vars->count = $questionsincategory;
 379          echo $OUTPUT->box(get_string('categorymove', 'question', $vars), 'generalbox boxaligncenter');
 380          $this->moveform->display();
 381      }
 382  
 383      public function move_questions($oldcat, $newcat){
 384          global $DB;
 385          $questionids = $DB->get_records_select_menu('question',
 386                  'category = ? AND (parent = 0 OR parent = id)', array($oldcat), '', 'id,1');
 387          question_move_questions_to_category(array_keys($questionids), $newcat);
 388      }
 389  
 390      /**
 391       * Creates a new category with given params
 392       */
 393      public function add_category($newparent, $newcategory, $newinfo, $return = false, $newinfoformat = FORMAT_HTML) {
 394          global $DB;
 395          if (empty($newcategory)) {
 396              print_error('categorynamecantbeblank', 'question');
 397          }
 398          list($parentid, $contextid) = explode(',', $newparent);
 399          //moodle_form makes sure select element output is legal no need for further cleaning
 400          require_capability('moodle/question:managecategory', context::instance_by_id($contextid));
 401  
 402          if ($parentid) {
 403              if(!($DB->get_field('question_categories', 'contextid', array('id' => $parentid)) == $contextid)) {
 404                  print_error('cannotinsertquestioncatecontext', 'question', '', array('cat'=>$newcategory, 'ctx'=>$contextid));
 405              }
 406          }
 407  
 408          $cat = new stdClass();
 409          $cat->parent = $parentid;
 410          $cat->contextid = $contextid;
 411          $cat->name = $newcategory;
 412          $cat->info = $newinfo;
 413          $cat->infoformat = $newinfoformat;
 414          $cat->sortorder = 999;
 415          $cat->stamp = make_unique_id_code();
 416          $categoryid = $DB->insert_record("question_categories", $cat);
 417  
 418          // Log the creation of this category.
 419          $params = array(
 420              'objectid' => $categoryid,
 421              'contextid' => $contextid
 422          );
 423          $event = \core\event\question_category_created::create($params);
 424          $event->trigger();
 425  
 426          if ($return) {
 427              return $categoryid;
 428          } else {
 429              redirect($this->pageurl);//always redirect after successful action
 430          }
 431      }
 432  
 433      /**
 434       * Updates an existing category with given params
 435       */
 436      public function update_category($updateid, $newparent, $newname, $newinfo, $newinfoformat = FORMAT_HTML) {
 437          global $CFG, $DB;
 438          if (empty($newname)) {
 439              print_error('categorynamecantbeblank', 'question');
 440          }
 441  
 442          // Get the record we are updating.
 443          $oldcat = $DB->get_record('question_categories', array('id' => $updateid));
 444          $lastcategoryinthiscontext = question_is_only_toplevel_category_in_context($updateid);
 445  
 446          if (!empty($newparent) && !$lastcategoryinthiscontext) {
 447              list($parentid, $tocontextid) = explode(',', $newparent);
 448          } else {
 449              $parentid = $oldcat->parent;
 450              $tocontextid = $oldcat->contextid;
 451          }
 452  
 453          // Check permissions.
 454          $fromcontext = context::instance_by_id($oldcat->contextid);
 455          require_capability('moodle/question:managecategory', $fromcontext);
 456  
 457          // If moving to another context, check permissions some more.
 458          if ($oldcat->contextid != $tocontextid) {
 459              $tocontext = context::instance_by_id($tocontextid);
 460              require_capability('moodle/question:managecategory', $tocontext);
 461          }
 462  
 463          // Update the category record.
 464          $cat = new stdClass();
 465          $cat->id = $updateid;
 466          $cat->name = $newname;
 467          $cat->info = $newinfo;
 468          $cat->infoformat = $newinfoformat;
 469          $cat->parent = $parentid;
 470          $cat->contextid = $tocontextid;
 471          $DB->update_record('question_categories', $cat);
 472  
 473          // If the category name has changed, rename any random questions in that category.
 474          if ($oldcat->name != $cat->name) {
 475              $where = "qtype = 'random' AND category = ? AND " . $DB->sql_compare_text('questiontext') . " = ?";
 476  
 477              $randomqtype = question_bank::get_qtype('random');
 478              $randomqname = $randomqtype->question_name($cat, false);
 479              $DB->set_field_select('question', 'name', $randomqname, $where, array($cat->id, '0'));
 480  
 481              $randomqname = $randomqtype->question_name($cat, true);
 482              $DB->set_field_select('question', 'name', $randomqname, $where, array($cat->id, '1'));
 483          }
 484  
 485          if ($oldcat->contextid != $tocontextid) {
 486              // Moving to a new context. Must move files belonging to questions.
 487              question_move_category_to_context($cat->id, $oldcat->contextid, $tocontextid);
 488          }
 489  
 490          // Cat param depends on the context id, so update it.
 491          $this->pageurl->param('cat', $updateid . ',' . $tocontextid);
 492          redirect($this->pageurl);
 493      }
 494  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1