From 7dc0db71952a80f868145fa94c1ac0124f8c531c Mon Sep 17 00:00:00 2001 From: Devang Gaur Date: Thu, 30 Jun 2016 00:50:53 +0530 Subject: [PATCH] MDL-54794 user: added Users to globalsearch --- lang/en/search.php | 1 + user/classes/search/user.php | 123 +++++++++++++++++++++++ user/tests/search_test.php | 189 +++++++++++++++++++++++++++++++++++ 3 files changed, 313 insertions(+) create mode 100644 user/classes/search/user.php create mode 100644 user/tests/search_test.php diff --git a/lang/en/search.php b/lang/en/search.php index c7219ec99d613..bfe296c2847d8 100644 --- a/lang/en/search.php +++ b/lang/en/search.php @@ -81,6 +81,7 @@ $string['score'] = 'Score'; $string['search'] = 'Search'; $string['search:mycourse'] = 'My courses'; +$string['search:user'] = 'Users'; $string['searcharea'] = 'Search area'; $string['searching'] = 'Searching in ...'; $string['searchnotpermitted'] = 'You are not allowed to do a search'; diff --git a/user/classes/search/user.php b/user/classes/search/user.php new file mode 100644 index 0000000000000..b51ed8e6097e2 --- /dev/null +++ b/user/classes/search/user.php @@ -0,0 +1,123 @@ +. + +/** + * Search area for Users for whom I have authority to view profile. + * + * @package core_user + * @copyright 2016 Devang Gaur {@link http://www.devanggaur.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core_user\search; + +require_once($CFG->dirroot . '/user/lib.php'); + +defined('MOODLE_INTERNAL') || die(); + +/** + * Search area for Users for whom I have access to view profile. + * + * @package core_user + * @copyright 2016 Devang Gaur {@link http://www.devanggaur.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class user extends \core_search\area\base { + + /** + * Returns recordset containing required data attributes for indexing. + * + * @param number $modifiedfrom + * @return \moodle_recordset + */ + public function get_recordset_by_timestamp($modifiedfrom = 0) { + global $DB; + return $DB->get_recordset_select('user', 'timemodified >= ? AND deleted = ? AND + confirmed = ?', array($modifiedfrom, 0, 1)); + } + + /** + * Returns document instances for each record in the recordset. + * + * @param StdClass $record + * @param array $options + * @return core_search/document + */ + public function get_document($record, $options = array()) { + + $context = \context_system::instance(); + + // Prepare associative array with data from DB. + $doc = \core_search\document_factory::instance($record->id, $this->componentname, $this->areaname); + // Assigning properties to our document. + $doc->set('title', content_to_text(fullname($record), false)); + $doc->set('contextid', $context->id); + $doc->set('courseid', SITEID); + $doc->set('itemid', $record->id); + $doc->set('modified', $record->timemodified); + $doc->set('owneruserid', \core_search\manager::NO_OWNER_ID); + $doc->set('content', content_to_text($record->description, $record->descriptionformat)); + + // Check if this document should be considered new. + if (isset($options['lastindexedtime']) && $options['lastindexedtime'] < $record->timecreated) { + // If the document was created after the last index time, it must be new. + $doc->set_is_new(true); + } + + return $doc; + } + + /** + * Checking whether I can access a document + * + * @param int $id user id + * @return int + */ + public function check_access($id) { + global $DB, $USER; + + $user = $DB->get_record('user', array('id' => $id)); + if (!$user || $user->deleted) { + return \core_search\manager::ACCESS_DELETED; + } + + if (user_can_view_profile($user)) { + return \core_search\manager::ACCESS_GRANTED; + } + + return \core_search\manager::ACCESS_DENIED; + } + + /** + * Returns a url to the profile page of user. + * + * @param \core_search\document $doc + * @return moodle_url + */ + public function get_doc_url(\core_search\document $doc) { + return $this->get_context_url($doc); + } + + /** + * Returns a url to the document context. + * + * @param \core_search\document $doc + * @return moodle_url + */ + public function get_context_url(\core_search\document $doc) { + return new \moodle_url('/user/profile.php', array('id' => $doc->get('itemid'))); + } +} diff --git a/user/tests/search_test.php b/user/tests/search_test.php new file mode 100644 index 0000000000000..371185bb5a763 --- /dev/null +++ b/user/tests/search_test.php @@ -0,0 +1,189 @@ +. + +/** + * Course global search unit tests. + * + * @package core + * @copyright 2016 Devang Gaur {@link http://www.devanggaur.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php'); + +/** + * Provides the unit tests for course global search. + * + * @package core + * @copyright 2016 Devang Gaur {@link http://www.davidmonllao.com} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class user_search_testcase extends advanced_testcase { + + /** + * @var string Area id + */ + protected $userareaid = null; + + public function setUp() { + $this->resetAfterTest(true); + set_config('enableglobalsearch', true); + + $this->userareaid = \core_search\manager::generate_areaid('core_user', 'user'); + + // Set \core_search::instance to the mock_search_engine as we don't require the search engine to be working to test this. + $search = testable_core_search::instance(); + } + + /** + * Indexing users contents. + * + * @return void + */ + public function test_users_indexing() { + + // Returns the instance as long as the area is supported. + $searcharea = \core_search\manager::get_search_area($this->userareaid); + $this->assertInstanceOf('\core_user\search\user', $searcharea); + + $user1 = self::getDataGenerator()->create_user(); + $user2 = self::getDataGenerator()->create_user(); + + // All records. + // Recordset will produce 4 user records: + // Guest User, Admin User and two above generated users. + $recordset = $searcharea->get_recordset_by_timestamp(0); + $this->assertTrue($recordset->valid()); + $nrecords = 0; + foreach ($recordset as $record) { + $this->assertInstanceOf('stdClass', $record); + $doc = $searcharea->get_document($record); + $this->assertInstanceOf('\core_search\document', $doc); + $nrecords++; + } + // If there would be an error/failure in the foreach above the recordset would be closed on shutdown. + $recordset->close(); + $this->assertEquals(4, $nrecords); + + // The +2 is to prevent race conditions. + $recordset = $searcharea->get_recordset_by_timestamp(time() + 2); + + // No new records. + $this->assertFalse($recordset->valid()); + $recordset->close(); + } + + /** + * Document contents. + * + * @return void + */ + public function test_users_document() { + + // Returns the instance as long as the area is supported. + $searcharea = \core_search\manager::get_search_area($this->userareaid); + $this->assertInstanceOf('\core_user\search\user', $searcharea); + + $user = self::getDataGenerator()->create_user(); + + $doc = $searcharea->get_document($user); + $this->assertInstanceOf('\core_search\document', $doc); + $this->assertEquals($user->id, $doc->get('itemid')); + $this->assertEquals($this->userareaid . '-' . $user->id, $doc->get('id')); + $this->assertEquals(SITEID, $doc->get('courseid')); + $this->assertFalse($doc->is_set('userid')); + $this->assertEquals(\core_search\manager::NO_OWNER_ID, $doc->get('owneruserid')); + $this->assertEquals(content_to_text(fullname($user), false), $doc->get('title')); + $this->assertEquals(content_to_text($user->description, $user->descriptionformat), $doc->get('content')); + } + + /** + * Document accesses. + * + * @return void + */ + public function test_users_access() { + + // Returns the instance as long as the area is supported. + $searcharea = \core_search\manager::get_search_area($this->userareaid); + + $user1 = self::getDataGenerator()->create_user(); + $user2 = self::getDataGenerator()->create_user(); + $user3 = self::getDataGenerator()->create_user(); + $user4 = self::getDataGenerator()->create_user(); + + $deleteduser = self::getDataGenerator()->create_user(array('deleted' => 1)); + $unconfirmeduser = self::getDataGenerator()->create_user(array('confirmed' => 0)); + $suspendeduser = self::getDataGenerator()->create_user(array('suspended' => 1)); + + $course1 = self::getDataGenerator()->create_course(); + $course2 = self::getDataGenerator()->create_course(); + + $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id)); + $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course1->id)); + + $this->getDataGenerator()->enrol_user($user1->id, $course1->id, 'teacher'); + $this->getDataGenerator()->enrol_user($user2->id, $course1->id, 'student'); + $this->getDataGenerator()->enrol_user($user2->id, $course2->id, 'student'); + $this->getDataGenerator()->enrol_user($user3->id, $course2->id, 'student'); + $this->getDataGenerator()->enrol_user($user4->id, $course2->id, 'student'); + $this->getDataGenerator()->enrol_user($suspendeduser->id, $course1->id, 'student'); + + $this->getDataGenerator()->create_group_member(array('userid' => $user2->id, 'groupid' => $group1->id)); + $this->getDataGenerator()->create_group_member(array('userid' => $user3->id, 'groupid' => $group1->id)); + $this->getDataGenerator()->create_group_member(array('userid' => $user4->id, 'groupid' => $group2->id)); + + $this->setAdminUser(); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user1->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user2->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user3->id)); + $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access($deleteduser->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($unconfirmeduser->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($suspendeduser->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access(2)); + + $this->setUser($user1); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user1->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user2->id)); + $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($user3->id)); + $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($user4->id)); + $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access(1));// Guest user can't be accessed. + $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access(2));// Admin user can't be accessed. + $this->assertEquals(\core_search\manager::ACCESS_DELETED, $searcharea->check_access(-123)); + $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($unconfirmeduser->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($suspendeduser->id)); + + $this->setUser($user2); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user1->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user2->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user3->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user4->id)); + + $this->setUser($user3); + $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($user1->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user2->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user3->id)); + $this->assertEquals(\core_search\manager::ACCESS_DENIED, $searcharea->check_access($suspendeduser->id)); + + $this->setGuestUser(); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user1->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user2->id)); + $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $searcharea->check_access($user3->id)); + } +} \ No newline at end of file