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 401 and 402] [Versions 401 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  namespace core_search;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  global $CFG;
  22  require_once (__DIR__ . '/fixtures/testable_core_search.php');
  23  require_once (__DIR__ . '/fixtures/mock_search_area.php');
  24  
  25  /**
  26   * Test for top results
  27   *
  28   * @package core_search
  29   * @author  Nathan Nguyen <nathannguyen@catalyst-au.net>
  30   * @copyright  Catalyst IT
  31   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  class top_result_test extends \advanced_testcase {
  34  
  35      /** @var stdClass course 1 */
  36      protected $course1;
  37      /** @var stdClass course 2 */
  38      protected $course2;
  39      /** @var stdClass user 1 */
  40      protected $user1;
  41      /** @var stdClass user 2 */
  42      protected $user2;
  43      /** @var stdClass user 3 */
  44      protected $user3;
  45      /** @var stdClass search engine */
  46      protected $search;
  47  
  48      /**
  49       * Prepare test and users.
  50       */
  51      private function prepare_test_courses_and_users(): void {
  52          global $DB;
  53  
  54          $this->setAdminUser();
  55  
  56          // Search engine.
  57          $this->search = \testable_core_search::instance(new \search_simpledb\engine());
  58  
  59          // Set default configurations.
  60          set_config('searchallavailablecourses', 1);
  61          set_config('searchincludeallcourses', 1);
  62          set_config('searchenablecategories', true);
  63          set_config('enableglobalsearch', true);
  64          set_config('searchmaxtopresults', 3);
  65          $teacher = $DB->get_record('role', ['shortname' => 'teacher']);
  66          $editingteacher = $DB->get_record('role', ['shortname' => 'editingteacher']);
  67          set_config('searchteacherroles', "$teacher->id, $editingteacher->id");
  68  
  69          // Generate test data.
  70          $generator = $this->getDataGenerator();
  71  
  72          // Courses.
  73          $this->course1 = $generator->create_course(['fullname' => 'Top course result 1']);
  74          // Ensure course 1 is indexed before course 2.
  75          $this->run_index();
  76          $this->course2 = $generator->create_course(['fullname' => 'Top course result 2']);
  77  
  78          // User 1.
  79          $urecord1 = new \stdClass();
  80          $urecord1->firstname = "User 1";
  81          $urecord1->lastname = "Test";
  82          $this->user1 = $generator->create_user($urecord1);
  83  
  84          // User 2.
  85          $urecord2 = new \stdClass();
  86          $urecord2->firstname = "User 2";
  87          $urecord2->lastname = "Test";
  88          $this->user2 = $generator->create_user($urecord2);
  89  
  90          // User 3.
  91          $urecord3 = new \stdClass();
  92          $urecord3->firstname = "User 3";
  93          $urecord3->lastname = "Test";
  94          $this->user3 = $generator->create_user($urecord3);
  95      }
  96  
  97      /**
  98       * Test course ranking
  99       */
 100      public function test_search_course_rank(): void {
 101          $this->resetAfterTest();
 102          $this->prepare_test_courses_and_users();
 103          $this->setUser($this->user1);
 104  
 105          // Search query.
 106          $data = new \stdClass();
 107          $data->q = 'Top course result';
 108          $data->cat = 'core-all';
 109  
 110          // Course 1 at the first index.
 111          $this->run_index();
 112          $docs = $this->search->search_top($data);
 113          $this->assertEquals('Top course result 1', $docs[0]->get('title'));
 114          $this->assertEquals('Top course result 2', $docs[1]->get('title'));
 115  
 116          // Enrol user to course 2.
 117          $this->getDataGenerator()->enrol_user($this->user1->id, $this->course2->id, 'student');
 118  
 119          // Course 2 at the first index.
 120          $this->run_index();
 121          $docs = $this->search->search_top($data);
 122          $this->assertEquals('Top course result 2', $docs[0]->get('title'));
 123          $this->assertEquals('Top course result 1', $docs[1]->get('title'));
 124      }
 125  
 126      /**
 127       * Test without teacher indexing
 128       */
 129      public function test_search_with_no_course_teacher_indexing(): void {
 130          $this->resetAfterTest();
 131          $this->prepare_test_courses_and_users();
 132          set_config('searchteacherroles', "");
 133          $this->getDataGenerator()->enrol_user($this->user1->id, $this->course1->id, 'teacher');
 134  
 135          // Search query.
 136          $data = new \stdClass();
 137          $data->q = 'Top course result';
 138          $data->cat = 'core-all';
 139  
 140          // Only return the course.
 141          $this->run_index();
 142          $docs = $this->search->search_top($data);
 143          $this->assertCount(2, $docs);
 144          $this->assertEquals('Top course result 1', $docs[0]->get('title'));
 145          $this->assertEquals('Top course result 2', $docs[1]->get('title'));
 146      }
 147  
 148      /**
 149       * Test with teacher indexing
 150       */
 151      public function test_search_with_course_teacher_indexing(): void {
 152          $this->resetAfterTest();
 153          $this->prepare_test_courses_and_users();
 154  
 155          $this->getDataGenerator()->enrol_user($this->user1->id, $this->course1->id, 'teacher');
 156          $this->getDataGenerator()->enrol_user($this->user2->id, $this->course1->id, 'student');
 157  
 158          // Search query.
 159          $data = new \stdClass();
 160          $data->q = 'Top course result 1';
 161          $data->cat = 'core-all';
 162  
 163          // Return the course and the teachers.
 164          $this->run_index();
 165          $docs = $this->search->search_top($data);
 166          $this->assertEquals('Top course result 1', $docs[0]->get('title'));
 167          $this->assertEquals('User 1 Test', $docs[1]->get('title'));
 168      }
 169  
 170      /**
 171       * Test with teacher indexing
 172       */
 173      public function test_search_with_course_teacher_content_indexing(): void {
 174          $this->resetAfterTest();
 175          $this->prepare_test_courses_and_users();
 176  
 177          // Create forums as course content.
 178          $generator = $this->getDataGenerator();
 179  
 180          // Course Teacher.
 181          $this->getDataGenerator()->enrol_user($this->user1->id, $this->course1->id, 'teacher');
 182  
 183          // Forums.
 184          $generator->create_module('forum',
 185              ['course' => $this->course1->id, 'name' => 'Forum 1,  does not contain the keyword']);
 186          $generator->create_module('forum',
 187              ['course' => $this->course2->id, 'name' => 'Forum 2, contains keyword Top course result 1']);
 188  
 189          $this->run_index();
 190  
 191          // Search query.
 192          $data = new \stdClass();
 193          $data->q = 'Top course result 1';
 194          $data->cat = 'core-all';
 195  
 196          // Return the course and the teacher and the forum.
 197          $docs = $this->search->search_top($data);
 198          $this->assertEquals('Top course result 1', $docs[0]->get('title'));
 199          $this->assertEquals('User 1 Test', $docs[1]->get('title'));
 200          $this->assertEquals('Forum 2, contains keyword Top course result 1', $docs[2]->get('title'));
 201      }
 202  
 203      /**
 204       * Execute indexing
 205       */
 206      private function run_index(): void {
 207          // Indexing.
 208          $this->waitForSecond();
 209          $this->search->index(false, 0);
 210      }
 211  }