Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 402]

   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 condition for adding filtering by tag to the question bank.
  19   *
  20   * @package   core_question
  21   * @copyright 2018 Ryan Wyllie <ryan@moodle.com>
  22   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  namespace core_question\bank\search;
  26  
  27  /**
  28   * Question bank search class to allow searching/filtering by tags on a question.
  29   *
  30   * @copyright 2018 Ryan Wyllie <ryan@moodle.com>
  31   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  class tag_condition extends condition {
  34  
  35      /** @var string SQL fragment to add to the where clause. */
  36      protected $where;
  37  
  38      /** @var string SQL fragment to add to the where clause. */
  39      protected $contexts;
  40  
  41      /** @var array List of IDs for tags that have been selected in the form. */
  42      protected $selectedtagids;
  43  
  44      /**
  45       * Constructor.
  46       *
  47       * @param array $contexts List of contexts to show tags from
  48       * @param int[] $selectedtagids List of IDs for tags to filter by.
  49       * @throws \coding_exception
  50       * @throws \dml_exception
  51       */
  52      public function __construct(array $contexts, array $selectedtagids = []) {
  53          global $DB;
  54  
  55          $this->contexts = $contexts;
  56  
  57          // If some tags have been selected then we need to filter
  58          // the question list by the selected tags.
  59          if ($selectedtagids) {
  60              // We treat each additional tag as an AND condition rather than
  61              // an OR condition.
  62              //
  63              // For example, if the user filters by the tags "foo" and "bar" then
  64              // we reduce the question list to questions that are tagged with both
  65              // "foo" AND "bar". Any question that does not have ALL of the specified
  66              // tags will be omitted.
  67              list($tagsql, $tagparams) = $DB->get_in_or_equal($selectedtagids, SQL_PARAMS_NAMED);
  68              $tagparams['tagcount'] = count($selectedtagids);
  69              $tagparams['questionitemtype'] = 'question';
  70              $tagparams['questioncomponent'] = 'core_question';
  71              $this->selectedtagids = $selectedtagids;
  72              $this->params = $tagparams;
  73              $this->where = "q.id IN (SELECT ti.itemid
  74                                         FROM {tag_instance} ti
  75                                        WHERE ti.itemtype = :questionitemtype
  76                                              AND ti.component = :questioncomponent
  77                                              AND ti.tagid {$tagsql}
  78                                     GROUP BY ti.itemid
  79                                       HAVING COUNT(itemid) = :tagcount)";
  80  
  81          } else {
  82              $this->selectedtagids = [];
  83              $this->params = [];
  84              $this->where = '';
  85          }
  86      }
  87  
  88      /**
  89       * Get the SQL WHERE snippet to be used in the SQL to retrieve the
  90       * list of questions. This SQL snippet will add the logic for the
  91       * tag condition.
  92       *
  93       * @return string
  94       */
  95      public function where() {
  96          return $this->where;
  97      }
  98  
  99      /**
 100       * Named SQL params to be used with the SQL WHERE snippet.
 101       *
 102       * @return array
 103       */
 104      public function params() {
 105          return $this->params;
 106      }
 107  
 108      /**
 109       * Print HTML to display the list of tags to filter by.
 110       */
 111      public function display_options() {
 112          global $OUTPUT;
 113  
 114          $tags = \core_tag_tag::get_tags_by_area_in_contexts('core_question', 'question', $this->contexts);
 115          $tagoptions = array_map(function($tag) {
 116              return [
 117                  'id' => $tag->id,
 118                  'name' => $tag->name,
 119                  'selected' => in_array($tag->id, $this->selectedtagids)
 120              ];
 121          }, array_values($tags));
 122          $context = [
 123              'tagoptions' => $tagoptions
 124          ];
 125  
 126          return $OUTPUT->render_from_template('core_question/tag_condition', $context);
 127      }
 128  }