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 39 and 401]

   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_message;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  global $CFG;
  22  require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
  23  
  24  /**
  25   * Provides the unit tests for sent message global search.
  26   *
  27   * @package     core_message
  28   * @copyright   2016 Devang Gaur
  29   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   */
  31  class search_sent_test extends \advanced_testcase {
  32  
  33      /**
  34       * @var string Area id
  35       */
  36      protected $messagesentareaid = null;
  37  
  38      /**
  39       * Setting up the test environment
  40       * @return void
  41       */
  42      public function setUp(): void {
  43          $this->resetAfterTest(true);
  44          set_config('enableglobalsearch', true);
  45  
  46          $this->messagesentareaid = \core_search\manager::generate_areaid('core_message', 'message_sent');
  47  
  48          // Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this.
  49          $search = \testable_core_search::instance();
  50      }
  51  
  52      /**
  53       * Indexing messages contents.
  54       *
  55       * @return void
  56       */
  57      public function test_message_sent_indexing() {
  58  
  59          // Returns the instance as long as the area is supported.
  60          $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
  61          $this->assertInstanceOf('\core_message\search\message_sent', $searcharea);
  62  
  63          $user1 = self::getDataGenerator()->create_user();
  64          $user2 = self::getDataGenerator()->create_user();
  65  
  66          $this->preventResetByRollback();
  67          $sink = $this->redirectMessages();
  68  
  69          $message = new \core\message\message();
  70          $message->courseid = SITEID;
  71          $message->userfrom = $user1;
  72          $message->userto = $user2;
  73          $message->subject = "Test Subject";
  74          $message->smallmessage = "Test small messsage";
  75          $message->fullmessage = "Test full messsage";
  76          $message->fullmessageformat = 0;
  77          $message->fullmessagehtml = null;
  78          $message->notification = 0;
  79          $message->component = 'moodle';
  80          $message->name = "instantmessage";
  81  
  82          message_send($message);
  83  
  84          $messages = $sink->get_messages();
  85  
  86          $this->assertEquals(1, count($messages));
  87  
  88          // All records.
  89          $recordset = $searcharea->get_recordset_by_timestamp(0);
  90          $this->assertTrue($recordset->valid());
  91          $nrecords = 0;
  92          foreach ($recordset as $record) {
  93              $this->assertInstanceOf('stdClass', $record);
  94              $doc = $searcharea->get_document($record);
  95              $this->assertInstanceOf('\core_search\document', $doc);
  96              $nrecords++;
  97          }
  98          // If there would be an error/failure in the foreach above the recordset would be closed on shutdown.
  99          $recordset->close();
 100          $this->assertEquals(1, $nrecords);
 101  
 102          // The +2 is to prevent race conditions.
 103          $recordset = $searcharea->get_recordset_by_timestamp(time() + 2);
 104  
 105          // No new records.
 106          $this->assertFalse($recordset->valid());
 107          $recordset->close();
 108      }
 109  
 110      /**
 111       * Indexing messages, with restricted contexts.
 112       */
 113      public function test_message_sent_indexing_contexts() {
 114          global $SITE;
 115  
 116          $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
 117  
 118          $user1 = self::getDataGenerator()->create_user();
 119          $user2 = self::getDataGenerator()->create_user();
 120  
 121          $this->preventResetByRollback();
 122          $sink = $this->redirectMessages();
 123  
 124          // Send first message.
 125          $message = new \core\message\message();
 126          $message->courseid = SITEID;
 127          $message->userfrom = $user1;
 128          $message->userto = $user2;
 129          $message->subject = 'Test1';
 130          $message->smallmessage = 'Test small messsage';
 131          $message->fullmessage = 'Test full messsage';
 132          $message->fullmessageformat = 0;
 133          $message->fullmessagehtml = null;
 134          $message->notification = 0;
 135          $message->component = 'moodle';
 136          $message->name = 'instantmessage';
 137          message_send($message);
 138  
 139          // Ensure that ordering by timestamp will return in consistent order.
 140          $this->waitForSecond();
 141  
 142          // Send second message in opposite direction.
 143          $message = new \core\message\message();
 144          $message->courseid = SITEID;
 145          $message->userfrom = $user2;
 146          $message->userto = $user1;
 147          $message->subject = 'Test2';
 148          $message->smallmessage = 'Test small messsage';
 149          $message->fullmessage = 'Test full messsage';
 150          $message->fullmessageformat = 0;
 151          $message->fullmessagehtml = null;
 152          $message->notification = 0;
 153          $message->component = 'moodle';
 154          $message->name = 'instantmessage';
 155          message_send($message);
 156  
 157          // Test function with null context and system context (same).
 158          $rs = $searcharea->get_document_recordset(0, null);
 159          $this->assertEquals(['Test1', 'Test2'], self::recordset_to_subjects($rs));
 160          $rs = $searcharea->get_document_recordset(0, \context_system::instance());
 161          $this->assertEquals(['Test1', 'Test2'], self::recordset_to_subjects($rs));
 162  
 163          // Test with user context for each user.
 164          $rs = $searcharea->get_document_recordset(0, \context_user::instance($user1->id));
 165          $this->assertEquals(['Test1'], self::recordset_to_subjects($rs));
 166          $rs = $searcharea->get_document_recordset(0, \context_user::instance($user2->id));
 167          $this->assertEquals(['Test2'], self::recordset_to_subjects($rs));
 168  
 169          // Test with a course context (should return null).
 170          $this->assertNull($searcharea->get_document_recordset(0,
 171                  \context_course::instance($SITE->id)));
 172      }
 173  
 174      /**
 175       * Utility function to convert recordset to array of message subjects for testing.
 176       *
 177       * @param moodle_recordset $rs Recordset to convert (and close)
 178       * @return array Array of IDs from records indexed by number (0, 1, 2, ...)
 179       */
 180      public static function recordset_to_subjects(\moodle_recordset $rs) {
 181          $results = [];
 182          foreach ($rs as $rec) {
 183              $results[] = $rec->subject;
 184          }
 185          $rs->close();
 186          return $results;
 187      }
 188  
 189      /**
 190       * Document contents.
 191       *
 192       * @return void
 193       */
 194      public function test_message_sent_document() {
 195  
 196          // Returns the instance as long as the area is supported.
 197          $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
 198          $this->assertInstanceOf('\core_message\search\message_sent', $searcharea);
 199  
 200          $user1 = self::getDataGenerator()->create_user();
 201          $user2 = self::getDataGenerator()->create_user();
 202  
 203          $this->preventResetByRollback();
 204          $sink = $this->redirectMessages();
 205  
 206          $message = new \core\message\message();
 207          $message->courseid = SITEID;
 208          $message->userfrom = $user1;
 209          $message->userto = $user2;
 210          $message->subject = "Test Subject";
 211          $message->smallmessage = "Test small messsage";
 212          $message->fullmessage = "Test full messsage";
 213          $message->fullmessageformat = 0;
 214          $message->fullmessagehtml = null;
 215          $message->notification = 0;
 216          $message->component = "moodle";
 217          $message->name = "instantmessage";
 218  
 219          message_send($message);
 220  
 221          $messages = $sink->get_messages();
 222          $message = $messages[0];
 223  
 224          $doc = $searcharea->get_document($message);
 225          $this->assertInstanceOf('\core_search\document', $doc);
 226          $this->assertEquals($message->id, $doc->get('itemid'));
 227          $this->assertEquals($this->messagesentareaid . '-' . $message->id, $doc->get('id'));
 228          $this->assertEquals(SITEID, $doc->get('courseid'));
 229          $this->assertEquals($message->useridfrom, $doc->get('owneruserid'));
 230          $this->assertEquals($message->useridto, $doc->get('userid'));
 231          $this->assertEquals(content_to_text($message->subject, false), $doc->get('title'));
 232          $this->assertEquals(content_to_text($message->smallmessage, false), $doc->get('content'));
 233      }
 234  
 235      /**
 236       * Document accesses.
 237       *
 238       * @return void
 239       */
 240      public function test_message_sent_access() {
 241          global $CFG;
 242  
 243          // Returns the instance as long as the area is supported.
 244          $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
 245  
 246          $user1 = self::getDataGenerator()->create_user();
 247          $user2 = self::getDataGenerator()->create_user();
 248          $user3 = self::getDataGenerator()->create_user();
 249  
 250          $this->preventResetByRollback();
 251          $sink = $this->redirectMessages();
 252  
 253          $message = new \core\message\message();
 254          $message->courseid = SITEID;
 255          $message->userfrom = $user1;
 256          $message->userto = $user2;
 257          $message->subject = "Test Subject";
 258          $message->smallmessage = "Test small messsage";
 259          $message->fullmessage = "Test full messsage";
 260          $message->fullmessageformat = 0;
 261          $message->fullmessagehtml = null;
 262          $message->notification = 0;
 263          $message->component = "moodle";
 264          $message->name = "instantmessage";
 265  
 266          $messageid = message_send($message);
 267  
 268          $messages = $sink->get_messages();
 269          $message = $messages[0];
 270  
 271          $this->setUser($user1);
 272  
 273          if ($CFG->messaging) {
 274              $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($messageid));
 275          } else {
 276              $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
 277          }
 278  
 279          $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-123));
 280  
 281          \core_message\api::delete_message($user1->id, $message->id);
 282          $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access($messageid));
 283  
 284          $this->setUser($user2);
 285          $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
 286  
 287          $this->setUser($user3);
 288          $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
 289  
 290          $this->setGuestUser();
 291          $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
 292  
 293          $this->setAdminUser();
 294          $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($messageid));
 295  
 296          delete_user($user2);
 297  
 298          $this->setUser($user1);
 299          $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access($messageid));
 300  
 301      }
 302  
 303      /**
 304       * Test sent deleted user.
 305       * Tests the case where a sent message for a deleted user
 306       * is attempted to be added to the index.
 307       *
 308       * @return void
 309       */
 310      public function test_message_sent_deleted_user() {
 311  
 312          // Returns the instance as long as the area is supported.
 313          $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
 314          $this->assertInstanceOf('\core_message\search\message_sent', $searcharea);
 315  
 316          $user1 = self::getDataGenerator()->create_user();
 317          $user2 = self::getDataGenerator()->create_user();
 318  
 319          $this->preventResetByRollback();
 320          $sink = $this->redirectMessages();
 321  
 322          $message = new \core\message\message();
 323          $message->courseid = SITEID;
 324          $message->userfrom = $user1;
 325          $message->userto = $user2;
 326          $message->subject = "Test Subject";
 327          $message->smallmessage = "Test small messsage";
 328          $message->fullmessage = "Test full messsage";
 329          $message->fullmessageformat = 0;
 330          $message->fullmessagehtml = null;
 331          $message->notification = 0;
 332          $message->component = "moodle";
 333          $message->name = "instantmessage";
 334  
 335          message_send($message);
 336  
 337          $messages = $sink->get_messages();
 338          $message = $messages[0];
 339  
 340          // Delete user.
 341          delete_user($user1);
 342  
 343          $doc = $searcharea->get_document($message);
 344  
 345          $this->assertFalse($doc);
 346  
 347      }
 348  
 349      /**
 350       * Test document icon.
 351       */
 352      public function test_get_doc_icon() {
 353          $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
 354  
 355          $document = $this->getMockBuilder('\core_search\document')
 356              ->disableOriginalConstructor()
 357              ->getMock();
 358  
 359          $result = $searcharea->get_doc_icon($document);
 360  
 361          $this->assertEquals('t/message', $result->get_name());
 362          $this->assertEquals('moodle', $result->get_component());
 363      }
 364  
 365      /**
 366       * Test assigned search categories.
 367       */
 368      public function test_get_category_names() {
 369          $searcharea = \core_search\manager::get_search_area($this->messagesentareaid);
 370  
 371          $expected = ['core-users'];
 372          $this->assertEquals($expected, $searcharea->get_category_names());
 373      }
 374  }