/** * Tests the get_year_for_tables function. */ public function test_get_year_for_tables() { $this->resetAfterTest(); // Create a couple of courses for testing. $course1 = $this->getDataGenerator()->create_course(array('startdate' => strtotime('2013-01-04 10:00'))); $course2 = $this->getDataGenerator()->create_course(array('startdate' => strtotime('2020-01-04 10:00'))); $course3 = $this->getDataGenerator()->create_course(array('startdate' => strtotime('2021-01-04 10:00'))); // System not turned on. $this->assertFalse(year_tables::get_year_for_tables()); // System turned on, initially transferring. Test with course and no course. set_config(year_tables::CONFIG_ENABLED, year_tables::ENABLED_TRANSFERRING, 'local_ousearch'); $this->assertFalse(year_tables::get_year_for_tables()); $this->assertFalse(year_tables::get_year_for_tables($course1)); // If any course is transferring, the non-course ones will return default. set_config(year_tables::CONFIG_TRANSFERRING_COURSE, $course1->id, 'local_ousearch'); $this->assertEquals(year_tables::NON_COURSE_YEAR, year_tables::get_year_for_tables()); $this->assertFalse(year_tables::get_year_for_tables($course1)); // Once course 1 is finished, course 2 will still return false and course 1 // should return its year. set_config(year_tables::CONFIG_TRANSFERRING_COURSE, $course2->id, 'local_ousearch'); $this->assertEquals(2013, year_tables::get_year_for_tables($course1)); $this->assertFalse(year_tables::get_year_for_tables($course2)); // Now we'll set it to mark that everything was transferred. set_config(year_tables::CONFIG_ENABLED, year_tables::ENABLED_ON, 'local_ousearch'); unset_config(year_tables::CONFIG_TRANSFERRING_COURSE, 'local_ousearch'); // 2020 should show a warning that we're running out of tables. $this->assertEquals(2020, year_tables::get_year_for_tables($course2)); $this->assertEquals(1, count(phpunit_util::get_debugging_messages())); phpunit_util::reset_debugging(); // 2021 should throw exception. try { year_tables::get_year_for_tables($course3); $this->fail(); } catch (moodle_exception $e) { $this->assertContains('start date beyond that supported by the OU search system', $e->getMessage()); } }
/** * Runs actual query and obtains results. * * @param int $dbstart Start position within database results (because * postprocessing is done which filters out some results, this might * not be the same as the number of results shown previously) * @param int $desired Number of desired results to return * @return stdClass Result object. Parameters ->success, then * ->dbstart and ->results and ->dbrows if success is true, or * ->problemword otherwise. */ public function query($dbstart = 0, $desired = 10) { $return = new StdClass(); // Work out the year for search. if ($this->courseid) { $course = get_course($this->courseid); $year = year_tables::get_year_for_tables($course); } else { // Non-course searches are not allowed when using year tables. if (year_tables::is_partially_or_fully_enabled()) { throw new coding_exception('When using year tables, whole-site searches are not permitted'); } $year = false; } // Translate words to IDs. list($ok, $problemword) = $this->internal_translate_words(); if (!$ok) { $return->success = false; $return->problemword = $problemword; return $return; } // Initially assume that 1 in 2 results will pass filters, if there // are any terms that will require filters. $filters = false; foreach ($this->terms as $term) { if (count($term->ids) > 1) { $filters = true; break; } } if (!$filters) { foreach ($this->negativeterms as $term) { if (count($term->ids) > 1) { $filters = true; break; } } } $sparsity = $filters ? 2 : 1; // Obtain results. $totalrequested = 0; $totalgot = 0; $results = array(); while (count($results) < $desired) { // Request a number of results. $left = $desired - count($results); $dbrequest = $left * $sparsity; if ($dbrequest > 1000) { $dbrequest = 1000; } $dbresults = $this->internal_query($dbstart, $dbrequest, $year); $filtered = $this->internal_filter($dbresults, $left); $results = array_merge($results, $filtered->results); $dbstart += $filtered->dbnext; // If we're out of database results, stop now. if (count($dbresults) < $dbrequest) { $totalrequested += count($dbresults); break; } // We still have DB results. Update sparsity value if available. $totalrequested += $dbrequest; $totalgot += count($filtered->results); if ($totalgot > 0) { $sparsity = $totalrequested / $totalgot; } else { $sparsity = 20; // Request loads! } } $return->success = true; $return->dbstart = $dbstart; $return->results = $results; $return->dbrows = $totalrequested; return $return; }
/** * Gets list of course-modules on the course which have search documents * and for which the user has accessallgroups OR the item is set to * visible groups. * @param int $courseid Course ID to check * @return array Array of course_module objects (id, course only) */ public static function get_group_exceptions($courseid) { global $DB; $year = year_tables::get_year_for_tables(get_course($courseid)); $docstable = year_tables::get_docs_table($year); // Get all CMs that have a document. $possible = $DB->get_records_sql("\n SELECT DISTINCT cm.id AS cmid, cm.course AS cmcourse, cm.groupmode AS cmgroupmode, x.*\n FROM {" . $docstable . "} bod\n JOIN {course_modules} cm ON bod.coursemoduleid = cm.id\n JOIN {context} x ON x.instanceid = cm.id AND x.contextlevel = " . CONTEXT_MODULE . "\n WHERE bod.courseid = ?", array($courseid)); // Check accessallgroups on each one. $results = array(); foreach ($possible as $record) { if ($record->cmgroupmode == VISIBLEGROUPS || has_capability('moodle/site:accessallgroups', context_course::instance($record->cmcourse))) { $results[] = (object) array('id' => $record->cmid, 'course' => $record->cmcourse); } } return $results; }