Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]

   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   * Defines the custom question bank view used on the Edit quiz page.
  19   *
  20   * @package   mod_quiz
  21   * @category  question
  22   * @copyright 1999 onwards Martin Dougiamas and others {@link http://moodle.com}
  23   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace mod_quiz\question\bank;
  27  
  28  use coding_exception;
  29  
  30  /**
  31   * Subclass to customise the view of the question bank for the quiz editing screen.
  32   *
  33   * @copyright  2009 Tim Hunt
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class custom_view extends \core_question\bank\view {
  37      /** @var bool whether the quiz this is used by has been attemptd. */
  38      protected $quizhasattempts = false;
  39      /** @var \stdClass the quiz settings. */
  40      protected $quiz = false;
  41      /** @var int The maximum displayed length of the category info. */
  42      const MAX_TEXT_LENGTH = 200;
  43  
  44      /**
  45       * Constructor
  46       * @param \question_edit_contexts $contexts
  47       * @param \moodle_url $pageurl
  48       * @param \stdClass $course course settings
  49       * @param \stdClass $cm activity settings.
  50       * @param \stdClass $quiz quiz settings.
  51       */
  52      public function __construct($contexts, $pageurl, $course, $cm, $quiz) {
  53          parent::__construct($contexts, $pageurl, $course, $cm);
  54          $this->quiz = $quiz;
  55      }
  56  
  57      protected function wanted_columns() {
  58          global $CFG;
  59  
  60          if (empty($CFG->quizquestionbankcolumns)) {
  61              $quizquestionbankcolumns = array(
  62                  'add_action_column',
  63                  'checkbox_column',
  64                  'question_type_column',
  65                  'question_name_text_column',
  66                  'preview_action_column',
  67              );
  68          } else {
  69              $quizquestionbankcolumns = explode(',', $CFG->quizquestionbankcolumns);
  70          }
  71  
  72          foreach ($quizquestionbankcolumns as $fullname) {
  73              if (!class_exists($fullname)) {
  74                  if (class_exists('mod_quiz\\question\\bank\\' . $fullname)) {
  75                      $fullname = 'mod_quiz\\question\\bank\\' . $fullname;
  76                  } else if (class_exists('core_question\\bank\\' . $fullname)) {
  77                      $fullname = 'core_question\\bank\\' . $fullname;
  78                  } else if (class_exists('question_bank_' . $fullname)) {
  79                      debugging('Legacy question bank column class question_bank_' .
  80                              $fullname . ' should be renamed to mod_quiz\\question\\bank\\' .
  81                              $fullname, DEBUG_DEVELOPER);
  82                      $fullname = 'question_bank_' . $fullname;
  83                  } else {
  84                      throw new coding_exception('Invalid quiz question bank column', $fullname);
  85                  }
  86              }
  87              $this->requiredcolumns[$fullname] = new $fullname($this);
  88          }
  89          return $this->requiredcolumns;
  90      }
  91  
  92      /**
  93       * Specify the column heading
  94       *
  95       * @return string Column name for the heading
  96       */
  97      protected function heading_column() {
  98          return 'mod_quiz\\question\\bank\\question_name_text_column';
  99      }
 100  
 101      protected function default_sort() {
 102          return array(
 103              'core_question\\bank\\question_type_column' => 1,
 104              'mod_quiz\\question\\bank\\question_name_text_column' => 1,
 105          );
 106      }
 107  
 108      /**
 109       * Let the question bank display know whether the quiz has been attempted,
 110       * hence whether some bits of UI, like the add this question to the quiz icon,
 111       * should be displayed.
 112       * @param bool $quizhasattempts whether the quiz has attempts.
 113       */
 114      public function set_quiz_has_attempts($quizhasattempts) {
 115          $this->quizhasattempts = $quizhasattempts;
 116          if ($quizhasattempts && isset($this->visiblecolumns['addtoquizaction'])) {
 117              unset($this->visiblecolumns['addtoquizaction']);
 118          }
 119      }
 120  
 121      public function preview_question_url($question) {
 122          return quiz_question_preview_url($this->quiz, $question);
 123      }
 124  
 125      public function add_to_quiz_url($questionid) {
 126          global $CFG;
 127          $params = $this->baseurl->params();
 128          $params['addquestion'] = $questionid;
 129          $params['sesskey'] = sesskey();
 130          return new \moodle_url('/mod/quiz/edit.php', $params);
 131      }
 132  
 133      /**
 134       * Renders the html question bank (same as display, but returns the result).
 135       *
 136       * Note that you can only output this rendered result once per page, as
 137       * it contains IDs which must be unique.
 138       *
 139       * @return string HTML code for the form
 140       */
 141      public function render($tabname, $page, $perpage, $cat, $recurse, $showhidden,
 142              $showquestiontext, $tagids = []) {
 143          ob_start();
 144          $this->display($tabname, $page, $perpage, $cat, $recurse, $showhidden, $showquestiontext, $tagids);
 145          $out = ob_get_contents();
 146          ob_end_clean();
 147          return $out;
 148      }
 149  
 150      /**
 151       * Display the controls at the bottom of the list of questions.
 152       * @param int       $totalnumber Total number of questions that might be shown (if it was not for paging).
 153       * @param bool      $recurse     Whether to include subcategories.
 154       * @param \stdClass $category    The question_category row from the database.
 155       * @param \context  $catcontext  The context of the category being displayed.
 156       * @param array     $addcontexts contexts where the user is allowed to add new questions.
 157       */
 158      protected function display_bottom_controls($totalnumber, $recurse, $category, \context $catcontext, array $addcontexts) {
 159          $cmoptions = new \stdClass();
 160          $cmoptions->hasattempts = !empty($this->quizhasattempts);
 161  
 162          $canuseall = has_capability('moodle/question:useall', $catcontext);
 163  
 164          echo '<div class="modulespecificbuttonscontainer">';
 165          if ($canuseall) {
 166  
 167              // Add selected questions to the quiz.
 168              $params = array(
 169                  'type' => 'submit',
 170                  'name' => 'add',
 171                  'class' => 'btn btn-primary',
 172                  'value' => get_string('addselectedquestionstoquiz', 'quiz'),
 173                  'data-action' => 'toggle',
 174                  'data-togglegroup' => 'qbank',
 175                  'data-toggle' => 'action',
 176                  'disabled' => true,
 177              );
 178              echo \html_writer::empty_tag('input', $params);
 179          }
 180          echo "</div>\n";
 181      }
 182  
 183      /**
 184       * Prints a form to choose categories.
 185       * @param string $categoryandcontext 'categoryID,contextID'.
 186       * @deprecated since Moodle 2.6 MDL-40313.
 187       * @see \core_question\bank\search\category_condition
 188       * @todo MDL-41978 This will be deleted in Moodle 2.8
 189       */
 190      protected function print_choose_category_message($categoryandcontext) {
 191          global $OUTPUT;
 192          debugging('print_choose_category_message() is deprecated, ' .
 193                  'please use \core_question\bank\search\category_condition instead.', DEBUG_DEVELOPER);
 194          echo $OUTPUT->box_start('generalbox questionbank');
 195          $this->display_category_form($this->contexts->having_one_edit_tab_cap('edit'),
 196                  $this->baseurl, $categoryandcontext);
 197          echo "<p style=\"text-align:center;\"><b>";
 198          print_string('selectcategoryabove', 'question');
 199          echo "</b></p>";
 200          echo $OUTPUT->box_end();
 201      }
 202  
 203      protected function display_options_form($showquestiontext, $scriptpath = '/mod/quiz/edit.php',
 204              $showtextoption = false) {
 205          // Overridden just to change the default values of the arguments.
 206          parent::display_options_form($showquestiontext, $scriptpath, $showtextoption);
 207      }
 208  
 209      protected function print_category_info($category) {
 210          $formatoptions = new \stdClass();
 211          $formatoptions->noclean = true;
 212          $strcategory = get_string('category', 'quiz');
 213          echo '<div class="categoryinfo"><div class="categorynamefieldcontainer">' .
 214                  $strcategory;
 215          echo ': <span class="categorynamefield">';
 216          echo shorten_text(strip_tags(format_string($category->name)), 60);
 217          echo '</span></div><div class="categoryinfofieldcontainer">' .
 218                  '<span class="categoryinfofield">';
 219          echo shorten_text(strip_tags(format_text($category->info, $category->infoformat,
 220                  $formatoptions, $this->course->id)), 200);
 221          echo '</span></div></div>';
 222      }
 223  
 224      protected function display_options($recurse, $showhidden, $showquestiontext) {
 225          debugging('display_options() is deprecated, see display_options_form() instead.', DEBUG_DEVELOPER);
 226          echo '<form method="get" action="edit.php" id="displayoptions">';
 227          echo "<fieldset class='invisiblefieldset'>";
 228          echo \html_writer::input_hidden_params($this->baseurl,
 229                  array('recurse', 'showhidden', 'qbshowtext'));
 230          $this->display_category_form_checkbox('recurse', $recurse,
 231                  get_string('includesubcategories', 'question'));
 232          $this->display_category_form_checkbox('showhidden', $showhidden,
 233                  get_string('showhidden', 'question'));
 234          echo '<noscript><div class="centerpara"><input type="submit" value="' .
 235                  get_string('go') . '" />';
 236          echo '</div></noscript></fieldset></form>';
 237      }
 238  
 239      protected function create_new_question_form($category, $canadd) {
 240          // Don't display this.
 241      }
 242  
 243      /**
 244       * Override the base implementation in \core_question\bank\view
 245       * because we don't want to print the headers in the fragment
 246       * for the modal.
 247       */
 248      protected function display_question_bank_header() {
 249      }
 250  
 251      /**
 252       * Override the base implementation in \core_question\bank\view
 253       * because we don't want it to read from the $_POST global variables
 254       * for the sort parameters since they are not present in a fragment.
 255       *
 256       * Unfortunately the best we can do is to look at the URL for
 257       * those parameters (only marginally better really).
 258       */
 259      protected function init_sort_from_params() {
 260          $this->sort = [];
 261          for ($i = 1; $i <= self::MAX_SORTS; $i++) {
 262              if (!$sort = $this->baseurl->param('qbs' . $i)) {
 263                  break;
 264              }
 265              // Work out the appropriate order.
 266              $order = 1;
 267              if ($sort[0] == '-') {
 268                  $order = -1;
 269                  $sort = substr($sort, 1);
 270                  if (!$sort) {
 271                      break;
 272                  }
 273              }
 274              // Deal with subsorts.
 275              list($colname, $subsort) = $this->parse_subsort($sort);
 276              $this->requiredcolumns[$colname] = $this->get_column_type($colname);
 277              $this->sort[$sort] = $order;
 278          }
 279      }
 280  }